ElementUI級聯(lián)選擇器實現(xiàn)同一父級下最多只能選中一個子級
這個需求有點多選與單選結(jié)合的意思,同一父級下的子節(jié)點單選,又可以選擇多個不同父級下的節(jié)點。這里以兩級為例,實現(xiàn)一個在多選模式下,同一父級下最多只能選中一個子級的級聯(lián)選擇器。
1、隱藏父級節(jié)點處的CheckBox
多選模式下可以通過勾選父級一鍵選中所有的子級,而每個父級下可能有多個子級,也可能只有一個,起初我想的是根據(jù)本次選擇選中的個數(shù)分類討論,但討論起來比較繁瑣,所以最后決定直接把父級的checkbox隱藏掉,不讓用戶直接勾選父級,減少了很多不必要的麻煩。
.hide {
.el-cascader-menu:first-of-type {
.el-cascader-node {
.el-checkbox {
display: none;
}
}
}
}這里需要注意的一點是hide類名必須使用級聯(lián)選擇器中的popper-class來添加自定義浮層類名的。

2、對選中的項進行篩選限制,先找到本次新增的項,和新增前的值進行對比,看是否存在與本次新增的項同屬于一個父級的,如果存在則刪除之前已經(jīng)存在的那一項,留下本次新增的。
這里的解決花費了我很多時間,因為一開始想著直接操作級聯(lián)選擇器綁定值,刪除掉不要的那一項就可以了,但問題出現(xiàn)了。綁定的值確實達到了我想要的效果(即刪除之前已經(jīng)存在的那一項,留下本次新增的),但級聯(lián)面板中右側(cè)的部分(即子節(jié)點部分),會自動刷新跳轉(zhuǎn)到第一個父級下的子級面板,用戶體驗差,嘗試解決,沒解決掉。。。
最后,選擇從另外一個角度來實現(xiàn),如果存在與本次新增的項同屬于一個父級的,則直接通過js觸發(fā)點擊事件,取消勾選之前已經(jīng)存在的那一項。
有了思路以后就可以一步一步來實現(xiàn)了。
首先找到本次新增的這一項,由于組件庫文檔中級聯(lián)選擇器這一塊并沒有提供相關的辦法獲取到最新選擇的一項,只能拿到已選擇的所有值,并且級聯(lián)選擇器新增的項并不是直接push到綁定值的末尾,而是按選項值在頁面上展示的順序添加的,所以只能手動去對比查找,需要定義一個preValue數(shù)組來存儲上一次的值。
let newIndex;
let i = 0, j = 0;
while (i < val.length && j < this.preValue.length) {
if (val[i][0] === this.preValue[j][0] && val[i][1] === this.preValue[j][1]) {
i++;
j++;
} else {
//添加在中間的情況
newIndex = i;
break;
}
}
//添加在末尾的情況
if (j === this.preValue.length) {
newIndex = i;
}找到新增項后,再去對比在此之前是否添加過于新增項同一父級下的其他子級。
let delIndex = val.findIndex((item, index) => index !== newIndex && item[0] === val[newIndex][0]);
如果存在的話,接下來就需要去觸發(fā)相應的點擊事件取消這一項的勾選。
我們先來觀察一下html結(jié)構(gòu),右側(cè)面板下的各個li標簽的id值其實就是右側(cè)面板id值加上:'-'+index,因此我們只需要拿到右側(cè)面板id值就能知道對應選項的id值,再觸發(fā)li標簽的孩子標簽中的checkbox的點擊事件就可以了。


右側(cè)面板id通過級聯(lián)選擇器的引用可以拿到,另外需要求得取消勾選選項的index,通過與級聯(lián)選擇器選項值對比得到。
let cancelIndex;
for (let i = 0; i < this.options.length; i++) {
if (this.options[i].value === val[delIndex][0]) {
for (let j = 0; j < this.options[i].children.length; j++) {
if (this.options[i].children[j].value === val[delIndex][1]) {
cancelIndex = j;
break;
}
}
break;
}
}獲取id值。
this.$nextTick(() => {
let panelId = this.$refs.cascade.panel.$refs.menu[1].$el.id; //其中menu[1]表示右側(cè)的面板 menu[0]即為左側(cè)的面板
let liId = document.getElementById(panelId + '-' + cancelIndex);
liId.children[0].click();
})到這里就基本完成了這個需求,其實不難,但因為一開始自己的思路(直接刪值)實現(xiàn)起來出現(xiàn)了問題,想著去解決花費了很多時間,也沒解決掉,最后和同事討論換一種思路很快就實現(xiàn)了,所以思路變通是非常重要的~
3、完整代碼
<template>
<div class='test'>
<el-cascader
class='cascader'
:options='options'
:props='props'
clearable
:popper-class="'hide'"
@change='handleChange'
ref='cascade'
></el-cascader>
</div>
</template>
<script>
export default {
name: 'Cascader',
data() {
return {
props: { multiple: true, expandTrigger: 'click' },
options: [{
value: 1,
label: '杭州',
children: [{
value: 3,
label: '西湖'
}, {
value: 4,
label: '錢塘'
}, {
value: 7,
label: '上城'
}]
}, {
value: 2,
label: '成都',
children: [{
value: 5,
label: '青羊'
}, {
value: 6,
label: '武侯'
}]
}],
preValue:[]
}
},
methods:{
handleChange(val){
if (this.preValue.length > 0 && val.length > this.preValue.length) {
let newIndex;
let i = 0, j = 0;
while (i < val.length && j < this.preValue.length) {
if (val[i][0] === this.preValue[j][0] && val[i][1] === this.preValue[j][1]) {
i++;
j++;
} else {
//添加在中間的情況
newIndex = i;
break;
}
}
//添加在末尾的情況
if (j === this.preValue.length) {
newIndex = i;
}
let delIndex = val.findIndex((item, index) => index !== newIndex && item[0] === val[newIndex][0]);
if (delIndex >= 0) {
// 取消選擇的節(jié)點
let cancelIndex;
for (let i = 0; i < this.options.length; i++) {
if (this.options[i].value === val[delIndex][0]) {
for (let j = 0; j < this.options[i].children.length; j++) {
if (this.options[i].children[j].value === val[delIndex][1]) {
cancelIndex = j;
break;
}
}
break;
}
}
this.$nextTick(() => {
let panelId = this.$refs.cascade.panel.$refs.menu[1].$el.id; //其中menu[1]表示右側(cè)的面板 menu[0]即為左側(cè)的面板
let liId = document.getElementById(panelId + '-' + cancelIndex);
liId.children[0].click();
})
val[delIndex] = '';
val = val.filter(item => item !== '');
}
}
this.preValue = val;
}
}
};
</script>
<style lang='less'>
.test {
text-align: center;
margin-top: 200px;
.title {
display: block;
margin-bottom: 20px;
}
.cascader {
.el-input__inner {
width: 362px;
}
.el-cascader__tags {
display: flex;
flex-wrap: nowrap;
overflow-y: overlay;
margin-left: 2px;
}
.el-cascader__tags::-webkit-scrollbar {
width: 0;
height: 3px;
}
/*定義滾動條軌道 內(nèi)陰影+圓角*/
.el-cascader__tags::-webkit-scrollbar-track {
background-color: rgba(186, 203, 227, 0.3);
}
/*定義滑塊 內(nèi)陰影+圓角*/
.el-cascader__tags::-webkit-scrollbar-thumb {
background-color: #B3C2D7;
}
}
}
.hide {
.el-cascader-menu:first-of-type {
.el-cascader-node {
.el-checkbox {
display: none;
}
}
}
}
</style>到此這篇關于ElementUI級聯(lián)選擇器實現(xiàn)同一父級下最多只能選中一個子級的文章就介紹到這了,更多相關ElementUI級聯(lián)選擇器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
解決vue2中使用axios http請求出現(xiàn)的問題
下面小編就為大家分享一篇解決vue2中使用axios http請求出現(xiàn)的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03

