Vue(十九):ElementUI 扩展实现树形结构表格组件的勾父选子、半勾选、过滤出半勾选节点功能

效果

原理分析

  1. 从后端获取数据后,判断当前节点是否勾选,从而判断是否勾选子节点
  2. 勾选当前节点时,子节点均勾选
  3. 全勾选半勾选不勾选的样式处理
  4. 全勾选全取消勾选的逻辑
  5. 筛选出半勾选的节点

定义变量

import {
   computed, nextTick, reactive, ref} from 'vue';
import {
   tree} from "./tree.js";

// 默认节点
const tableData = reactive([
    {
   id: '节点1', hasChildren: true}, {
   id: '节点2', hasChildren: true},
    {
   id: '节点3', hasChildren: true}, {
   id: '节点4', hasChildren: true},
]);
const treeTableRef = ref();         // 表格实例
const selections = ref([]);			// 勾选节点
const childrenNodes = reactive({
   });	// 全部子节点
const isSelectedAll = ref(false);   // 是否勾选全部

定义是否勾选全部子节点函数

/**
 * 勾选子节点
 * @param id
 * @param selected
 */
const selectedChildren = (id, selected) => {
   
	(childrenNodes[id] || []).forEach(row => {
   
		treeTableRef.value.toggleRowSelection(row, selected);
		if (id !== row.id) selectedChildren(row.id, selected);
	});
}

单个节点勾选函数

/**
 * 单个节点勾选
 * @param selection    选中节点集合
 * @param row        当前节点
 */
const select = (selection, row) => {
   
	nextTick(() => {
   
		// 是否勾选当前节点下全部子节点
		selectedChildren(row.id, selection.some(d => d.id === row.id));
	});
}

从后端获取节点数据

/**
 * 加载子节点
 * @param row        当前节点
 * @param treeNode    节点状态
 * @param resolve    渲染子集函数
 */
const load = (row, treeNode, resolve) => {
   
	setTimeout(() => {
   
		childrenNodes[row.id] = (tree[row.id] || []).map(d => ({
   ...d, parentId: row.id}));
		resolve(childrenNodes[row.id]);
		// 判断当前节点是否选中,选中则自动勾选子节点
		nextTick(() => select(selections.value, row));
	}, 100);
}

全勾选、全取消勾选函数和勾选监听

/**
 * 全选节点勾选
 * @param selection    选中节点集合
 */
const selectAll = (selection) => {
   
	isSelectedAll.value = !isSelectedAll.value;
	treeTableRef.value.data.forEach(row => {
   
		// 默认数据的勾选
		treeTableRef.value.toggleRowSelection(row, isSelectedAll.value);
		// 是否勾选全部节点下全部子节点
		selectedChildren(row.id, isSelectedAll.value);
	});
}

/**
 * 监听节点选择事件
 * @param selection    选中节点集合
 */
const selectionChange = (selection) => {
   
    selections.value = selection;
    // 勾选的节点数量为0时,设置勾选全部的状态为false
    nextTick(() => ((selection.length === 0) && (isSelectedAll.value = false)));
}

表头Checkbox选中样式

/**
 * 表格头选中状态
 * @type {ComputedRef}    样式选择器名称
 */
const headerRowClassName = computed(() => {
   
	let count = tableData.length;
	for (const key in childrenNodes) {
   
		count += (childrenNodes[key] || []).length;
	}
	return (count === selections.value.length || selections.value.length === 0) ? '' : 'half-checked';
})

定义当前节点样式选择器

/**
 * 定义表格行样式选择器
 * @param row            当前节点
 * @param rowIndex        当前节点索引
 * @returns {string}    样式选择器名称
 */
const rowClassName = ({
    row, rowIndex}) => {
   
	if (selections.value.length === 0) return '';

	const selectedNodeFlags = []; // 存储节点的状态

	/**
	 * 筛选子节点勾选状态
	 * @param item    当前节点
	 */
	const filterSelectedChildrenNodeFlags = (item) => {
   
		(childrenNodes[item.id] || []).forEach(node => {
   
			// 避免死循环
			if (item.id 

你可能感兴趣的:(Vue,vue.js,elementui,前端,javascript)