vue單個(gè)組件實(shí)現(xiàn)無限層級(jí)多選菜單功能
wTree.vue
原理:每一個(gè)多選框都是一個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)就是一個(gè)wTree組件,有父級(jí)(頂級(jí)level為0),有子級(jí)(底層list[]是空的),組件之間狀態(tài)傳遞是通過組件通信傳遞,對(duì)于外部數(shù)據(jù)checkList數(shù)組的修改是通過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ù)組長度,直接改變狀態(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)無限層級(jí)多選菜單,希望對(duì)大家有所幫助,如果大家有任何疑問請(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)菜單欄無限多層級(jí)分類
相關(guān)文章
vue?contextmenujs鼠標(biāo)右鍵菜單高度不夠顯示不全的問題及解決方法
這篇文章主要介紹了使用vue-contextmenujs鼠標(biāo)右鍵菜單時(shí),當(dāng)高度不夠時(shí)顯示不全的問題,大家需要注意本文給提供的解決方案雖然能夠解決現(xiàn)有問題,但是如果組件升級(jí)了,想要使用最新升級(jí)后的組件,還要再次修改代碼,需要的朋友可以參考下2022-07-07
vuejs選中當(dāng)前樣式active的實(shí)例
今天小編就為大家分享一篇vuejs選中當(dāng)前樣式active的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08
vue-cli?npm如何解決vue項(xiàng)目中缺失core-js的問題
這篇文章主要介紹了vue-cli?npm如何解決vue項(xiàng)目中缺失core-js的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
vue.js路由mode配置之去掉url上默認(rèn)的#方法
今天小編就為大家分享一篇vue.js路由mode配置之去掉url上默認(rèn)的#方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue3修改link標(biāo)簽?zāi)J(rèn)icon無效問題詳解
這篇文章主要介紹了vue3修改link標(biāo)簽?zāi)J(rèn)icon無效問題詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
在vue中使用axios實(shí)現(xiàn)post方式獲取二進(jìn)制流下載文件(實(shí)例代碼)
這篇文章主要介紹了在vue中使用axios實(shí)現(xiàn)post方式獲取二進(jìn)制流下載文件的相關(guān)資料,需要的朋友可以參考下2019-12-12
vue實(shí)現(xiàn)數(shù)字滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)數(shù)字滾動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06

