vue單個(gè)組件實(shí)現(xiàn)無(wú)限層級(jí)多選菜單功能
wTree.vue
原理:每一個(gè)多選框都是一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)就是一個(gè)wTree組件,有父級(jí)(頂級(jí)level為0),有子級(jí)(底層list[]是空的),組件之間狀態(tài)傳遞是通過(guò)組件通信傳遞,對(duì)于外部數(shù)據(jù)checkList數(shù)組的修改是通過(guò)store實(shí)現(xiàn)的。初始化從底層狀態(tài)傳遞到上層,一層一層傳遞。改變狀態(tài),不同狀態(tài)改變,修改checklist數(shù)組。大概就這個(gè)思路,下面是代碼:
<template>
<div>
<div >
<span v-for="o in levelNum"> </span>
<i v-if="item.list" :class="open ? openClass : closeClass" @click="showSub" style="color: #00d6b2"></i>
<span v-else> </span>
<span>
<a @click="changeState">
<img src="./../assets/selectedAll.png" v-if="selectedState === 'all'" width="15px" height="15px"/>
<img src="./../assets/selectedSub.png" v-if="selectedState === 'sub'" width="15px" height="15px"/>
<img src="./../assets/selectedNull.png" v-if="selectedState === 'null'" width="15px" height="15px"/>
</a>
</span>
<span>{{item.name}}</span>
</div>
<component v-show="open" :is="node" :item="o" :state="stateSub" v-for="o of item.list" :key="o.key" :level="levelNum" v-on:changeToPar="changeBySub">
</component>
</div>
</template>
<script>
export default {
name: 'wTree',
props: ['item', 'level', 'state'],
data () {
return {
open: true,
node: 'wTree', // 控制菜單開關(guān)的
selected: false, // 選中的情況下
selectedState: 'null', // 子組件被選中的情況下向上傳遞all/sub/null
originInfo: 'create', // 組件信息源,create/parent/children/this
openClass: 'el-icon-caret-bottom',
closeClass: 'el-icon-caret-right',
selectClass: 'el-icon-check',
selectBg: '#1c8de0',
list: [],
createSwitch: true
}
},
computed: {
levelNum () {
return (this.level + 1)
},
stateSub () {
return {
selected: this.selected,
originInfo: this.originInfo
}
}
},
methods: {
showSub () {
this.open = !this.open
},
changeState () {
if (this.selected) {
this.selected = false
this.selectedState = 'null'
this.originInfo = 'this'
for (let o of this.list) {
o.selectedState = 'null'
}
} else {
this.selected = true
this.selectedState = 'all'
this.originInfo = 'this'
for (let o of this.list) {
o.selectedState = 'all'
}
}
let data = {
id: this.item.menuId,
selectedState: this.selectedState,
originInfo: 'parent'
}
this.$emit('changeToPar', data)
},
changeBySub (data) {
// 如果是父組件true,判斷狀態(tài),未被選中,添加id到list,selectSub=true,通知父組件,添加store的數(shù)組中,選中通知父組件,this.list.length=this.length狀態(tài)改為selected
// 修改自身狀態(tài),添加list
let temp = data
if (data.originInfo === 'create') {
this.list.push(data)
} else {
this.originInfo = 'parent'
let stateNull = 'null'
let stateAll = 'all'
let stateSub = 'sub'
for (let o of this.list) {
if (o.id === temp.id) {
o.selectedState = temp.selectedState
}
if (o.selectedState !== 'all') {
stateAll = null
}
if (o.selectedState !== 'null') {
stateNull = null
}
}
if (stateNull) {
this.selectedState = stateNull
this.selected = false
} else if (stateAll) {
this.selectedState = stateAll
this.selected = true
} else {
this.selectedState = stateSub
this.selected = true
}
let data = {
id: this.item.menuId,
selectedState: this.selectedState,
originInfo: 'parent'
}
this.$emit('changeToPar', data)
}
}
},
watch: {
selected () {
// 初始化
if (this.originInfo === 'create') {
// 不改變值
} else {
// 改變值********
if (this.selected) {
// 添加值
this.$store.commit('PUSH_CHECK_LIST', this.item.menuId)
} else {
// 刪除值
this.$store.commit('SPLICE_CHECK_LIST', this.item.menuId)
}
}
},
state () {
// 子組件得到通知,如果狀態(tài)一直,不去改變,如果狀態(tài)不一致改變
if (this.state.originInfo === 'this') {
this.originInfo = 'this'
}
if (this.originInfo === 'create') {
this.originInfo = 'children'
} else {
if (this.state.originInfo !== 'parent') {
if (this.state.selected) {
this.selected = true
this.selectedState = 'all'
if (this.list !== []) {
for (let o of this.list) {
o.selectedState = 'all'
}
}
} else {
this.selected = false
this.selectedState = 'null'
if (this.list !== []) {
for (let o of this.list) {
o.selectedState = 'null'
}
}
}
}
}
},
list () {
// 初始化數(shù)組
if (this.list.length === this.item.list.length) {
let stateNull = 'null'
let stateAll = 'all'
let stateSub = 'sub'
for (let o of this.list) {
if (o.selectedState !== 'all') {
stateAll = null
}
if (o.selectedState !== 'null') {
stateNull = null
}
}
if (stateNull) {
this.selectedState = stateNull
this.selected = false
} else if (stateAll) {
this.selectedState = stateAll
this.selected = true
} else {
this.selectedState = stateSub
this.selected = true
}
let data = {
id: this.item.menuId,
selectedState: this.selectedState,
originInfo: 'create'
}
this.$emit('changeToPar', data)
}
}
},
created () {
// 初始化,把每個(gè)組件,從最底層添加到節(jié)點(diǎn)列表中,這樣每個(gè)子組件都在list中了,就是originInfo=create的情況下添加數(shù)組,就不用判斷數(shù)組長(zhǎng)度,直接改變狀態(tài)
if (this.createSwitch) {
let i = this.$store.state.checkList.indexOf(this.item.menuId)
console.log(!this.item.list)
console.log('-----------------------初始化')
if (!this.item.list) {
if (i > -1) {
this.selectedState = 'all'
this.selected = true
} else {
this.selectedState = 'null'
this.selected = false
}
let data = {
id: this.item.menuId,
selectedState: this.selectedState,
originInfo: 'create'
}
this.$emit('changeToPar', data)
this.originInfo = 'this'
}
this.createSwitch = false
}
console.log(this.state)
console.log('----------------created')
},
updated () {
console.log('-------updated=======')
let i = this.$store.state.checkList.indexOf(this.item.menuId)
console.log(!this.item.list)
console.log('-----------------------初始化')
if (!this.item.list) {
if (i > -1) {
this.selectedState = 'all'
this.selected = true
} else {
this.selectedState = 'null'
this.selected = false
}
let data = {
id: this.item.menuId,
selectedState: this.selectedState,
originInfo: 'parent'
}
this.$emit('changeToPar', data)
this.originInfo = 'this'
}
},
mounted () {
console.log('=========mounted-----')
}
}
</script>
調(diào)用 orgList帶有層級(jí)的json數(shù)組
<w-tree v-for="o of orgList" :item="o" :level="0" :key="o.key"></w-tree>
總結(jié)
以上所述是小編給大家介紹vue單個(gè)組件實(shí)現(xiàn)無(wú)限層級(jí)多選菜單,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
- Vue實(shí)現(xiàn)商品分類菜單數(shù)量提示功能
- 基于vue.js實(shí)現(xiàn)側(cè)邊菜單欄
- vue2.0使用v-for循環(huán)制作多級(jí)嵌套菜單欄
- Vue 菜單欄點(diǎn)擊切換單個(gè)class(高亮)的方法
- Vue實(shí)現(xiàn)側(cè)邊菜單欄手風(fēng)琴效果實(shí)例代碼
- vue實(shí)現(xiàn)頂部菜單欄
- vue如何實(shí)現(xiàn)自定義底部菜單欄
- Vue-路由導(dǎo)航菜單欄的高亮設(shè)置方法
- 基于vue實(shí)現(xiàn)圓形菜單欄組件
- vue+el-menu實(shí)現(xiàn)菜單欄無(wú)限多層級(jí)分類
相關(guān)文章
Vue不能watch數(shù)組和對(duì)象變化解決方案
這篇文章主要為大家介紹了Vue不能watch數(shù)組和對(duì)象變化解決方案示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
一文詳解Vue響應(yīng)式數(shù)據(jù)的原理
在vue2的響應(yīng)式中,存在著添加屬性、刪除屬性、以及通過(guò)下標(biāo)修改數(shù)組,但頁(yè)面不會(huì)自動(dòng)更新的問(wèn)題,而這些問(wèn)題在vue3中都得以解決,本文就給大家詳細(xì)的介紹一下Vue響應(yīng)式數(shù)據(jù)原理,感興趣的小伙伴跟著小編一起來(lái)看看吧2023-08-08
Vue.config.js配置報(bào)錯(cuò)ValidationError:?Invalid?options?object解
這篇文章主要給大家介紹了關(guān)于Vue.config.js配置報(bào)錯(cuò)ValidationError:?Invalid?options?object的解決辦法,主要由于vue.config.js配置文件錯(cuò)誤導(dǎo)致的,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
解決vue一個(gè)頁(yè)面中復(fù)用同一個(gè)echarts組件的問(wèn)題
這篇文章主要介紹了解決vue一個(gè)頁(yè)面中復(fù)用同一個(gè)echarts組件的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
vuejs選中當(dāng)前樣式active的實(shí)例
今天小編就為大家分享一篇vuejs選中當(dāng)前樣式active的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08

