Vue折騰記 – (1)寫一個不大靠譜的二級側邊欄

CRPER發表於2017-07-14

前言

本來想寫個新手系列教程..發現這種東西一搜尋一大把;

那就寫點實戰類的吧;
這篇文章你能學點什麼?
當然是一些常見內建指令的用法,元件過渡,遍歷的思路等等


效果圖

實現思路

  • 過渡用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實現了…
還有變形金剛版本,,整個響應涉及幾個到元件間的通訊;

就不把全部程式碼丟出來了,一大坨…

效果是這樣的

來源:https://juejin.im/post/59689933518825492a4c1bd1

相關文章