本來是不太想動的...
無可奈何,看到一句話【業精於勤, 荒於嬉】便還是動手寫一寫加深理解的同時給以后的自己留個備份吧...
element-ui Tree組件如何給具有懶加載的tree設置半選效果?這也是讓我很頭疼的一個問題...
因為數據不是一口氣都請求回來的,故而當你進入頁面的時候,你有的數據只是你能看到的第一層節點,但是由於某種情況需要做數據的回顯,這就會產生問題了。
當然,如果數據不是很多的情況下自然可以獲取全部的數據,然后給tree設置上默認選中的節點,這個問題自然也就不存在了。
但,若是數據量龐大且級數很深的情況下,一般接口都會根據前端傳給后端的標識來返回某層數據,這樣就會產生一個問題:
【當你設置了默認選中的子節點,但是由於剛進入頁面此時tree中數據暫是沒有這個子節點時,其父節點並不會具有半選效果】如下圖所示:

我還是一如既往粗魯的找度娘詢問了一番,沒有找到想要的結果...
直到我在element-ui的git上翻尋前人智慧時,遇到了Ta...
這個大哥給了一個非常棒的想法,並且成功了讓心猿意馬的我眼前一亮【原來還可以這般巧妙的使用對象的引用?!】

好了,廢話不多說了,先看下使用前的代碼吧:
(當然下面使用到的這幾個屬性在官網都有,哪個不懂的看下文檔就行了)
<template>
<div class="lazy-tree">
<h2>展示:</h2>
<el-tree
:props="props"
:load="loadNode"
lazy
node-key="id"
:default-checked-keys="[1001]"
show-checkbox>
</el-tree>
</div>
</template>
<script>
export default {
data () {
return {
props: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
}
}
},
methods: {
// 動態獲取葉子節點的方法
loadNode (node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'region', id: 1000 }])
}
if (node.level > 1) return resolve([])
setTimeout(() => {
const data = [{
id: 1001,
name: 'leaf',
leaf: true
}, {
name: 'zone'
}]
resolve(data)
}, 500)
}
}
}
</script>
<style>
.lazy-tree{
padding: 20px;
width: 500px;
height: 500px;
background-color: #70E2FA;
}
</style>
然后這里是使用后的代碼:
(這里我多加了一些方法用於模仿請求接口啥的都不是重點關注的...核心內容還是這個 setHalfCheckedNodes (key) )
<template>
<div class="lazy-tree">
<h2>展示:</h2>
<el-tree
ref="lazyTree"
:props="props"
:load="loadNode"
lazy
node-key="id"
:default-checked-keys="defaultCheckedKeys"
show-checkbox>
</el-tree>
</div>
</template>
<script>
export default {
data () {
return {
props: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
},
// 默認選中的節點
defaultCheckedKeys: []
}
},
mounted () {
this.getDetails()
},
methods: {
// 動態獲取葉子節點的方法
loadNode (node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'region', id: 1000 }])
}
if (node.level > 1) return resolve([])
setTimeout(() => {
const data = [
{
id: 1001,
name: 'leaf',
leaf: true
},
{
id: 1002,
name: 'zone',
leaf: true
}
]
resolve(data)
}, 500)
},
// 模擬的詳情接口
detail () {
return new Promise((resolve, reject) => {
const data = [{ id: 1001, name: 'leaf', parent: 1000 }]
resolve(data)
})
},
// 獲取回顯數據
async getDetails () {
const res = await this.detail()
res.forEach(item => {
this.defaultCheckedKeys.push(item.id) // 此處應有去重
this.setHalfCheckedNodes(item.parent)
})
},
// 設置半選狀態
setHalfCheckedNodes (key) {
const node = this.$refs['lazyTree'].getNode(key)
if (node) { // 此處應判斷當前節點的checked屬性是否為true,是則不必半選
node.indeterminate = true
}
}
}
}
</script>
<style>
.lazy-tree{
padding: 20px;
width: 500px;
height: 500px;
background-color: #70E2FA;
}
</style>
總結:
這里我只是輕描淡寫的用2層的tree大致講述了如何設置設置半選狀態。
但,即使是更深的tree也還是萬變不離其宗,用的還是這個方法,只不過判斷第二層是否需要設置半選的時候需要再給第一層再設置下半選。
因為,在你展開第二層tree的時候,如果【選中】狀態的葉子節點在第三層,由於此時tree上還沒有第三層的數據,
所以組件自動計算發現沒有需要有半選和全選的按鈕,就會清空你設置好的半選狀態。
另外,在 setHalfCheckedNodes 中我說的需要判斷當前node的isChecked指的就是下圖中的【節點本身是否被選中】

