vue3写一个超炫酷的管理系统布局

6,444 阅读2分钟

昨天在primeui的模板市场看到了一个管理系统模板,看着很炫酷,但是这个模板不是免费的,下面我用tailwindcss实现以下这个布局。

image.png

image.png

其实,实现这样的布局很简单,关键的是内阴影和左上角的圆角边框。
我会分成头部导航Navbar.vueSidebar.vueMain.vue等三个组件,分别实现这个布局。

image.png

1.首先我们写一下html,bocy,app的样式:
下面是style.css,就是放tailwindcss样式的地方:

@tailwind base;
@tailwind components;
@tailwind utilities;

html {
    font-size: 16px;
    @apply min-h-screen;
}

body {
    @apply min-h-screen;
}

/*因为app是包裹整个应用程序的容器,所以这里需要设置*/
#app {
    @apply min-h-screen;
}

2.app的vue中的代码:

<script setup>
import Navbar from './components/Navbar.vue'
import Sidebar from './components/Sidebar.vue'
import Main from './components/Main.vue'
</script>

<template>
  <Navbar />
  <Sidebar />
  <Main />
</template>

3.Navbar.vue组件:

<script setup>
import emitter from '../utils/emitter.js'
import { ref } from 'vue'

const isSidebarOpen = ref(false)
const toggleSidebar = () => {
  isSidebarOpen.value =!isSidebarOpen.value
  emitter.emit('toggle-sidebar')
}
</script>

<template>
  <nav class="fixed top-0 left-0 right-0 h-16 bg-white">
    <div class="px-8 h-full flex justify-between items-center">
      <!-- Navbar 左侧 -->
      <div class="flex items-center">
        <h1 class="text-2xl font-bold text-gray-800">Ablog</h1>
        <button
            @click="toggleSidebar"
            class="ml-6 p-3 rounded-full hover:bg-gray-200 transition-colors"
        >
          <svg t="1732184020779" class="fill-slate-700 h-6 w-6" viewBox="0 0 1109 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="28259"><path d="M0.000427 512a85.333333 85.333333 0 0 1 85.205333-85.333333h938.922667c47.061333 0 85.205333 38.186667 85.205333 85.333333a85.333333 85.333333 0 0 1-85.205333 85.333333H85.20576A85.077333 85.077333 0 0 1 0.000427 512zM0.000427 85.333333C0.000427 38.186667 38.10176 0 84.992427 0h470.016C601.94176 0 640.000427 37.888 640.000427 85.333333c0 47.146667-38.101333 85.333333-84.992 85.333334H84.992427C38.059093 170.666667 0.000427 132.778667 0.000427 85.333333z m469.333333 853.333334c0-47.146667 38.101333-85.333333 84.992-85.333334h470.016c46.933333 0 84.992 37.888 84.992 85.333334 0 47.146667-38.101333 85.333333-84.992 85.333333H554.32576c-46.933333 0-84.992-37.888-84.992-85.333333z" p-id="28260"></path></svg>
        </button>
      </div>

      <!-- Navbar 右侧 -->
      <img
          class="w-11 h-11 rounded-lg object-cover"
          src="https://primefaces.org/cdn/primevue/images/organization/walter.jpg"
      />
    </div>
  </nav>

  <!-- 占位符,这样在Main.vue中不需要进行处理Navbar下面的空间 -->
  <div class="h-16"></div>
</template>

因为侧边栏Sidebar的展开和折叠是通过Navbar.vue中的按钮来实现,所以需要实现兄弟组件之间通信,我使用mitt实现了兄弟组件之间的通信。
emitter.js

import mitt from 'mitt'

// 兄弟组件之间通信的事件中心
const emitter = mitt()

export default emitter

4.Sidebar.vue组件:
sidebar.vue中需要监听由Navbar.vue抛出来的事件toggle-sidebar。然后侧边栏的宽度动态变化

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import emitter from '../utils/emitter.js'

const isSidebarOpen = ref(false)
const toggleSidebar = () => {
  isSidebarOpen.value = !isSidebarOpen.value
  console.log('Sidebar toggled')
}

onMounted(() => {
  emitter.on('toggle-sidebar', toggleSidebar)
})
onUnmounted(() => {
  emitter.off('toggle-sidebar')
})
</script>

<template>
  <aside
      :class="{ 'w-48' : isSidebarOpen, 'w-14' :!isSidebarOpen }"
      class="fixed top-16 left-0 bottom-0 bg-white transition-all duration-300 ease-in-out"
  >
  </aside>
</template>

5.Main.vue组件:
这个组件非常重要,刚才那种炫酷的布局能不能实现全靠它。

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import emitter from '../utils/emitter.js'

const isSidebarOpen = ref(false)
const toggleSidebar = () => {
  isSidebarOpen.value =!isSidebarOpen.value
}
onMounted(() => {
  emitter.on('toggle-sidebar', toggleSidebar)
})
onUnmounted(() => {
  emitter.off('toggle-sidebar')
})
</script>

<template>
  <main
      :class="{ 'ml-48' : isSidebarOpen , 'ml-14' :!isSidebarOpen }"
      class="h-[calc(100vh-64px)] bg-white overflow-hidden transition-all duration-300 ease-in-out">
    <div class="content-box bg-slate-100 h-full w-full p-5 border-tl rounded-tl-[30px] overflow-auto">
      <h1 class="text-5xl font-bold text-blue-500">Welcome to the my blog website!</h1>
      。。。。。
    </div>
  </main>
</template>

<style scoped>
.content-box {
  box-shadow: inset 0 3px 4px #0000001a;
}
</style>

image.png 还有一点很重要,要保证main标签上下不能滚动,content-box能滚动。这样才能实现这个炫酷的效果。
同样的Main.vue的左侧外边距也需要动态变化。

6.效果图展示:

image.png

image.png

image.png 源码请访问: gitee.com/akbar-hotan…