前言
本來想寫個新手系列教程..發現這種東西一搜尋一大把;
那就寫點實戰類的吧;這篇文章你能學點什麼?
當然是一些常見內建指令的用法,元件過渡,遍歷的思路等等
效果圖
實現思路
- 過渡用css -
- 遍歷迴圈判斷(比對路由,點選的項名等)
- 增加標記位來預設展開重新整理頁面當前所在項
- 儘量減少DOM的改動,能用
v-show
的區域絕不用v-if
- 自定義選單JSON儘量格式簡潔,沒有一大坨標記位這些干擾物(越簡單越方便後期)
程式碼
- 選單
menuList.js
export const MENULIST = [
{
menuName: "客戶管理",
menuIcon: "fz-ad-icon-test",
menuSubLink: [
{
menuName: "廣告主",
menuUrl: "/customer/adhost"
},
{
menuName: "渠道",
menuUrl: "/customer/channel"
}
]
},
{
menuName: "廣告管理",
menuIcon: "fz-ad-guanggao",
menuSubLink: [
{
menuName: "廣告新增",
menuUrl: "/ad/add"
},
{
menuName: "廣告稽核",
menuUrl: "/ad/check"
}
]
},
{
menuName: "投放管理",
menuIcon: "fz-ad-toufang",
menuSubLink: [
{
menuName: "廣告位",
menuUrl: "/puton/area"
},
{
menuName: "廣告規格",
menuUrl: "/puton/regular"
}
]
},
{
menuName: "資料統計",
menuIcon: "fz-ad-statistics",
menuSubLink: [
{
menuName: "廣告主",
menuUrl: "/status/adhost"
},
{
menuName: "渠道",
menuUrl: "/status/channel"
}
]
},
{
menuName: "管理者",
menuIcon: "fz-ad-guanli",
menuUrl: "/manager"
},
{
menuName: "操作日誌",
menuIcon: "fz-ad-rizhi",
menuUrl: "/logger"
}
];複製程式碼
- Sidebar.vue
<template>
<div class="sidebar" >
<ul class="sidebar-menu ">`
<template v-for="(item ,index) in menulist">
<li :class="currentUrl === item.menuUrl ? 'active':''">
<template v-if="item.menuUrl">
<router-link :to="item.menuUrl" @click.native="toggleName=''">
<i :class="['fzicon',item.menuIcon]"></i>
<span>{{item.menuName}}</span>
</router-link>
</template>
<template v-else-if="item.menuSubLink">
<a href="javascript:;" @click="isToggle(item.menuName,item.defaultActive)">
<i :class="['fzicon',item.menuIcon]"></i>
<span>{{item.menuName}}</span>
<i class="trangle" :class="[config.iconfont, (item.menuName === toggleName) || item.defaultActive? config.icon_expand: config.icon_collapse]">
</i>
</a>
<transition name="sliderToggle" mode="out-in">
<ul class="tree-menu" v-show="item.menuName === toggleName || item.defaultActive">
<li v-for="(subitem,subindex) in item.menuSubLink" :key="subitem" :class="currentUrl === subitem.menuUrl ? 'active':''">
<router-link :to="subitem.menuUrl">
<i :class="subitem.menuIcon"></i>
<span>{{subitem.menuName}}</span>
</router-link>
</li>
</ul>
</transition>
</template>
</li>
</template>
</ul>
</div>
</template>
<script>
import { MENULIST } from './menuList'; // 引入的自定義選單資料
export default {
name: 'layout-sidebar',
data: function () {
return {
menulist: MENULIST, // 自定義選單資料
currentUrl: '', // 當前瀏覽器的url
toggleName: '', // 選單子專案名稱
config: {
'iconfont': 'fzicon', // iconfont的字型
'icon_collapse': 'fz-ad-jiantou', // 箭頭
'icon_expand': 'fz-ad-jiantou1' // 箭頭
}
}
},
props: ['toggle', 'padMode'], // 這裡是用來構成佈局響應傳遞的props,單一元件不用管他
watch: {
'$route'() {
this.currentUrl = this.$route.fullPath; // 實時監測當前路由的變化並且賦值
}
},
methods: {
isToggle(name, defaultActive) {
this.clearDefaultActive(); // 清除標記位,是否當前為預設展開
defaultActive ? false : name !== this.toggleName ? this.toggleName = name : this.toggleName = ''; // 判斷展開收縮的核心
},
clearDefaultActive() {
this.menulist.forEach(item => {
this.$delete(item, 'defaultActive')
})
}
},
created: function () {
this.currentUrl = this.$route.fullPath;
this.$nextTick(() => {
this.menulist.forEach((item, index) => { // 增加標記位,判斷當前url然後自動展開或者啟用對應項(重新整理預設展開當前url的項)
if (!item.menuSubLink && item.menuUrl) {
this.currentUrl === item.menuUrl ? this.$set(item, 'defaultActive', true) : '';
} else {
if (item.menuSubLink) {
item.menuSubLink.forEach((subitem, index) => {
this.currentUrl === subitem.menuUrl ? this.$set(item, 'defaultActive', true) : '';
})
}
}
})
})
},
mounted: function () {
}
}
</script>
<style scoped lang="scss">
// 自定義過渡效果
.sliderToggle-enter-active,
.sliderToggle-leave-active {
transition: all 0.5s linear;
height: 100%;
height: auto;
overflow: hidden;
}
.sliderToggle-enter,
.sliderToggle-leave-to {
overflow: hidden;
padding-top: 0;
padding-bottom: 0;
height: 0;
opacity: 0;
}
// 側邊欄全域性樣式
.sidebar {
position: absolute;
top: 0;
left: 0;
padding-top: 68px;
min-height: 100%;
z-index: 810;
transition: all 0.3s linear;
background-color: #222d32;
.sidebar-menu {
list-style: none;
margin: 0;
padding: 0;
white-space: nowrap;
span {
cursor: pointer;
}
a {
text-decoration: none;
color: #8aa4af;
&:hover {
color: #fff;
}
}
ul {
list-style: none;
margin: 0;
padding: 0;
white-space: nowrap;
overflow: hidden;
}
>li {
position: relative;
margin: 0;
padding: 0;
text-align: left;
&.active {
color: #fff;
}
>a {
border-left: 3px solid transparent;
position: relative;
padding: 15px 5px 15px 19px;
display: block;
font-size: 14px;
>i {
padding-right: 4px;
}
.trangle {
float: right;
padding-right: 10px;
}
}
&.active {
>a {
border-left: 3px solid #3c8dbc;
color: #fff;
}
}
>.tree-menu {
margin: 0 1px;
background: #2c3b41;
list-style: none;
padding: 0;
margin: 0;
.tree-menu {
padding-left: 20px;
}
>li {
margin: 0;
&.active {
>a {
border-left: 3px solid #3c8dbc;
color: #fff;
}
}
>a {
padding: 15px 10px 15px 40px;
display: block;
font-size: 14px;
border-left: 3px solid transparent;
}
}
&.active {
display: block;
}
}
}
}
&.expand {
width: 230px;
}
&.collapse {
width: 50px;
.sidebar-menu {
>li {
>a {
padding: 15px 5px 15px 15px;
span,
i:last-child {
display: none;
}
}
.tree-menu {
display: none;
}
&:hover {
>a {
display: block;
span {
display: block;
position: absolute;
left: 47px;
width: 153px;
padding: 15px 5px 15px 19px;
background-color: #222d32;
color: #fff;
width: 177px;
top: 0;
border-radius: 0 5px 0 0;
}
i:last-child {
display: inline-block;
position: absolute;
right: -165px;
top: 50%;
transform: translateY(-50%);
color: #fff;
}
}
>.tree-menu {
display: block;
position: absolute;
left: 47px;
width: 180px;
background-color: #222d32;
color: #fff;
top: 46px;
width: 180px;
border-radius: 0 0 5px 5px;
}
}
}
}
}
}
</style>複製程式碼
總結
實際上這貨就是把adminlte
的風格用vue實現了...
還有變形金剛版本,,整個響應涉及幾個到元件間的通訊;
就不把全部程式碼丟出來了,一大坨...
效果是這樣的