场景描述

项目中用到了elementUI的tree组件,角色跟菜单是一对多关联的。编辑一个角色时,可以选择多个菜单。修改角色的菜单功能需要进行回显,从后台获取数据在相对应的el-tree节点上打勾。

关键点说明

此解决方案不能适应所有情况。
使用此方案的前提:*将el-tree的属性 check-strictly 设置为 false(默认就是false)。目的是使父子节点相互关联。如果设置为true,此方案不适用

思路

提交数据到后台时,需要使用tree的getHalfCheckedKeys和getCheckedKeys获取得到已勾选和半勾选的树节点id集合。因为开启了父子相互关联,所以提交的id集合中肯定会有叶子节点的id(这句是重点)。
回显时,从后台取到与某个角色关联的菜单的id集合中也一定会有叶子节点id。可以从集合中只取出叶子节点,调用el-tree的setCheckedKeys方法即可。

代码实现

在有网络的情况下,将全部代码复制到html中可查看效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
    <el-tree
            :data="treeList"
            show-checkbox
            default-expand-all
            node-key="id"
            ref="tree"
            highlight-current
            :props="defaultProps">
    </el-tree>
    <el-divider></el-divider>
    <div v-text="'半选节点id集合 : ' + halfCheckedKeys"></div>
    <div v-text="'全选节点id集合 : ' + checkedKeys"></div>
    <div v-text="'所有选中id集合 : ' + allChecked"></div>
    <el-button @click="submit()">打印选中的id</el-button>
    <el-divider></el-divider>
    要回显的id集合:<input type="text" name="" id="" placeholder="以’,‘分割" v-model="toShowList"/>
    <el-button @click="reShow()">回显</el-button>
</div>
</body>
<!-- import Vue before Element -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script>
    new Vue({
        el: '#app',
        data: function () {
            return {
                visible: false,
                defaultProps: {
                    children: 'children',
                    label: 'name'
                },
                toShowList:'1,3,4,7',
                halfCheckedKeys: [],
                checkedKeys: [],
                allChecked: [],
                //list转为树形数据
                treeList: this.treeDataTranslate(this.initData(), 'id', 'parentId', 'children'),
            }
        },
        methods: {
            //模拟请求后台数据
            initData() {
                let list = [];
                //根,一级
                list.push({id: 1, name: '1:根数据'})
                //二级
                list.push({id: 2, parentId: 1, name: '2:二级1'})
                list.push({id: 3, parentId: 1, name: '3:二级2'})
                list.push({id: 4, parentId: 1, name: '4:二级3'})
                // 三级
                list.push({id: 5, parentId: 2, name: '5:三级1-1'})
                list.push({id: 6, parentId: 2, name: '6:三级1-2'})
                list.push({id: 7, parentId: 3, name: '7:三级2-1'})
                list.push({id: 8, parentId: 3, name: '8:三级2-2'})
                list.push({id: 9, parentId: 4, name: '9:三级3-1'})
                list.push({id: 10, parentId: 4, name: '10:三级3-2'})
                //四级
                list.push({id: 11, parentId: 5, name: '11:四级1-1-1'})
                list.push({id: 12, parentId: 5, name: '12:四级1-1-2'})
                return list
            },
            /**
             * 树形数据转换
             * @param {*} data list数据
             * @param {*} id 主键ID
             * @param {*} pid 上级ID
             * @param childrenKey 子list数据的key
             */
            treeDataTranslate(data, id = 'id', pid = 'parentId', childrenKey = 'children') {
                let res = []
                let temp = {}
                for (let i = 0; i < data.length; i++) {
                    temp[data[i][id]] = data[i]
                }
                for (let k = 0; k < data.length; k++) {
                    if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
                        if (!temp[data[k][pid]][childrenKey]) {
                            temp[data[k][pid]][childrenKey] = []
                        }
                        temp[data[k][pid]][childrenKey].push(data[k])
                    } else {
                        res.push(data[k])
                    }
                }
                return res
            },
            // 获取数据,提交到后台
            submit() {
                this.halfCheckedKeys = this.$refs.tree.getHalfCheckedKeys()
                this.checkedKeys = this.$refs.tree.getCheckedKeys()
                this.allChecked = this.halfCheckedKeys.concat(this.checkedKeys)
            //   request请求 。。。。。。。。
            },
            //回显方法,应该放到mounted方法中执行调用,这里用按钮触发
            reShow() {
                // 所有数据的parentId数组
                let allParentId = []
                this.initData().forEach(ele => allParentId.push(ele.parentId))
                //要勾选的节点id列表,数据应该来自后台
                let checkedKeyArray = this.toShowList.split(',').map(ele => parseInt(ele))
                //只需要叶子节点的id
                let children = checkedKeyArray.filter(menuId => ! allParentId.includes(menuId) );
                this.$refs.tree.setCheckedKeys(children)
            }
        }
    })
</script>
</html>
Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐