1.封装
根据官网配置项封装了下el-tree 方便维护和复用,有用的话点赞收藏叭~
<template>
<div class="my-tree">
<el-input
v-if="hasSearch"
v-model="filterText"
class="search-input"
placeholder="输入关键字进行过滤">
</el-input>
<slot></slot>
<el-tree
ref="myTree"
:icon-class="iconClass"
:filter-node-method="filterNodeMethod"
:default-checked-keys="defaultCheckedKeys"
:check-strictly="checkStrictly"
:show-checkbox="showCheckbox"
:default-expanded-keys="defaultExpandedKeys"
:highlight-current="highlightCurrent"
:check-on-click-node="checkOnClickNode"
:default-expand-all="defaultExpandAll"
:expand-on-click-node="expandOnClickNode"
:node-key="nodeKey"
:data="treeData"
:props="defaultProps"
:empty-text="emptyText"
:render-content="renderContent"
@node-click="nodeClick"
@check="check"
@check-change="checkChange"
@current-change="currentChange"
@node-expand="nodeExpand"
@node-collapse="nodeCollapse">
</el-tree>
</div>
</template>
<script>
export default {
name: 'MyTree',
props: {
nodeKey: {
type: String,
default: 'id'
},
// 树形控件展示数据
treeData: {
type: Array,
default: function () {
return []
}
},
// 默认展开的节点的 key 的数组
defaultExpandedKeys: {
type: Array,
default: function () {
return []
}
},
// props配置项
defaultProps: {
type: Object,
default: function () {
return {
label: 'label',
children: 'children',
disabled: function (data, node) {
return data
}
}
}
},
// 内容为空时的文案
emptyText: {
type: String,
default: '暂无数据'
},
// 是否高亮当前选中
highlightCurrent: {
type: Boolean,
default: false
},
// 是否默认展开所有节点
defaultExpandAll: {
type: Boolean,
default: false
},
// 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
expandOnClickNode: {
type: Boolean,
default: true
},
// 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
checkOnClickNode: {
type: Boolean,
default: false
},
// 节点是否可被选择
showCheckbox: {
type: Boolean,
default: false
},
// 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法
checkStrictly: {
type: Boolean,
default: false
},
// 默认勾选的节点的 key 的数组
defaultCheckedKeys: {
type: Array,
default: function () {
return []
}
},
// 是否需要搜索功能
hasSearch: {
type: Boolean,
default: false
},
// 自定义树节点的图标
iconClass: {
type: String,
default: ''
},
// 自定义节点内容
renderContent: {
type: Function,
default: function (h, { node, data, store }) {
return (
<span class="custom-tree-node">
<span>{node.label}</span>
</span>)
}
}
},
data() {
return {
filterText: '' // 关键字过滤值
}
},
watch: {
filterText(val) {
this.$refs.myTree.filter(val)
}
},
methods: {
// 节点被点击时的回调
nodeClick(data, node, self) {
this.$emit('nodeClick', { data, node, self })
},
// 当复选框被点击的时候触发
check(data, checkObj) {
this.$emit('check', { data, checkObj })
},
// 节点选中状态发生变化时的回调
checkChange(data, isChecked, childIsCheked) {
// 传递给 data 属性的数组中该节点所对应的对象、节点本身是否被选中、节点的子树中是否有被选中的节点
this.$emit('checkChange', { data, isChecked, childIsCheked })
},
// 当前选中节点变化时触发的事件
currentChange(data, node) {
this.$emit('currentChange', { data, node })
},
// 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏
filterNodeMethod(value, data, node) {
if (!value) return true
return data[this.defaultProps.label].indexOf(value) !== -1
},
// 节点被展开时触发的事件
nodeExpand(data, node, el) {
this.$emit('nodeExpand', { data, node, el })
},
// 节点被关闭时触发的事件
nodeCollapse(data, node, el) {
this.$emit('nodeCollapse', { data, node, el })
},
// 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点所组成的数组
getCheckedNodes(leafOnly = false, includeHalfChecked = false) {
return this.$refs.myTree.getCheckedNodes(leafOnly, includeHalfChecked)
},
// 设置目前勾选的节点,使用此方法必须设置 node-key 属性
setCheckedNodes(nodes) {
this.$refs.myTree.setCheckedNodes(nodes)
},
// 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所组成的数组
getCheckedKeys(leafOnly = false, includeHalfChecked = false) {
return this.$refs.myTree.getCheckedKeys(leafOnly, includeHalfChecked)
},
// 通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性
setCheckedKeys(keys, leafOnly = false) {
this.$refs.myTree.setCheckedKeys(keys, leafOnly)
},
// 通过 key / data 设置某个节点的勾选状态,使用此方法必须设置 node-key 属性
setChecked(keyordata, checked, deep = false) {
this.$refs.myTree.setChecked(keyordata, checked, deep)
},
// 若节点可被选择(即 show-checkbox 为 true),则返回目前半选中的节点所组成的数组
getHalfCheckedNodes() {
return this.$refs.myTree.getHalfCheckedNodes()
},
// 若节点可被选择(即 show-checkbox 为 true),则返回目前半选中的节点的 key 所组成的数组
getHalfCheckedKeys() {
return this.$refs.myTree.getHalfCheckedKeys()
},
// 获取当前被选中节点的 key,使用此方法必须设置 node-key 属性,若没有节点被选中则返回 null
getCurrentKey() {
return this.$refs.myTree.getCurrentKey()
},
// 获取当前被选中节点的 data,若没有节点被选中则返回 null
getCurrentNode() {
return this.$refs.myTree.getCurrentNode()
},
// 通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性
setCurrentKey(key) {
this.$refs.myTree.setCurrentKey(key)
},
// 通过 node 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性
setCurrentNode(node) {
this.$refs.myTree.setCurrentNode(node)
},
// 设置 node-key 属性 (node) 待被选节点的 node getNode 根据 data 或者 key 拿到 Tree 组件中的 node
getNode(data) {
return this.$refs.myTree.getNode(data)
},
// 删除 Tree 中的一个节点,使用此方法必须设置 node-key 属性
remove(data) {
this.$refs.myTree.remove(data)
},
// 为 Tree 中的一个节点追加一个子节点
append(data, parentNode) {
this.$refs.myTree.append(data, parentNode)
},
// 递归拉平数据
recursion(arr) {
return [].concat(...arr.map(item => {
if (item[this.defaultProps['children']]) {
let arr = [].concat(item, ...this.recursion(item[this.defaultProps['children']]))
delete item[this.defaultProps['children']]
return arr
}
return [].concat(item)
}
))
},
// 获取拉平的treeData数据
getFlatData() {
let cloneData = JSON.parse(JSON.stringify(this.treeData))
return this.recursion(cloneData)
}
}
}
</script>
<style lang="scss" scoped>
.my-tree {
.search-input {
margin-bottom: 10px;
}
}
</style>
2.使用
<template>
<div class="tree-box">
<my-tree ref="myTree" :tree-data="treeData" icon-class="el-icon-star-on" :default-checked-keys="defaultCheckedKeys" :show-checkbox="true" :default-expanded-keys="defaultExpandedKeys" :highlight-current="true" :check-on-click-node="false" :default-props="defaultProps" @nodeClick="nodeClick" @checkChange="checkChange" @check="check"></my-tree>
<div class="info-box">
<p>当前选中:{{ chooseObj.name||'-' }}</p>
<p>当前勾选:{{ curChecks||'-' }}</p>
</div>
<div class="btn-box">
<el-button type="primary" @click="getCheckedNodes">根据node获取勾选项Id</el-button>
<el-button type="primary" @click="setCheckedNodes">根据node设置勾选三级 3-2-2</el-button>
<el-button type="primary" @click="getCheckedKeys">根据key获取勾选项Id</el-button>
<el-button type="primary" @click="setCheckedKeys">根据key设置勾选三级 3-2-2</el-button>
<el-button type="primary" @click="setChecked">勾选三级 3-1-1</el-button>
</div>
</div>
</template>
<script>
import MyTree from '../../components/MyTree/index.vue'
export default {
components: { MyTree },
data() {
return {
treeData: [{
id: 1,
name: '一级 2',
child: [{
id: 3,
name: '二级 2-1',
child: [
{
id: 4,
name: '三级 3-1-1',
child: [{
id: 8,
name: '四级 4-1-1'
}, {
id: 9,
name: '四级 4-1-2',
disabled: true
}]
},
{
id: 5,
name: '三级 3-1-2',
disabled: true,
child: [{
id: 10,
name: '四级 4-1-3'
}, {
id: 11,
name: '四级 4-1-4',
disabled: true
}]
}]
}, {
id: 2,
name: '二级 2-2',
disabled: true,
child: [{
id: 6,
name: '三级 3-2-1'
}, {
id: 7,
name: '三级 3-2-2',
disabled: true
}]
}]
}],
defaultExpandedKeys: [5],
defaultCheckedKeys: [9],
defaultProps: {
label: 'name',
children: 'child'
},
chooseObj: {},
checkInfo: {
checkObj: {
checkedNodes: [{ name: '四级 4-1-2' }]
}
}
}
},
computed: {
curChecks() {
if (this.checkInfo && this.checkInfo.checkObj) {
return this.checkInfo.checkObj.checkedNodes.map(item => item.name).join('、')
} else {
return ''
}
}
},
methods: {
// 节点被点击时获取选中项
nodeClick(obj) {
this.chooseObj = obj.data
},
// 节点选中状态发生变化时的回调
checkChange(obj) {
},
// 当复选框被点击的时候触发
check(obj) {
this.checkInfo = obj
},
// 根据node获取当前勾选项
getCheckedNodes() {
let checkArr = this.$refs.myTree.getCheckedNodes(true, true)
this.$message.success(`当前勾选id有:${checkArr.map(item => item.id).join('、')}`)
},
// 根据node设置目前勾选的节点
setCheckedNodes() {
this.$refs.myTree.setCheckedNodes([{
id: 7,
name: '三级 3-2-2',
disabled: true
}])
},
// 根据key获取当前勾选项
getCheckedKeys() {
let checkArr = this.$refs.myTree.getCheckedKeys(true, true)
this.$message.success(`当前勾选id有:${checkArr.map(item => item).join('、')}`)
},
// 根据key设置目前勾选的节点
setCheckedKeys() {
this.$refs.myTree.setCheckedKeys([7])
},
// 勾选三级 3-1-1
setChecked() {
this.$refs.myTree.setChecked(4, !this.$refs.myTree.getNode(4).checked)
}
}
}
</script>
<style lang="scss" scoped>
.tree-box {
width: 60%;
margin: 0 auto;
::v-deep .el-tree-node__expand-icon {
font-size: 16px;
}
}
</style>
3.重置样式
如若要对不同的一级二级节点设置不同的样式可以参考这样:
/* 一级节点样式 */
>.el-tree-node>.el-tree-node__content {
height: 44px;
font-size: 14px;
color: #333;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
background-color: #F5F5F7;
margin-bottom: 8px;
padding-left: 12px !important;
}
/* 二级节点样式 */
>.el-tree-node .el-tree-node .el-tree-node__content {
height: 34px;
font-size: 13px;
color: #444;
margin-bottom: 8px;
padding-left: 36px !important;
&:before {
content: "";
display: inline-block;
width: 6px;
height: 6px;
background-color: #54B7AD;
border-radius: 50%;
margin-right: 8px;
}
}
/* 三级节点样式 */
>.el-tree-node .el-tree-node .el-tree-node .el-tree-node__content {
height: 30px;
font-size: 12px;
color: #444;
margin-bottom: 4px;
padding-left: 50px !important;
&:before {
display: none;
}
}