Element Tree 树形控件
本示例以 Vue Element Admin 项目为基础,介绍 Element Tree 树形控件
【注意:返回的数据是平级数据,前端自动递归处理】
1、/src/views/tree.vue
<template>
<div class="app-container">
<el-row>
<el-col :span="24">
<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>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<div class="grid-content bg-purple">
<el-tree ref="tree1" :data="list" node-key="menu_code" :props="defaultProps" default-expand-all @node-click="handleNodeClick"/>
</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple">
<el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input>
<el-tree ref="tree" :data="list" :props="defaultProps" default-expand-all :filter-node-method="filterNode" @node-click="handleNodeClick"></el-tree>
</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple-light">
<el-tree
ref="tree2"
:data="list"
show-checkbox
node-key="menu_code"
highlight-current
:default-expanded-keys="[1,2,3]"
:default-checked-keys="[5]"
:filter-node-method="filterNode"
:props="defaultProps"
@check-change="handleCheckChange"
@node-click="handleNodeClick"/>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
// import { getTreeMenus } from "@/api/tree";
import { jsonTree } from "@/utils/tree";
export default {
data() {
return {
filterText: '',
list: [],
defaultProps: {
id: "menu_code",
label: "menu_name",
children: "children"
},
listQuery: {
resource_code: 1,
page: 1,
per_page: 20
}
};
},
watch: {
filterText(val) {
console.log(val)
this.$refs.tree.filter(val);
}
},
created() {
this.getList();
},
methods: {
async getList() {
// 动态查询
// getTreeMenus(this.listQuery)
// .then(res => {
// this.list = jsonTree(res.data.items, {
// id: "menu_code",
// pid: "parent_code",
// children: "children"
// });
// })
// .catch(err => {
// console.error(err);
// console.log("修改出错了");
// });
//本地数据
this.list = jsonTree([
{ "menu_code": 1,"menu_name": "一级菜单 1","parent_code": 0 },
{ "menu_code": 2,"menu_name": "一级菜单 2","parent_code": 0 },
{ "menu_code": 3,"menu_name": "一级菜单 3","parent_code": 0 },
{ "menu_code": 4,"menu_name": "二级菜单 1-1","parent_code": 1 },
{ "menu_code": 5,"menu_name": "二级菜单 2-1","parent_code": 2 },
{ "menu_code": 6,"menu_name": "二级菜单 3-1","parent_code": 3 },
{ "menu_code": 7,"menu_name": "二级菜单 3-2","parent_code": 3 },
{ "menu_code": 8,"menu_name": "二级菜单 3-3","parent_code": 3 },
{ "menu_code": 9,"menu_name": "三级菜单 3-3-1","parent_code": 8 },
{ "menu_code": 10,"menu_name": "三级菜单 3-3-2","parent_code": 8 },
{ "menu_code": 11,"menu_name": "四级菜单 3-3-2-1","parent_code": 10 },
{ "menu_code": 12,"menu_name": "四级菜单 3-3-2-2","parent_code": 10 },
{ "menu_code": 13,"menu_name": "四级菜单 3-3-2-3","parent_code": 10 }
],
{
id: "menu_code",
pid: "parent_code",
children: "children"
})
},
handleCheckChange(data, checked, indeterminate) {
console.log(data, checked, indeterminate);
},
handleNodeClick(data) {
console.log(JSON.stringify(data))
this.filterText = data.menu_name
},
filterNode(value, data) {
if (!value) return true;
console.log(JSON.stringify(data))
//return data.label.indexOf(value) !== -1;//官方写法
return data.menu_name.indexOf(value) !== -1;//自定义写法
},
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() {
var arr = ['menu68','menu66','menu65'];
this.$refs.tree.setCheckedKeys(arr);
},
resetChecked() {
this.$refs.tree.setCheckedKeys([]);
}
// renderContent(h, { node, data, store }) {},
}
};
</script>
<style>
.el-row { margin-bottom: 20px; &:last-child { margin-bottom: 0; }}
.el-col { border-radius: 4px; }
.bg-purple-dark { background: #99a9bf; }
.bg-purple { background: #d3dce6; }
.bg-purple-light { background: #e5e9f2; }
.grid-content { border-radius: 4px; min-height: 36px; }
.row-bg { padding: 10px 0; background-color: #f9fafc; }
</style>
2、/src/api/tree.js
import request from '@/utils/request'
export function getTreeMenus(query) {
return request({
url: '/v1/menus',
method: 'get',
params: query
})
}
3、/src/utils/tree.js
export function jsonTree(data, config) {
var id = config.id || "id",
pid = config.pid || "pid",
children = config.children || "children";
var idMap = [],
newIdMap = [],
jsonTree = [];
data.forEach(function (v) {
idMap[v[id]] = v;
});
data.forEach(function (v) {
var parent = idMap[v[pid]];
delete v.parent;
if (parent) {
!parent[children] && (parent[children] = []);
parent[children].push(v);
} else {
jsonTree.push(v);
}
});
return jsonTree;
}
4、服务端 API 接口返回 json 数据
{
"data": {
"items": [
{ "menu_code": 1,"menu_name": "一级菜单 1","parent_code": 0 },
{ "menu_code": 2,"menu_name": "一级菜单 2","parent_code": 0 },
{ "menu_code": 3,"menu_name": "一级菜单 3","parent_code": 0 },
{ "menu_code": 4,"menu_name": "二级菜单 1-1","parent_code": 1 },
{ "menu_code": 5,"menu_name": "二级菜单 2-1","parent_code": 2 },
{ "menu_code": 6,"menu_name": "二级菜单 3-1","parent_code": 3 }
],
"total": 6,
"page_count": 1
},
"code": "200",
"msg": null
}
*
*
*