ElementUI 的Tree Tree 選單樹形控制元件
Tree 樹形控制元件
Tree 樹形控制元件
Tree 樹形控制元件
用清晰的層級結構展示資訊,可展開或摺疊。
基礎用法
基礎的樹形結構展示。
<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick"></el-tree>
<script>
export default {
data() {
return {
data: [{
label: '一級 1',
children: [{
label: '二級 1-1',
children: [{
label: '三級 1-1-1'
}]
}]
}, {
label: '一級 2',
children: [{
label: '二級 2-1',
children: [{
label: '三級 2-1-1'
}]
}, {
label: '二級 2-2',
children: [{
label: '三級 2-2-1'
}]
}]
}, {
label: '一級 3',
children: [{
label: '二級 3-1',
children: [{
label: '三級 3-1-1'
}]
}, {
label: '二級 3-2',
children: [{
label: '三級 3-2-1'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
};
</script>
可選擇
適用於需要選擇層級時使用。
本例還展示了動態載入節點資料的方法。
<el-tree
:props="props"
:load="loadNode"
lazy
show-checkbox
@check-change="handleCheckChange">
</el-tree><script>
export default {
data() {
return {
props: {
label: 'name',
children: 'zones'
},
count: 1
};
},
methods: {
handleCheckChange(data, checked, indeterminate) {
console.log(data, checked, indeterminate);
},
handleNodeClick(data) {
console.log(data);
},
loadNode(node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'region1' }, { name: 'region2' }]);
}
if (node.level > 3) return resolve([]);var hasChild; if (node.data.name === 'region1') { hasChild = true; } else if (node.data.name === 'region2') { hasChild = false; } else { hasChild = Math.random() > 0.5; } setTimeout(() => { var data; if (hasChild) { data = [{ name: 'zone' + this.count++ }, { name: 'zone' + this.count++ }]; } else { data = []; } resolve(data); }, 500); } }
};
</script>
懶載入自定義葉子節點
由於在點選節點時才進行該層資料的獲取,預設情況下 Tree 無法預知某個節點是否為葉子節點,所以會為每個節點新增一個下拉按鈕,如果節點沒有下層資料,則點選後下拉按鈕會消失。同時,你也可以提前告知 Tree 某個節點是否為葉子節點,從而避免在葉子節點前渲染下拉按鈕。
<el-tree
:props="props1"
:load="loadNode1"
lazy
show-checkbox>
</el-tree><script>
export default {
data() {
return {
props1: {
label: 'name',
children: 'zones',
isLeaf: 'leaf'
},
};
},
methods: {
loadNode1(node, resolve) {
if (node.level === 0) {
return resolve([{ name: 'region' }]);
}
if (node.level > 1) return resolve([]);setTimeout(() => { const data = [{ name: 'leaf', leaf: true }, { name: 'zone' }]; resolve(data); }, 500); } }
};
</script>
預設展開和預設選中
可將 Tree 的某些節點設定為預設展開或預設選中
分別通過default-expanded-keys
和default-checked-keys
設定預設展開和預設選中的節點。需要注意的是,此時必須設定node-key
,其值為節點資料中的一個欄位名,該欄位在整棵樹中是唯一的。
<el-tree
:data="data2"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]"
:props="defaultProps">
</el-tree>
<script>
export default {
data() {
return {
data2: [{
id: 1,
label: '一級 1',
children: [{
id: 4,
label: '二級 1-1',
children: [{
id: 9,
label: '三級 1-1-1'
}, {
id: 10,
label: '三級 1-1-2'
}]
}]
}, {
id: 2,
label: '一級 2',
children: [{
id: 5,
label: '二級 2-1'
}, {
id: 6,
label: '二級 2-2'
}]
}, {
id: 3,
label: '一級 3',
children: [{
id: 7,
label: '二級 3-1'
}, {
id: 8,
label: '二級 3-2'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
}
};
</script>
禁用狀態
可將 Tree 的某些節點設定為禁用狀態
通過disabled
設定禁用狀態。
<el-tree
:data="data3"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]">
</el-tree>
<script>
export default {
data() {
return {
data3: [{
id: 1,
label: '一級 2',
children: [{
id: 3,
label: '二級 2-1',
children: [{
id: 4,
label: '三級 3-1-1'
}, {
id: 5,
label: '三級 3-1-2',
disabled: true
}]
}, {
id: 2,
label: '二級 2-2',
disabled: true,
children: [{
id: 6,
label: '三級 3-2-1'
}, {
id: 7,
label: '三級 3-2-2',
disabled: true
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
}
};
</script>
樹節點的選擇
通過 node 獲取通過 key 獲取通過 node 設定通過 key 設定清空
本例展示如何獲取和設定選中節點。獲取和設定各有兩種方式:通過 node 或通過 key。如果需要通過 key 來獲取或設定,則必須設定node-key
。
<el-tree
:data="data2"
show-checkbox
default-expand-all
node-key="id"
ref="tree"
highlight-current
:props="defaultProps">
</el-tree><div class="buttons">
<el-button @click="getCheckedNodes">通過 node 獲取</el-button>
<el-button @click="getCheckedKeys">通過 key 獲取</el-button>
<el-button @click="setCheckedNodes">通過 node 設定</el-button>
<el-button @click="setCheckedKeys">通過 key 設定</el-button>
<el-button @click="resetChecked">清空</el-button>
</div><script>
export default {
methods: {
getCheckedNodes() {
console.log(this.$refs.tree.getCheckedNodes());
},
getCheckedKeys() {
console.log(this.$refs.tree.getCheckedKeys());
},
setCheckedNodes() {
this.$refs.tree.setCheckedNodes([{
id: 5,
label: '二級 2-1'
}, {
id: 9,
label: '三級 1-1-1'
}]);
},
setCheckedKeys() {
this.$refs.tree.setCheckedKeys([3]);
},
resetChecked() {
this.$refs.tree.setCheckedKeys([]);
}
},data() { return { data2: [{ id: 1, label: '一級 1', children: [{ id: 4, label: '二級 1-1', children: [{ id: 9, label: '三級 1-1-1' }, { id: 10, label: '三級 1-1-2' }] }] }, { id: 2, label: '一級 2', children: [{ id: 5, label: '二級 2-1' }, { id: 6, label: '二級 2-2' }] }, { id: 3, label: '一級 3', children: [{ id: 7, label: '二級 3-1' }, { id: 8, label: '二級 3-2' }] }], defaultProps: { children: 'children', label: 'label' } }; }
};
</script>
自定義節點內容
節點的內容支援自定義,可以在節點區新增按鈕或圖示等內容
可以通過兩種方法進行樹節點內容的自定義:render-content
和 scoped slot。使用render-content
指定渲染函式,該函式返回需要的節點區內容即可。渲染函式的用法請參考 Vue 文件。使用 scoped slot 會傳入兩個引數node
和data
,分別表示當前節點的 Node 物件和當前節點的資料。注意:由於 jsfiddle 不支援 JSX 語法,所以render-content
示例在 jsfiddle 中無法執行。但是在實際的專案中,只要正確地配置了相關依賴,就可以正常執行。
<div class="custom-tree-container">
<div class="block">
<p>使用 render-content</p>
<el-tree
:data="data4"
show-checkbox
node-key="id"
default-expand-all
:expand-on-click-node="false"
:render-content="renderContent">
</el-tree>
</div>
<div class="block">
<p>使用 scoped slot</p>
<el-tree
:data="data5"
show-checkbox
node-key="id"
default-expand-all
:expand-on-click-node="false">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<el-button
type="text"
size="mini"
@click="() => append(data)">
Append
</el-button>
<el-button
type="text"
size="mini"
@click="() => remove(node, data)">
Delete
</el-button>
</span>
</span>
</el-tree>
</div>
</div><script>
let id = 1000;export default {
data() {
const data = [{
id: 1,
label: '一級 1',
children: [{
id: 4,
label: '二級 1-1',
children: [{
id: 9,
label: '三級 1-1-1'
}, {
id: 10,
label: '三級 1-1-2'
}]
}]
}, {
id: 2,
label: '一級 2',
children: [{
id: 5,
label: '二級 2-1'
}, {
id: 6,
label: '二級 2-2'
}]
}, {
id: 3,
label: '一級 3',
children: [{
id: 7,
label: '二級 3-1'
}, {
id: 8,
label: '二級 3-2'
}]
}];
return {
data4: JSON.parse(JSON.stringify(data)),
data5: JSON.parse(JSON.stringify(data))
}
},methods: { append(data) { const newChild = { id: id++, label: 'testtest', children: [] }; if (!data.children) { this.$set(data, 'children', []); } data.children.push(newChild); }, remove(node, data) { const parent = node.parent; const children = parent.data.children || parent.data; const index = children.findIndex(d => d.id === data.id); children.splice(index, 1); }, renderContent(h, { node, data, store }) { return ( <span class="custom-tree-node"> <span>{node.label}</span> <span> <el-button size="mini" type="text" on-click={ () => this.append(data) }>Append</el-button> <el-button size="mini" type="text" on-click={ () => this.remove(node, data) }>Delete</el-button> </span> </span>); } }
};
</script>
<style>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>
節點過濾
通過關鍵字過濾樹節點
在需要對節點進行過濾時,呼叫 Tree 例項的filter
方法,引數為關鍵字。需要注意的是,此時需要設定filter-node-method
,值為過濾函式。
<el-input
placeholder="輸入關鍵字進行過濾"
v-model="filterText">
</el-input><el-tree
class="filter-tree"
:data="data2"
:props="defaultProps"
default-expand-all
:filter-node-method="filterNode"
ref="tree2">
</el-tree><script>
export default {
watch: {
filterText(val) {
this.$refs.tree2.filter(val);
}
},methods: { filterNode(value, data) { if (!value) return true; return data.label.indexOf(value) !== -1; } }, data() { return { filterText: '', data2: [{ id: 1, label: '一級 1', children: [{ id: 4, label: '二級 1-1', children: [{ id: 9, label: '三級 1-1-1' }, { id: 10, label: '三級 1-1-2' }] }] }, { id: 2, label: '一級 2', children: [{ id: 5, label: '二級 2-1' }, { id: 6, label: '二級 2-2' }] }, { id: 3, label: '一級 3', children: [{ id: 7, label: '二級 3-1' }, { id: 8, label: '二級 3-2' }] }], defaultProps: { children: 'children', label: 'label' } }; }
};
</script>
手風琴模式
對於同一級的節點,每次只能展開一個
<el-tree
:data="data"
:props="defaultProps"
accordion
@node-click="handleNodeClick">
</el-tree>
<script>
export default {
data() {
return {
data: [{
label: '一級 1',
children: [{
label: '二級 1-1',
children: [{
label: '三級 1-1-1'
}]
}]
}, {
label: '一級 2',
children: [{
label: '二級 2-1',
children: [{
label: '三級 2-1-1'
}]
}, {
label: '二級 2-2',
children: [{
label: '三級 2-2-1'
}]
}]
}, {
label: '一級 3',
children: [{
label: '二級 3-1',
children: [{
label: '三級 3-1-1'
}]
}, {
label: '二級 3-2',
children: [{
label: '三級 3-2-1'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleNodeClick(data) {
console.log(data);
}
}
};
</script>
可拖拽節點
通過 draggable 屬性可讓節點變為可拖拽。
<el-tree
:data="data6"
node-key="id"
default-expand-all
@node-drag-start="handleDragStart"
@node-drag-enter="handleDragEnter"
@node-drag-leave="handleDragLeave"
@node-drag-over="handleDragOver"
@node-drag-end="handleDragEnd"
@node-drop="handleDrop"
draggable
:allow-drop="allowDrop"
:allow-drag="allowDrag">
</el-tree>
<script>
export default {
data() {
return {
data6: [{
id: 1,
label: '一級 1',
children: [{
id: 4,
label: '二級 1-1',
children: [{
id: 9,
label: '三級 1-1-1'
}, {
id: 10,
label: '三級 1-1-2'
}]
}]
}, {
id: 2,
label: '一級 2',
children: [{
id: 5,
label: '二級 2-1'
}, {
id: 6,
label: '二級 2-2'
}]
}, {
id: 3,
label: '一級 3',
children: [{
id: 7,
label: '二級 3-1'
}, {
id: 8,
label: '二級 3-2',
children: [{
id: 11,
label: '三級 3-2-1'
}, {
id: 12,
label: '三級 3-2-2'
}, {
id: 13,
label: '三級 3-2-3'
}]
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
},
methods: {
handleDragStart(node, ev) {
console.log('drag start', node);
},
handleDragEnter(draggingNode, dropNode, ev) {
console.log('tree drag enter: ', dropNode.label);
},
handleDragLeave(draggingNode, dropNode, ev) {
console.log('tree drag leave: ', dropNode.label);
},
handleDragOver(draggingNode, dropNode, ev) {
console.log('tree drag over: ', dropNode.label);
},
handleDragEnd(draggingNode, dropNode, dropType, ev) {
console.log('tree drag end: ', dropNode && dropNode.label, dropType);
},
handleDrop(draggingNode, dropNode, dropType, ev) {
console.log('tree drop: ', dropNode.label, dropType);
},
allowDrop(draggingNode, dropNode, type) {
if (dropNode.data.label === '二級 3-1') {
return type !== 'inner';
} else {
return true;
}
},
allowDrag(draggingNode) {
return draggingNode.data.label.indexOf('三級 3-2-2') === -1;
}
}
};
</script>
Attributes
引數 |
說明 |
型別 |
可選值 |
預設值 |
---|---|---|---|---|
data |
展示資料 |
array |
— |
— |
empty-text |
內容為空的時候展示的文字 |
String |
— |
— |
node-key |
每個樹節點用來作為唯一標識的屬性,整棵樹應該是唯一的 |
String |
— |
— |
props |
配置選項,具體看下錶 |
object |
— |
— |
render-after-expand |
是否在第一次展開某個樹節點後才渲染其子節點 |
boolean |
— |
true |
load |
載入子樹資料的方法,僅當 lazy 屬性為true 時生效 |
function(node, resolve) |
— |
— |
render-content |
樹節點的內容區的渲染 Function |
Function(h, { node, data, store } |
— |
— |
highlight-current |
是否高亮當前選中節點,預設值是 false。 |
boolean |
— |
false |
default-expand-all |
是否預設展開所有節點 |
boolean |
— |
false |
expand-on-click-node |
是否在點選節點的時候展開或者收縮節點, 預設值為 true,如果為 false,則只有點箭頭圖示的時候才會展開或者收縮節點。 |
boolean |
— |
true |
check-on-click-node |
是否在點選節點的時候選中節點,預設值為 false,即只有在點選複選框時才會選中節點。 |
boolean |
— |
false |
auto-expand-parent |
展開子節點的時候是否自動展開父節點 |
boolean |
— |
true |
default-expanded-keys |
預設展開的節點的 key 的陣列 |
array |
— |
— |
show-checkbox |
節點是否可被選擇 |
boolean |
— |
false |
check-strictly |
在顯示覆選框的情況下,是否嚴格的遵循父子不互相關聯的做法,預設為 false |
boolean |
— |
false |
default-checked-keys |
預設勾選的節點的 key 的陣列 |
array |
— |
— |
filter-node-method |
對樹節點進行篩選時執行的方法,返回 true 表示這個節點可以顯示,返回 false 則表示這個節點會被隱藏 |
Function(value, data, node) |
— |
— |
accordion |
是否每次只打開一個同級樹節點展開 |
boolean |
— |
false |
indent |
相鄰級節點間的水平縮排,單位為畫素 |
number |
— |
16 |
lazy |
是否懶載入子節點,需與 load 方法結合使用 |
boolean |
— |
false |
draggable |
是否開啟拖拽節點功能 |
boolean |
— |
false |
allow-drag |
判斷節點能否被拖拽 |
Function(node) |
— |
— |
allow-drop |
拖拽時判定目標節點能否被放置。type 引數有三種情況:'prev'、'inner' 和 'next',分別表示放置在目標節點前、插入至目標節點和放置在目標節點後 |
Function(draggingNode, dropNode, type) |
— |
— |
props
引數 |
說明 |
型別 |
可選值 |
預設值 |
---|---|---|---|---|
label |
指定節點標籤為節點物件的某個屬性值 |
string, function(data, node) |
— |
— |
children |
指定子樹為節點物件的某個屬性值 |
string |
— |
— |
disabled |
指定節點選擇框是否禁用為節點物件的某個屬性值 |
boolean, function(data, node) |
— |
— |
isLeaf |
指定節點是否為葉子節點,僅在指定了 lazy 屬性的情況下生效 |
boolean, function(data, node) |
— |
— |
方法
Tree
內部使用了 Node 型別的物件來包裝使用者傳入的資料,用來儲存目前節點的狀態。 Tree
擁有如下方法:
方法名 |
說明 |
引數 |
---|---|---|
filter |
對樹節點進行篩選操作 |
接收一個任意型別的引數,該引數會在 filter-node-method 中作為第一個引數 |
updateKeyChildren |
通過 keys 設定節點子元素,使用此方法必須設定 node-key 屬性 |
(key, data) 接收兩個引數,1. 節點 key 2. 節點資料的陣列 |
getCheckedNodes |
若節點可被選擇(即 show-checkbox為 true),則返回目前被選中的節點所組成的陣列 |
(leafOnly, includeHalfChecked) 接收兩個 boolean 型別的引數,1. 是否只是葉子節點,預設值為 false 2. 是否包含半選節點,預設值為 false |
setCheckedNodes |
設定目前勾選的節點,使用此方法必須設定 node-key 屬性 |
(nodes) 接收勾選節點資料的陣列 |
getCheckedKeys |
若節點可被選擇(即 show-checkbox為 true),則返回目前被選中的節點的 key 所組成的陣列 |
(leafOnly) 接收一個 boolean 型別的引數,若為 true 則僅返回被選中的葉子節點的 keys,預設值為 false |
setCheckedKeys |
通過 keys 設定目前勾選的節點,使用此方法必須設定 node-key 屬性 |
(keys, leafOnly) 接收兩個引數,1. 勾選節點的 key 的陣列 2. boolean 型別的引數,若為 true 則僅設定葉子節點的選中狀態,預設值為 false |
setChecked |
通過 key / data 設定某個節點的勾選狀態,使用此方法必須設定 node-key 屬性 |
(key/data, checked, deep) 接收三個引數,1. 勾選節點的 key 或者 data 2. boolean 型別,節點是否選中 3. boolean 型別,是否設定子節點 ,預設為 false |
getHalfCheckedNodes |
若節點可被選擇(即 show-checkbox為 true),則返回目前半選中的節點所組成的陣列 |
- |
getHalfCheckedKeys |
若節點可被選擇(即 show-checkbox為 true),則返回目前半選中的節點的 key 所組成的陣列 |
- |
getCurrentKey |
獲取當前被選中節點的 key,使用此方法必須設定 node-key 屬性,若沒有節點被選中則返回 null |
— |
getCurrentNode |
獲取當前被選中節點的 node,若沒有節點被選中則返回 null |
— |
setCurrentKey |
通過 key 設定某個節點的當前選中狀態,使用此方法必須設定 node-key 屬性 |
(key) 待被選節點的 key,若為 null 則取消當前高亮的節點 |
setCurrentNode |
通過 node 設定某個節點的當前選中狀態,使用此方法必須設定 node-key 屬性 |
(node) 待被選節點的 node |
getNode |
根據 data 或者 key 拿到 Tree 元件中的 node |
(data) 要獲得 node 的 key 或者 data |
remove |
刪除 Tree 中的一個節點,使用此方法必須設定 node-key 屬性 |
(data) 要刪除的節點的 data 或者 node |
append |
為 Tree 中的一個節點追加一個子節點 |
(data, parentNode) 接收兩個引數,1. 要追加的子節點的 data 2. 子節點的 parent 的 data、key 或者 node |
insertBefore |
為 Tree 的一個節點的前面增加一個節點 |
(data, refNode) 接收兩個引數,1. 要增加的節點的 data 2. 要增加的節點的後一個節點的 data、key 或者 node |
insertAfter |
為 Tree 的一個節點的後面增加一個節點 |
(data, refNode) 接收兩個引數,1. 要增加的節點的 data 2. 要增加的節點的前一個節點的 data、key 或者 node |
Events
事件名稱 |
說明 |
回撥引數 |
---|---|---|
node-click |
節點被點選時的回撥 |
共三個引數,依次為:傳遞給 data 屬性的陣列中該節點所對應的物件、節點對應的 Node、節點元件本身。 |
node-contextmenu |
當某一節點被滑鼠右鍵點選時會觸發該事件 |
共四個引數,依次為:event、傳遞給 data 屬性的陣列中該節點所對應的物件、節點對應的 Node、節點元件本身。 |
check-change |
節點選中狀態發生變化時的回撥 |
共三個引數,依次為:傳遞給 data 屬性的陣列中該節點所對應的物件、節點本身是否被選中、節點的子樹中是否有被選中的節點 |
check |
當複選框被點選的時候觸發 |
共兩個引數,依次為:傳遞給 data 屬性的陣列中該節點所對應的物件、樹目前的選中狀態物件,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四個屬性 |
current-change |
當前選中節點變化時觸發的事件 |
共兩個引數,依次為:當前節點的資料,當前節點的 Node 物件 |
node-expand |
節點被展開時觸發的事件 |
共三個引數,依次為:傳遞給 data 屬性的陣列中該節點所對應的物件、節點對應的 Node、節點元件本身 |
node-collapse |
節點被關閉時觸發的事件 |
共三個引數,依次為:傳遞給 data 屬性的陣列中該節點所對應的物件、節點對應的 Node、節點元件本身 |
node-drag-start |
節點開始拖拽時觸發的事件 |
共兩個引數,依次為:被拖拽節點對應的 Node、event |
node-drag-enter |
拖拽進入其他節點時觸發的事件 |
共三個引數,依次為:被拖拽節點對應的 Node、所進入節點對應的 Node、event |
node-drag-leave |
拖拽離開某個節點時觸發的事件 |
共三個引數,依次為:被拖拽節點對應的 Node、所離開節點對應的 Node、event |
node-drag-over |
在拖拽節點時觸發的事件(類似瀏覽器的 mouseover 事件) |
共三個引數,依次為:被拖拽節點對應的 Node、當前進入節點對應的 Node、event |
node-drag-end |
拖拽結束時(可能未成功)觸發的事件 |
共四個引數,依次為:被拖拽節點對應的 Node、結束拖拽時最後進入的節點(可能為空)、被拖拽節點的放置位置(before、after、inner)、event |
node-drop |
拖拽成功完成時觸發的事件 |
共四個引數,依次為:被拖拽節點對應的 Node、結束拖拽時最後進入的節點、被拖拽節點的放置位置(before、after、inner)、event |
Scoped Slot
name |
說明 |
---|---|
— |
自定義樹節點的內容,引數為 { node, data } |
本文件系騰訊云云+社群成員共同維護,如有問題請聯絡 [email protected]