动态

详情 返回 返回

Element Table 表格樹形結構多選框選中子級父級狀態變為半選中狀態(遞歸多級) - 动态 详情

1.實現效果

實現效果

2.數據和佈局準備

準備一個 el-table 組件以及數據源,這裏的數據源可以是你的接口提供的。

<template>
    <div style="width: 78%;">
        <el-table ref="menuTableRef" :data="menuList" style="width: 100%;margin-bottom: 20px;"
            :row-class-name="rowClassNameFun" row-key="id" border
            :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" @select="handleSelect"
            @select-all="handleSelectAll">
            <el-table-column type="selection" width="55"> </el-table-column>
            <el-table-column align="center" prop="title" label="標題">
            </el-table-column>
            <el-table-column align="center" prop="describe" label="描述">
            </el-table-column>
            <el-table-column align="center" prop="name" label="name" />
        </el-table>
    </div>
</template>

<script>
export default {
    name: 'MenuTree',
    data() {
        return {
            menuList: [
                {
                    id: 1,
                    title: '系統管理',
                    describe: '系統管理描述',
                    name: 'system',
                    parentId: 0,
                    children: [
                        {
                            id: 11,
                            title: '用户管理',
                            describe: '系統管理描述',
                            name: 'user',
                            parentId: 1,
                            children: []
                        },
                        {
                            id: 12,
                            title: '角色管理',
                            describe: '角色管理描述',
                            name: 'role',
                            parentId: 1,
                            children: []
                        }
                    ]
                },
                {
                    id: 2,
                    title: '數據管理',
                    describe: '數據管理描述',
                    name: 'data',
                    parentId: 0,
                    children: [
                        {
                            id: 21,
                            title: '數據導入',
                            describe: '數據導入描述',
                            name: 'import',
                            parentId: 2,
                            children: []
                        }
                    ]
                },
                {
                    id: 3,
                    title: '權限管理',
                    describe: '權限管理描述',
                    name: 'permission',
                    parentId: 0,
                    children: [
                        {
                            id: 31,
                            title: '角色管理',
                            describe: '角色管理描述',
                            name: 'role',
                            parentId: 3,
                            children: []
                        }
                    ]
                },
                {
                    id: 4,
                    title: '日誌管理',
                    describe: '日誌管理描述',
                    name: 'log',
                    parentId: 0,
                    children: [
                        {
                            id: 41,
                            title: '操作日誌',
                            describe: '操作日誌描述',
                            name: 'operation',
                            parentId: 4,
                            children: []
                        }
                    ]
                },
                {
                    id: 5,
                    title: '設置管理',
                    describe: '設置管理描述',
                    name: 'setting',
                    parentId: 0,
                    children: [
                        {
                            id: 51,
                            title: '參數設置',
                            describe: '參數設置描述',
                            name: 'parameter',
                            parentId: 5,
                            children: []
                        }
                    ]
                }
            ]
        }
    },

    created() {
        this.initData(this.menuList)
    },

    methods: {
        initData(data) {
            for (let item of data) {
                item.isSelect = false // 默認為不選中
                if (item.children && item.children.length > 0) {
                    this.initData(item.children)
                }
            }
        }
     }

3.代碼實現

在每個方法中都寫好了註釋,細心看代碼,一步一步跟着代碼邏輯來就可以實現最終效果。
代碼邏輯

表格數據是否選中標誌
isSelect狀態: true為選中狀態; false為未選中狀態; 空字符串為半選中狀態
<script>
methods: {

        initData(data) {
            for (let item of data) {
                item.isSelect = false // 默認為不選中
                if (item.children && item.children.length > 0) {
                    this.initData(item.children)
                }
            }
        },

        rowClassNameFun({ row }) {
            if (row.isSelect === "") {
                return "indeterminate";
            }
        },

        /**
         * 處理選中事件
         * @param selection 所有選中的row
         * @param row 當前選中的row
         */
        handleSelect(selection, row) {
            //當點擊父級點複選框時,當前的狀態可能為未知狀態,所以當前行狀態設為false並選中,即可實現子級點全選效果
            if (row.isSelect === "") {
                row.isSelect = false;
                this.$refs['menuTableRef'].toggleRowSelection(row, true);
            }

            row.isSelect = !row.isSelect

            let level = this.getSelectedRowLevel(row)

            if (level == 1) {
                this.changeAllChildrenStatus(row.children, row.isSelect)
            } else if (level == 2) {
                this.changeAllChildrenStatus(row.children, row.isSelect)
                this.changeAllParentsStatus(row)
            } else if (level == 3) {
                this.changeAllParentsStatus(row)
            }
        },

        /**
         * 處理全選事件
         * @param selection 全選選中的行
         */
        handleSelectAll(selection) {
            let isAllSelect = this.checkIsAllSelect()
            this.menuList.forEach((item) => {
                item.isSelect = isAllSelect
                this.$refs['menuTableRef'].toggleRowSelection(item, !isAllSelect)
                this.handleSelect(selection, item)
            })
        },

        /**
         * 獲取選中行的等級
         * @param row
         * @returns 1 父級 2 既是父級也是子級 3 葉子節點
         */
        getSelectedRowLevel(row) {
            if (row.parentId == 0) {
                return 1
            } else {
                if (row.children || row.children.length) {
                    return 2
                } else {
                    return 3
                }
            }
        },
        /**
         * 改變所有子節點選中狀態
         * @param data
         */
        changeAllChildrenStatus(data, isSelect) {
            data.forEach((item) => {
                item.isSelect = isSelect;
                this.$refs['menuTableRef'].toggleRowSelection(item, isSelect);
                if (item.children && item.children.length) {
                    this.changeAllChildrenStatus(item.children, isSelect);
                }
            })
        },

        /**
         * 改變所有父級選中狀態
         * 操作的是子節點:
         * 1、獲取父節點  
         * 2、判斷子節點選中個數,如果全部選中則父節點設為選中狀態,如果都不選中,則為不選中狀態,如果部分選擇,則設為不明確狀態
         * 3、判斷父節點是否還有父級
         * @param row
         */
        changeAllParentsStatus(row) {
            let parentRow = null
            if (row.parentId == 0) {
                parentRow = row
            } else {
                parentRow = this.getParentRow(this.menuList, row.parentId)
            }
  
            let selectStatusList = []
            this.getRowSelectStatus(parentRow.children, selectStatusList)

            let isAllSelected = selectStatusList.every(e => e == true)
            let isAllNotSelected = selectStatusList.every(e => e == false)

            if (isAllSelected) {
                parentRow.isSelect = true;
                this.$refs['menuTableRef'].toggleRowSelection(parentRow, true);
            } else if (isAllNotSelected) {
                parentRow.isSelect = false;
                this.$refs['menuTableRef'].toggleRowSelection(parentRow, false);
            } else {
                parentRow.isSelect = "";
            }
            
            // 還有父級
            if (parentRow.parentId != 0) {
                this.changeAllParentsStatus(parentRow)
            }
        },

        /**
         * 獲取選中節點的根節點對象
         * @param data
         * @param parentId
         */
        getParentRow(data, parentId) {
            for (let item of data) {
                if (item.id == parentId) {
                    return item;
                }

                if (item.children && item.children.length) {
                    let result = this.getParentRow(item.children, parentId);
                    if (result) {
                        return result;
                    }
                }
            }
            return null;
        },

        /**
         * 獲取row選中狀態
         * @param data 行數據
         * @param list 選中狀態容器
         */
        getRowSelectStatus(data, list) {
            data.forEach((item) => {
                list.push(item.isSelect)
                if (item.children && item.children.length) {
                    this.getRowSelectStatus(item.children, list)
                }
            })

        },

        /**
         * 判斷一級row是否全選
         * @returns
         */
        checkIsAllSelect() {
            let rootRowIsSelectList = []
            this.menuList.forEach((item) => {
                rootRowIsSelectList.push(item.isSelect);
            });

            //判斷一級row是否是全選.如果一級row全為true,則設置為取消全選,否則全選
            let isAllSelect = rootRowIsSelectList.every((item) => {
                return true == item;
            });
            return isAllSelect;
        },

        /**
         * 獲取選中行的id列表
         * @param data menuList
         * @param list 選中row和被選中row父級id的列表
         */
        getSelectedRowId(data, list) {
            data.forEach((item) => {
                if (item.isSelect || item.isSelect === "") {
                    list.push(item.id)
                }
                if (item.children && item.children.length) {
                    this.getSelectedRowId(item.children, list)
                }
            })
        },
    }
</script>

半選中樣式

<style scoped lang="scss">
::v-deep .indeterminate .el-checkbox__input .el-checkbox__inner {
    background-color: #409eff !important;
    border-color: #409eff !important;
    color: #fff !important;
}

::v-deep .indeterminate .el-checkbox__input.is-checked .el-checkbox__inner::after {
    transform: scale(0.5);
}

::v-deep .indeterminate .el-checkbox__input .el-checkbox__inner {
    background-color: #f2f6fc;
    border-color: #dcdfe6;
}

::v-deep .indeterminate .el-checkbox__input .el-checkbox__inner::after {
    border-color: #c0c4cc !important;
    background-color: #c0c4cc;
}

::v-deep .product-show th .el-checkbox__inner {
    display: none !important;
}

::v-deep .indeterminate .el-checkbox__input .el-checkbox__inner::after {
    content: "";
    position: absolute;
    display: block;
    background-color: #fff;
    height: 2px;
    transform: scale(0.5);
    left: 0;
    right: 0;
    top: 5px;
    width: auto !important;
}

::v-deep .product-show .el-checkbox__inner {
    display: block !important;
}

::v-deep .product-show .el-checkbox {
    display: block !important;
}
</style>

4.參考

  • Element Table 表格樹形結構多選框選中父級時會選中子級(遞歸多級)_element table tree 選擇子級-CSDN博客
  • less和scss樣式穿透的三種寫法_less deep寫法-CSDN博客

Add a new 评论

Some HTML is okay.