vue3权限树封装成组件

vue3权限树组件
功能:
1、勾选节点、自动把父节点勾选。
2、取消勾选、子节点全部取消勾选。检查父节点,如果只有这个子节点、遍历把父节点取消勾选
3、filter过滤不仅展示父节点、相关子节点同时展示
4、 高亮显示所有过滤数据

效果图
在这里插入图片描述
父组件引用

<template>
	<Tree ref="treeRef" :data="data" style="width: 100%;"/>
</template>
<script setup lang="ts">
	import Tree from './tree.vue'
	const data = ref([])
	//1. 设置选中节点
    const taskCodes = res.data.permissionList.map(item => item.taskCode);
	treeRef.value!.setCheckedKeys(taskCodes);

	// 2. 获取选中的节点
	permissionList.value = treeRef.value!.getPermissionList()
	
</script>

tree子组件

<template>
    <span>
        <el-input v-model="filterText" class="w-60 mb-2" placeholder="请输入菜单名称" />

        <el-tree style="width: 100%;height: calc(100vh - 370px);overflow-y: auto;" :data="data" ref="treeRef"
            :props="defaultProps" node-key="id" default-expand-all :expand-on-click-node="false" :check-strictly="true"
            show-checkbox @check-change="handleCheckChange" @node-click="handleNodeClick"
            :filter-node-method="filterNode" 
            :render-content="renderNode"
            />
    </span>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, defineExpose } from 'vue'
import { useVModels } from "@vueuse/core";
const treeRef = ref()
const filterText = ref('')
const props = defineProps<{
    data: any;
}>();
const emit = defineEmits(["update:data"]);
const { data } = useVModels(props, emit);
const defaultProps = {
    children: 'children',
    label: 'label',
    disabled: 'disabled',
}
const handleCheckChange = (node, checked, indeterminate) => {
    if (checked) {
        ensureParentChecked(node);
    }
    else {
        checkParentUncheck(node);
        // 子级节点取消勾选
        checkChildUncheck(node);
    }
}
const handleNodeClick = (node, checked) => {
    if (!checked.checked) {
        ensureParentChecked(node);
    }
    else {
        checkParentUncheck(node);
        // 子级节点取消勾选
        checkChildUncheck(node);
    }
}
const ensureParentChecked = (node) => {
    treeRef.value!.setChecked(node, true, false);
    const parent = treeRef.value!.getNode(node)?.parent;
    if (parent && parent.data) {
        treeRef.value!.setChecked(parent.data, true, false);
        ensureParentChecked(parent.data);
    }
}
const checkParentUncheck = (node) => {
    treeRef.value!.setChecked(node, false, false);
    const parent = treeRef.value!.getNode(node)?.parent;
    if (!parent || !parent.data) return;
    const children = parent.childNodes;
    const allUnchecked = children.every(child => {
        return !child.checked && !child.indeterminate;
    });
    if (allUnchecked) {
        treeRef.value!.setChecked(parent.data, false, false);
        checkParentUncheck(parent.data);
    }
}
const checkChildUncheck = (node) => {
    const children = treeRef.value!.getNode(node)?.childNodes;
    if (children) {
        children.forEach(child => {
            treeRef.value!.setChecked(child, false, false);
            checkChildUncheck(child);
        });
    }
}
const filterNode = (value: string, data: any, node: any) => {
    if (!value) return true
    let _array = [];//这里使用数组存储 只是为了存储值。
    getReturnNode(node, _array, value);
    let result = false;
    _array.forEach((item) => {
        result = result || item;
    });
    return result;
}

const getReturnNode = (node, _array, value) =>{
    let isPass = node.data && node.data.label && node.data.label.indexOf(value) !== -1;
    isPass ? _array.push(isPass) : '';
    if (!isPass && node.level != 1 && node.parent) {
        getReturnNode(node.parent, _array, value);
    }
}
// 自定义节点渲染函数
const renderNode = (h: any, { node, data }: any) => {
    const label = data.label;
    const filterValue = filterText.value;
    if (filterValue && label.includes(filterValue)) {
        const parts = label.split(new RegExp(`(${filterValue})`, 'gi'));
        return h('span', {}, parts.map(part => {
            if (part.toLowerCase() === filterValue.toLowerCase()) {
                return h('span', { style: { color: 'red' } }, part);
            }
            return h('span', part);
        }));
    }
    return h('span', label);
};

watch(filterText, (val) => {
    treeRef.value!.filter(val)
})
const getPermissionList = () => {
    return treeRef.value!.getCheckedNodes().map((item: { id: string; label: string }) => ({
        taskCode: item.id,
        taskName: item.label
    }));
}
const setCheckedKeys = (keys: string[]) => {
    treeRef.value!.setCheckedKeys(keys, false);
}

defineExpose({
    getPermissionList, // 获取选中的权限列表
    setCheckedKeys,   // 设置选中的权限列表
})
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值