当前位置: 首页> 文旅> 酒店 > 彩页印刷_烟台seo_网店运营工资一般多少_seo和sem的区别与联系

彩页印刷_烟台seo_网店运营工资一般多少_seo和sem的区别与联系

时间:2025/8/5 14:57:07来源:https://blog.csdn.net/younuoqianjin/article/details/146223092 浏览次数:1次
彩页印刷_烟台seo_网店运营工资一般多少_seo和sem的区别与联系

功能12:折叠/展开侧边栏

功能11:实现面包屑功能
功能10:添加首页菜单项
功能9:退出登录功能
功能8:页面权限控制
功能7:路由全局前置守卫
功能6:动态添加路由记录
功能5:侧边栏菜单动态显示
功能4:首页使用Layout布局
功能3:点击登录按钮实现页面跳转
功能2:静态登录界面
功能1:创建前端项目

前言

el-menu提供了侧边栏的折叠属性collapse,可以水平折叠收起菜单。

一.操作步骤

1.新建appStore

定义appStore,保存控制侧边栏状态的相关信息。
showSidebar :false侧边栏展开,true侧边栏折叠。
sidebarWidth :展开时的组件宽度。

import { defineStore } from 'pinia'
import { ref } from 'vue'const useAppStore = defineStore('app', () => {const showSidebar = ref(false)const sidebarWidth = ref(180)const setSidebar = () => {showSidebar.value = !showSidebar.valueif (sidebarWidth.value === 180) {sidebarWidth.value = 64} else {sidebarWidth.value = 180}}return {showSidebar,sidebarWidth,setSidebar}
})export default useAppStore

2.修改Navbar.vue

在面包屑前,增加一个图标,点击图标会触发appStore里的状态变化,实现侧边栏折叠和展开。

<template><el-header class="navbar"><div class="parent"><el-icon :size="20" class="hamburger-container" @click="toggleSideBar"><template v-if="appStore.showSidebar"><Expand /></template><template v-else><Fold /></template></el-icon><el-breadcrumb separator="/"><el-breadcrumb-item v-for="(item, index) in breadcrumbItems" :key="item.path"><router-link v-if="index === 0" :to="item.path">{{ item.meta.title }}</router-link><span v-else>{{ item.meta.title }}</span></el-breadcrumb-item></el-breadcrumb></div><div class="user-menu"><el-dropdown trigger="hover"><div class="avatar-container"><img :src="avatarUrl" alt="用户头像" class="avatar-image" /></div><template #dropdown><el-dropdown-menu class="dropdown-menu"><el-dropdown-item @click="handleSettings" class="menu-item"><span>个人设置</span></el-dropdown-item><el-dropdown-item divided @click="handleLogout" class="menu-item"><span>退出登录</span></el-dropdown-item></el-dropdown-menu></template></el-dropdown></div></el-header>
</template><script setup>
import { ElMessageBox } from 'element-plus'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()const breadcrumbItems = computed(() => {// 获取当前路由的匹配数组,过滤无meta的路由const matched = route.matched.filter(item => item.meta?.title);// 确保首页始终在首位(如果当前路由不是首页)if (route.path !== '/' && matched[0]?.path !== '/') {matched.unshift({ path: '/index', meta: { title: '首页' } });}if (route.path === '/' || route.path === '/index') {matched.splice(0, matched.length - 1)}return matched;
})// 请确保在 assets 目录下存在 user-avatar.png 图片文件
const avatarUrl = new URL('@/assets/images/profile.jpg', import.meta.url).hrefimport useUserStore from '@/stores/user'
const userStore = useUserStore()const handleLogout = () => {// 处理退出登录逻辑ElMessageBox.confirm('确定注销并退出系统吗?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {userStore.logout().then(() => {location.href = '/index';})}).catch(() => { });
}const handleSettings = () => {// 处理设置逻辑console.log('打开设置页面')
}import useAppStore from '@/stores/app'
const appStore = useAppStore()
const toggleSideBar = () => {appStore.setSidebar()
}
</script><style scoped lang="scss">
.parent {display: flex; /* 启用 Flex 布局 */gap: 16px; /* 子元素间距(可选) */justify-content: flex-start; /* 水平对齐方式(可选) */align-items: center; /* 垂直对齐方式(可选) */.hamburger-container {line-height: 46px;height: 100%;float: left;cursor: pointer;transition: background 0.3s;-webkit-tap-highlight-color: transparent;&:hover {background: rgba(0, 0, 0, 0.025);}}
}
/* 导航栏整体样式 */
.navbar {background-color: #ffffff;border-bottom-width: 1px;border-bottom-style: solid;border-bottom-color: #e5e7eb;display: flex;align-items: center;justify-content: space-between;height: 64px;padding: 0 24px;box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}/* 用户菜单容器 */
.user-menu {position: relative;z-index: 1000;
}/* 头像容器 */
.avatar-container {position: relative;width: 40px;height: 40px;transition: all 0.3s ease;
}/* 头像图片样式 */
.avatar-image {width: 100%;height: 100%;border-radius: 9999px;object-fit: cover;border: 2px solid #fff;box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}/* 悬停效果 */
.avatar-container:hover .avatar-image {transform: scale(1.1);box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}/* 下拉菜单样式 */
.dropdown-menu {border: none !important;border-radius: 8px !important;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;margin-top: 12px !important;padding: 8px 0 !important;
}/* 菜单项样式 */
.menu-item {font-size: 14px;color: #333 !important;transition: all 0.2s ease;
}.menu-item:hover {background: #f5f7fa !important;color: #409eff !important;transform: translateX(4px);
}/* 分割线样式 */
.el-dropdown-menu__item--divided {border-color: #ebeef5 !important;
}
</style>

3.修改Sidebar.vue

将el-menu的collapse属性绑定到appstore的showSidebar,响应式的控制侧边栏的展开和折叠。

<template><el-menu router :default-active="activeMenu" :default-openeds="openedMenus" class="el-menu-vertical":collapse="appStore.showSidebar" unique-opened><template v-for="item in menuData" :key="item.path"><MenuItem :item="item" :level="0" /></template></el-menu>
</template><script setup>
import { defineProps, computed, ref } from 'vue';
import MenuItem from './MenuItem.vue';
import { useRoute } from 'vue-router';import useAppStore from '@/stores/app'
const appStore = useAppStore()const route = useRoute()
defineProps({menuData: {type: Array,required: true}
});const activeMenu = computed(() => {return route.path
})const openedMenus = computed(() => {return route.matched.map(item => item.path).filter(path => path !== '/')
})
</script><style lang="scss" scoped>
.el-menu-vertical {height: 100%;--el-menu-bg-color: #304156;--el-menu-text-color: #bfcbd9;--el-menu-active-color: #409EFF;--el-menu-hover-bg-color: #1e0b39;
}
</style>

4.修改MenuItem.vue

按照Element Plus的官网,调整el-menu的一些显示,让折叠的时候达到预期效果。

<template><div v-if="!item.hidden"><template v-if="hasChildren"><el-sub-menu :index="item.path"><template #title><el-icon><component is="House" /></el-icon><span>{{ item.meta?.title }}</span></template><template v-for="child in item.children" :key="child.path"><MenuItem :item="child" :level="level + 1" :base-path="resolvePath(item.path)" /></template></el-sub-menu></template><template v-else><el-menu-item :index="resolvePath(item.path)"><el-icon><component is="House" /></el-icon><template #title><span>{{ item.meta?.title }}</span></template></el-menu-item></template></div>
</template>

5.修改layout/index.vue

增加样式,让侧边栏的高度撑满整个屏幕。通过绑定appStore里的控制侧边栏宽度属性,响应式改变侧边栏的组件宽度。

<template><el-container class="container"><el-aside :width="appStore.sidebarWidth + 'px'" class="aside"><Sidebar :menu-data="permissionStore.arrayForMenu" /></el-aside><el-container><el-header height="48px"><Navbar /></el-header><AppMain /></el-container></el-container>
</template><script setup>
import { ElContainer, ElAside } from 'element-plus'
import Sidebar from './components/Sidebar.vue'
import Navbar from './components/Navbar.vue'
import AppMain from './components/AppMain.vue'
import usePermissionStore from '@/stores/permission'
import useAppStore from '@/stores/app'const appStore = useAppStore()
const permissionStore = usePermissionStore()
</script><style>
.container {height: 100%;.aside {height: 100%;}
}.el-header {--el-header-padding: 0;height: auto;
}
</style>

6.修改index.html

增加全局控制样式

  <style>html,body,#app {height: 100%;margin: 0px;padding: 0px;}</style>

7.新建全局样式表src\assets\styles\index.scss

控制el-menu相关效果的属性

/* 覆盖所有折叠弹出菜单的背景色 */
.el-menu--popup {background-color: #304156 !important;/* 自定义背景色 */
}/* 覆盖悬停色 */
.el-menu--popup .el-menu-item:hover,
.el-menu--popup .el-sub-menu__title:hover {background-color: #1e0b39 !important;
}/* 默认文字颜色 */
.el-menu--popup .el-menu-item,
.el-menu--popup .el-sub-menu__title {color: #bfcbd9 !important;
}/* 隐藏折叠后的菜单文字 */
.el-menu--collapse .el-sub-menu__title span {display: none;
}/* 隐藏折叠后的展开箭头 */
.el-menu--collapse .el-sub-menu__icon-arrow {display: none;
}

在main.js文件里进行全局注册

import '@/assets/styles/index.scss'

二.功能验证

运行项目,浏览器访问http://localhost:5173/index,点击导航栏里的图标,折叠和展开的边栏
在这里插入图片描述

三.知识点拓展

1、Pinia 状态管理(核心知识点)

通俗理解:就像在项目中创建一个"共享记事本",所有组件都能读写这个记事本里的内容。

代码体现

// 定义存储侧边栏状态的"记事本"
const useAppStore = defineStore('app', () => {const showSidebar = ref(false) // 折叠状态const sidebarWidth = ref(180)  // 侧边栏宽度// 修改状态的"笔"const setSidebar = () => {showSidebar.value = !showSidebar.valuesidebarWidth.value = showSidebar.value ? 64 : 180}return { showSidebar, sidebarWidth, setSidebar }
})

应用场景
• 在导航栏组件点击折叠按钮时调用 setSidebar
• 侧边栏组件通过 showSidebar 自动响应折叠状态
• 布局组件通过 sidebarWidth 调整侧边栏宽度


2、组件间通信

通俗理解:不同组件之间通过"共享记事本"(Pinia)传递信息,无需直接对话。

实现方式
• Navbar 组件:触发状态修改

<el-icon @click="toggleSideBar"></el-icon>

• Sidebar 组件:自动响应状态变化

<el-menu :collapse="appStore.showSidebar">

3、响应式设计

通俗理解:当数据变化时,页面会自动像"镜子"一样实时反映变化。

技术实现

  1. ref() 创建响应式数据
  2. computed() 计算属性
    const activeMenu = computed(() => route.path)
    

实际效果
• 点击折叠按钮 → 自动更新侧边栏宽度和菜单状态
• 路由变化 → 面包屑自动更新


4、组件化开发

通俗理解:把页面拆分成多个"积木块",每个积木独立且可复用。

组件结构
Navbar.vue:顶部导航栏
Sidebar.vue:侧边栏容器
MenuItem.vue:递归渲染菜单项(可无限嵌套)

递归组件

<!-- 菜单项组件自己调用自己 -->
<MenuItem v-for="child in item.children" :item="child" :level="level + 1"
/>

5、Element Plus 使用技巧

关键属性

<el-menu :collapse="appStore.showSidebar" unique-opened
>

样式覆盖

/* 修改 Element 默认样式 */
.el-menu--popup {background-color: #304156 !important;
}

折叠优化
• 隐藏折叠后的文字和箭头

.el-menu--collapse .el-sub-menu__title span {display: none;
}

6、CSS 布局技巧

布局方案

  1. 全屏布局
    html, body, #app { height: 100% }
    
  2. Flex 布局
    .parent {display: flex;align-items: center;
    }
    
  3. 过渡动画
    .avatar-image {transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }
    

7、最佳实践总结

  1. 状态集中管理:复杂状态交给 Pinia
  2. 组件解耦:每个组件专注单一功能
  3. 响应式思维:用数据驱动视图变化
  4. 样式分层
    • 组件样式用 scoped
    • 全局样式统一管理
  5. UI 框架深度定制:通过 CSS 覆盖实现个性化效果

四.思考

关键字:彩页印刷_烟台seo_网店运营工资一般多少_seo和sem的区别与联系

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: