目录
第一种 切换箭头打开和折叠 :
<template>
<div class="tree">
<el-tree
:data="data5"
:props="props"
show-checkbox
node-key="id"
default-expand-all
>
</el-tree>
</div>
</template>
<script>
export default {
data() {
return {
props: {
label: "label",
children: "children",
},
data5: [
{
id: 1,
label: "一级 1",
icon: "el-icon-success",
children: [
{
id: 4,
label: "二级 1-1",
children: [
{
id: 9,
label: "三级 1-1-1",
icon: "el-icon-info",
},
{
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",
},
],
},
],
};
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-icon-caret-right:before {
content: "y";
font-size: 16px;
}
::v-deep .expanded:before {
content: "x";
font-size: 16px;
}
</style>
第二种 修改箭头打开和折叠 + 动画:
<template>
<div class="tree">
<el-tree
icon-class="user"
:data="data5"
:props="props"
show-checkbox
node-key="id"
default-expand-all
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span> <i :class="node.icon"></i>{{ node.label }} </span>
</span>
</el-tree>
</div>
</template>
<script>
export default {
data() {
return {
props: {
label: "label",
children: "children",
},
data5: [
{
id: 1,
label: "一级 1",
icon: "el-icon-success",
children: [
{
id: 4,
label: "二级 1-1",
children: [
{
id: 9,
label: "三级 1-1-1",
icon: "el-icon-info",
},
{
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",
},
],
},
],
};
},
};
</script>
<style lang="scss" scoped>
/deep/.user {
// background: url("../../assets/logo.png");
background: url("../../assets/logo.png");
box-sizing: border-box;
background-size: 100%;
background-repeat: no-repeat;
}
/deep/.el-tree-node__expand-icon {
transform: rotate(-90deg);
}
/deep/.el-tree-node__expand-icon.expanded {
transform: rotate(0deg);
}
</style>
第三种 修改箭头打开和折叠 + 一二级自定义图标:
<template> <div class="ov-container"> <el-tree :data="data" :props="defaultProps"> <span class="custom-tree-node" slot-scope="{ node, data }"> <i v-if="node.level == 1" class="province" /> <i v-else-if="node.level == 2" class="city" /> <i v-else-if="node.level == 3" /> {{ data.label }} </span> </el-tree> </div> </template> <script> export default { name: "index", 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", }, ], }, ], }, { label: "一级 4", children: [ { label: "三级 3-2-1", }, ], }, { label: "一级 4", }, ], }; }, }; </script> <style scoped lang="scss"> .ov-container { height: calc(100vh - 80px); background: #ffffff; border-radius: 5px; margin: 10px; } .province { background: url("../../assets/logo.png"); width: 17px; height: 14px; display: inline-block; background-size: 100% 100%; } .city { background: url("../../assets/图片2.png") no-repeat; width: 17px; height: 14px; display: inline-block; background-size: 100% 100%; } .line { background: url("../../assets/百花.png") no-repeat; background-size: 100%; width: 17px; height: 14px; display: inline-block; } .data { background: url("../../assets/花朵.png") no-repeat; background-size: 100%; width: 17px; height: 14px; display: inline-block; } .el-tree /deep/ .el-tree-node__expand-icon.expanded { -webkit-transform: rotate(0deg); transform: rotate(0deg); } //有子节点 且未展开 .el-tree /deep/ .el-icon-caret-right:before { // background: url("../../assets/logo.png") no-repeat 0 0; content: "√"; display: block; width: 12px; height: 12px; font-size: 16px; background-size: 100% 100%; } //有子节点 且已展开 .el-tree /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before { // background: url("../../assets/logo.png") no-repeat 0 0; content: "x"; display: block; width: 12px; height: 12px; font-size: 12px; background-size: 100% 100%; } //没有子节点 .el-tree /deep/.el-tree-node__expand-icon.is-leaf::before { // background: url("../../assets/logo.png") no-repeat 0 0; content: ""; display: block; width: 12px; height: 12px; font-size: 16px; background-size: 100% 100%; } </style>
第四种在el-tree前加复选框和图标
第五种 Vue3 + ts 封装
<template>
<!--
ref="treeRef" 用于获取树型组件的实例
:check-strictly="checkStrictly" 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法
:indent="0" 树节点的缩进距离,设为0即取消缩进。
:show-checkbox="props.isShowCheckbox" 是否显示复选框,通过 props.isShowCheckbox 来控制。
:default-expand-all="props.expandAll" 是否默认展开所有节点,通过 props.expandAll 来控制
:default-checked-keys="props.checkedKeys" 默认选中的节点的 key 的数组
:data="props.treeData" 展示数据 树的数据源,通过 props.treeData 来控制
:props="defaultProps" 配置选项,设置树节点的属性,通过 defaultProps 来控制。
:accordion="props.accordion" 是否每次只展开一个子树节点(手风琴),通过 props.accordion 来控制。
node-key="id" 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的
@node-click="onCurAllNodes" 点击树节点触发的事件 onCurAllNodes 是该函数的名称。
@node-expand="onHandleExpand" 节点被展开的事件 onHandleExpand 是该函数的名称。
@check-change="getCheckedAllNodes" 勾选状态发生变化时的事件回调函数,getCheckedNodes 是该函数的名称。
check-on-click-node 点击节点时选中节点,默认值为 false。
<i :class="checkIconByNodeLevel(node)" />:根据节点的层级来动态设置节点前面的图标样式。
{{ node.label }}:显示节点的标签文本。需要根据实际的数据结构来获取。props="defaultProps" 、数据源、node.label 三者需要保持一致。
示例:
<template>
<zw-tree
:treeData="treeData"
@onCurAllNodes="onCurAllNodes"
@getCheckedAllNodes="getCheckedAllNodes"
@onHandleExpand="onHandleExpand"
/>
</template>
<script setup lang="ts" name="Tree">
import { ref } from 'vue';
const treeData = ref([{}]);
const onCurAllNodes = (data: object) => {
console.log('当前节点下所有节点:', data);
};
const onHandleExpand = (data: object) => {
console.log('展开节点时触发:', data);
};
const getCheckedAllNodes = (data: object) => {
console.log('复选框改变:', data);
};
</script>
-->
<el-tree
ref="treeRef"
class="tree-line"
:check-strictly="checkStrictly"
:indent="0"
:show-checkbox="props.isShowCheckbox"
:default-expand-all="props.expandAll"
:default-checked-keys="props.checkedKeys"
:data="props.treeData"
:props="defaultProps"
:accordion="props.accordion"
node-key="id"
@node-click="onCurAllNodes"
@node-expand="onHandleExpand"
@check-change="getCheckedAllNodes"
check-on-click-node
>
<template #default="{ node }">
<i :class="checkIconByNodeLevel(node)" /> {{ node.label }}
</template>
</el-tree>
</template>
<script lang="ts" setup>
import { defineExpose, ref } from 'vue';
// 默认配置
const defaultProps = {
children: 'children',
label: 'label',
};
interface Tree {
label: string;
children?: Tree[];
}
const treeRef = ref();
const props = defineProps({
// 树型数据
treeData: {
type: Array,
default: () => {
return [];
},
},
// 是否全部展开
expandAll: {
type: Boolean,
default: () => {
return true;
},
},
// 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法
checkStrictly: {
type: Boolean,
default: () => {
return false;
},
},
checkedKeys: {
type: Array,
default: () => {
return [];
},
},
isShowCheckbox: {
type: Boolean,
default: () => {
return true;
},
},
accordion: {
type: Boolean,
default: () => {
false;
},
},
});
// 根据节点层级显示不同的图标
const checkIconByNodeLevel = (node: {
childNodes: [];
expanded: boolean;
data: { id: number };
}) => {
if (node.childNodes.length == 0) {
return 'iconfont icon-24gl-fileEmpty';
} else {
if (node.expanded) {
return 'iconfont icon-wenjianzhankai';
}
return 'iconfont icon-jian';
}
};
// 定义事件
const emits = defineEmits([
'onCurAllNodes',
'getCheckedAllNodes',
'onHandleExpand',
]);
// 点击事件
const onCurAllNodes = (data: Tree) => {
emits('onCurAllNodes', data);
};
// 复选框改变事件
const getCheckedAllNodes = (data: Tree) => {
emits('getCheckedAllNodes', data);
};
// 展开事件
const onHandleExpand = (data: Tree) => {
emits('onHandleExpand', data);
};
defineExpose({
treeRef,
});
</script>
<style lang="scss" scoped>
@import url('/@/myIcon/iconfont.css');
</style>