vue?tree封裝一個(gè)可選的樹(shù)組件方式
組件實(shí)現(xiàn)的基本功能
1,根據(jù)后端返回的數(shù)據(jù)格式,傳入組件動(dòng)態(tài)的渲染出當(dāng)前角色有哪些權(quán)限(新建,修改)
2,適配有2級(jí)和只有一級(jí)多選的數(shù)據(jù)
3,有全選(√) ,全不選 ,部分已選(-)的3裝狀態(tài),每一級(jí)都支持(用的iview2次封裝)
4,改變之后返回當(dāng)前選中的所有權(quán)限的id,用于提交
5,手風(fēng)琴效果,小屏適配
先看效果圖
有部分權(quán)限沒(méi)打開(kāi)
打開(kāi)
小屏
權(quán)限數(shù)據(jù)結(jié)構(gòu),select_status=1表示選中
默認(rèn)添加沒(méi)有權(quán)限的初始數(shù)據(jù)結(jié)構(gòu)
有些數(shù)據(jù)只有一級(jí)子菜單,有些有兩級(jí)
核心代碼.vue
<template> <div class="powerList"> <div v-for="(item,index) in powers" :key="item.id" :class="{item:true,active:item.active}"> <Checkbox :indeterminate="item.indeterminate" :value="item.val1" @click.prevent.native="handleCheckAll(index)"> <span style="color:#1C213A;font-weight:600;"> {{item.name}}</span> </Checkbox> <div style="font-size:30px;float:right;width:220px;cursor: pointer;color:#BEC1C8;text-align:right;" @click="open(item.active,index)"> <Icon :type="item.active? 'md-arrow-dropup': 'md-arrow-dropdown'" /> </div> <!-- 全部都是只有一級(jí)子菜單的 --> <CheckboxGroup v-if="oneChild(item.child)" v-model="item.checked" @on-change="checkGroupChange($event,index)"> <Checkbox v-for="item2 in item.child" :key='item2.id' :label="item2.id">{{item2.name}}</Checkbox> </CheckboxGroup> <template v-else> <div v-for='(item3,index3) in item.child' :key="item3.id" class="item3"> <!-- 有二級(jí)子菜單的 --> <template v-if="item3.child"> <Checkbox :indeterminate="item3.indeterminate" :value="item3.val1" @click.prevent.native="level2CheckAll(index,index3)"> {{item3.name}}</Checkbox> <CheckboxGroup v-model="item3.checked" @on-change='checkGroupChange($event,index,index3)'> <Checkbox v-for="item4 in item3.child" :key='item4.id' :label="item4.id">{{item4.name}}</Checkbox> </CheckboxGroup> </template> </div> </template> </div> </div> </template>
<script> /** *公共的權(quán)限選擇組件,接受后端返回的權(quán)限列表powerData *返回選中的權(quán)限的id的arr @change接受 */ export default { props: { powerData: Array }, data () { return { powers: [] } }, watch: { powerData: { handler (val, old) { if (val && val.length && JSON.stringify(val) !== JSON.stringify(old)) { this.powers = this.formatData(val) this.save([...this.powers]) } }, immediate: true, deep: true } }, methods: { // 保存返回選中的項(xiàng)的數(shù)組 save (arr) { let auth_id = [] arr.forEach(item => { if (item.indeterminate || item.val1) { auth_id.push(item.id) if (this.oneChild(item.child)) { auth_id = auth_id.concat([...item.checked]) } else { item.child.forEach(item2 => { if (item2.indeterminate || item2.val1) { auth_id.push(item2.id) auth_id = auth_id.concat([...item2.checked]) } }) } } }) console.log(auth_id) this.$emit('change', auth_id) }, //把獲取到的權(quán)限格式化成需要的格式 /** * active :dom開(kāi)關(guān) * indeterminate: 勾選狀態(tài)為-的樣式 * val1 全選的狀態(tài) * total 有多級(jí)時(shí)子菜單的總數(shù) * checked 二級(jí)多選當(dāng)前選中的值 */ formatData (arr) { return arr.map(item => { item.active = false //用于開(kāi)關(guān)下拉 if (!this.oneChild(item.child)) { // 有多級(jí)子菜單 let total = 0 //計(jì)算當(dāng)前項(xiàng)下的底級(jí)子菜單的總數(shù) 用于給主一級(jí)全選相應(yīng)的狀態(tài) item.child.map(item => item.child.length).forEach(item => { total += item }) item.total = total item.child = item.child.map(item2 => { item2.checked = item2.child.filter(item3 => item3.select_status === 1).map(item4 => item4.id) if (item2.checked.length === item2.child.length) { //選中的子選項(xiàng)數(shù)量等于子選項(xiàng)數(shù)量 就是全選 item2.indeterminate = false item2.val1 = true } else if (item2.checked.length === 0) { // 沒(méi)有選中的 item2.indeterminate = false item2.val1 = false } else { //< item2.indeterminate = true item2.val1 = false } return item2 }) this.changeLevel1Status(item) // 設(shè)置一級(jí)全選的狀態(tài) } else { // 只有一級(jí)子菜單的 item.checked = item.child.filter(item => item.select_status === 1).map(item => item.id) //子菜單當(dāng)前選中的值 let childNum = item.child.length let checkedNum = item.child.filter(item5 => item5.select_status === 1).length if (checkedNum === 0) { item.indeterminate = false item.val1 = false } else if (checkedNum < childNum) { item.indeterminate = true item.val1 = false } else { item.indeterminate = false item.val1 = true } } return item }) }, // 權(quán)限展開(kāi),手風(fēng)琴 open (val, index) { // 關(guān)閉所有的 this.powers = this.powers.map(item => { item.active = false return item }) let obj = this.powers[index] obj.active = !val // 打開(kāi)點(diǎn)擊的 this.powers.splice(index, 1, obj) }, // 只有一級(jí)子菜單的 oneChild (arr) { return arr.every(item => item.child === undefined) }, /** * 主菜單的全選 * @param index (索引) */ handleCheckAll (index) { if (this.oneChild(this.powers[index].child)) { //只有一級(jí)子菜單的 let powers = [...this.powers] let obj = powers[index] if (obj.indeterminate) { //當(dāng)前項(xiàng)有子菜單選中的 obj.val1 = false; } else { obj.val1 = !obj.val1 } obj.indeterminate = false; if (obj.val1) { // 如果是全選 obj.checked = obj.child.map(item => item.id); } else { obj.checked = []; } this.powers = [...powers] this.save([...this.powers]) } else { this.checkAllOther(index) } }, // 有多級(jí)子菜單的全選 checkAllOther (index) { let powers = [...this.powers] if (powers[index].indeterminate) { //當(dāng)前項(xiàng)有子菜單選中的 powers[index].val1 = false; } else { powers[index].val1 = !powers[index].val1 } powers[index].indeterminate = false; if (powers[index].val1) { // 如果是全選 powers[index].child.forEach(item => { item.val1 = true // 所有2級(jí)全選選中 item.indeterminate = false //狀態(tài)去掉 item.checked = item.child.map(item2 => item2.id) //2級(jí)全選的子菜單都選中 }) } else { powers[index].child.forEach(item => { item.val1 = false item.checked = []; item.indeterminate = false //狀態(tài)去掉 }) } this.powers = [...powers] this.save([...this.powers]) }, // 子菜單的checkGrounp改變,data選中的項(xiàng)的id構(gòu)成的arr checkGroupChange (data, index, index3) { let powers = [...this.powers] let obj = index3 === undefined ? powers[index] : powers[index].child[index3]// 有index3就是二級(jí)子菜單的checkGroup if (data.length === obj.child.length) { //全部勾選 obj.indeterminate = false; obj.val1 = true; } else if (data.length > 0) { //有選中的 obj.indeterminate = true; obj.val1 = false; } else { //沒(méi)選中的 obj.indeterminate = false; obj.val1 = false; } // 有二級(jí)子菜單的項(xiàng)改變的時(shí)候 if (index3 !== undefined) { this.changeLevel1Status(powers[index]) } this.powers = [...powers] this.save([...this.powers]) }, // 2級(jí)的全選 level2CheckAll (index, index3) { let powers = [...this.powers] let obj = powers[index].child[index3] //當(dāng)前操作的2級(jí)全選 if (obj.indeterminate) { //當(dāng)前項(xiàng)有子菜單選中的 obj.val1 = false; } else { obj.val1 = !obj.val1 } obj.indeterminate = false; if (obj.val1) { // 如果是全選 obj.checked = obj.child.map(item => item.id); } else { obj.checked = []; } this.changeLevel1Status(powers[index]) this.powers = [...powers] this.save([...this.powers]) }, // 二級(jí)子菜單或2級(jí)全選時(shí)更改一級(jí)全選的狀態(tài) changeLevel1Status (obj) { let checkedNum = 0 obj.child.map(item => item.checked.length).forEach(item => { checkedNum += item }) if (checkedNum === 0) { obj.indeterminate = false obj.val1 = false } else if (checkedNum < obj.total) { obj.indeterminate = true obj.val1 = false } else { obj.indeterminate = false obj.val1 = true } } }, } </script>
<style lang="scss" scoped> .powerList { display: flex; justify-content: space-between; flex-wrap: wrap; .item { width: 370px; height: 58px; background: #f9f9f9; line-height: 58px; margin-bottom: 20px; padding: 0 10px 0 20px; overflow: hidden; &.active { height: auto; } /deep/ .ivu-checkbox-group label { display: block; } .item3 { /deep/ .ivu-checkbox-group { padding-left: 20px; label { display: inline-block; } } } } } </style>
核心代碼主要就是數(shù)據(jù)的處理,底級(jí)的更改都觸發(fā)上一級(jí)的狀態(tài)和值得改變
用的時(shí)候主要就是一個(gè)props傳入數(shù)據(jù), 一個(gè)方法返回給父組件選中的值
<power :powerData='powers' @change="powerChange" />
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue中子組件向父組件傳遞數(shù)據(jù)的實(shí)例代碼(實(shí)現(xiàn)加減功能)
這篇文章主要介紹了vue中子組件向父組件傳遞數(shù)據(jù)的實(shí)例代碼(實(shí)現(xiàn)加減功能) ,需要的朋友可以參考下2018-04-04vue-devtools?開(kāi)發(fā)工具插件之支持vue3?chrome?瀏覽器插件
這篇文章主要介紹了vue-devtools?開(kāi)發(fā)工具插件之支持vue3?chrome?瀏覽器插件,用這個(gè)版本主要是為了支持vue3?推薦直接下載,文中給大家提供了下載地址,感興趣的朋友跟隨小編一起看看吧2022-01-01詳解vue-cli之webpack3構(gòu)建全面提速優(yōu)化
這篇文章主要介紹了詳解vue-cli之webpack3構(gòu)建全面提速優(yōu)化,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12vue請(qǐng)求服務(wù)器數(shù)據(jù)后綁定不上的解決方法
今天小編就為大家分享一篇vue請(qǐng)求服務(wù)器數(shù)據(jù)后綁定不上的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10