对el-cascader二次封装实现双击父节点,全选该父节点下的子节点,并且父子节点互不影响

对el-cascader二次封装实现双击父节点,全选该父节点下的子节点,并且父子节点互不影响,如下图b94a4f60a9294c1c9fa575a63939b8a8.gif

 思路:既然能够取消子节点不影响父节点,就需要将checkStrictly属性置为true,通过方法实现双击父节点选中所有子节点,此外不点击多选框实现选中效果,需要用到cascader中node对象原型上的doCheck方法(element官网文档并没有直接给到如何修改状态的方法,通过查看cascader-panel.js源码发现)

一、使用插槽自定义结构

第一步是使用插槽自定义结构,及data中定义的变量

<el-cascader v-model="value" :props="props" :options="options" ref="cascader" clearable>
    <template slot-scope="{ node,data }">
         <div @dblclick="handleMoreChoice(node)">{{ data.label }}</div>
    </template>
</el-cascader>

二、能够多选并且父子之间不互相关联

根据element官网文档需要将这两个属性添加上

props: { multiple: true, checkStrictly: true },

三、实现双击父节点子节点全选

handleMoreChoice(node) {
            this.value = this.value.slice(0) //slice方法是为了触发value反显到input框中,并且不改变原数组
            const nodeList = this.getNodeChildren(node);
            // 取消选中
            if (node.checked) {
                nodeList.forEach(item => {
                    item.doCheck(false)
                    if (this.value.includes(item.path)) {
                        this.value.splice(this.value.indexOf(item.path), 1)
                    }
                })
            } else {  // 确认选中
                nodeList.forEach(item => {
                    item.doCheck(true)
                    if (!this.value.includes(item.path)) {
                        this.value.push(item.path)
                    }
                })
            }
        },
        //获取所有子级
        getNodeChildren(node) {
            let childrenNode = []
            function getChildren(data) {
                childrenNode.push(data)
                if (data.children.length) {
                    for (let index = 0; index < data.children.length; index++) {
                        getChildren(data.children[index])
                    }
                }
            }
            getChildren(node)
            return childrenNode
        },

上述代码在没有使用slice方法之前,只是实现了双击父节点选中子节点,但是input框中并没有反显相应数据,推测可能是value新添加的数据不是响应式的,但是使用this.$forceUpdate()或者this.$set()都不能达到效果,此时想到vue2官网文档中a335c102a84747c2b913c072a237808c.png

所以使用slice方法,亲测concat方法同样生效,但与此同时,就会导致父节点双击选中,页面中子节点对应的dom结构会隐藏,但效果实现了,如上边GIF所示,这个问题暂时没有想到解决方法

四、下面为完整代码 

<template>
    <div>
        <el-cascader v-model="value" :props="props" :options="options" ref="cascader" clearable>
            <template slot-scope="{ node,data }">
                <div @dblclick="handleMoreChoice(node)">{{ data.label }}</div>
            </template>
        </el-cascader>
    </div>
</template>

<script>
export default {
    data() {
        return {
            props: { multiple: true, checkStrictly: true },
            value: [],
            options: [
                {
                    value: 'zhinan',
                    label: '指南',
                    children: [
                        {
                            value: 'shejiyuanze',
                            label: '设计原则',
                            children: [{
                                value: 'yizhi',
                                label: '一致',
                                children: [
                                    {
                                        value: "test1",
                                        label: "测试1"
                                    },
                                    {
                                        value: "test2",
                                        label: "测试2"
                                    },
                                ]
                            }, {
                                value: 'fankui',
                                label: '反馈',
                                children: [
                                    {
                                        value: "test3",
                                        label: "测试3"
                                    },
                                    {
                                        value: "test4",
                                        label: "测试4"
                                    },
                                ]
                            }]
                        },
                        {
                            value: 'daohang',
                            label: '导航',
                            children: [{
                                value: 'cexiangdaohang',
                                label: '侧向导航'
                            }, {
                                value: 'dingbudaohang',
                                label: '顶部导航'
                            }]
                        },
                    ]
                },
                {
                    value: 'zhinan0',
                    label: '指南0',
                    children: [
                        {
                            value: 'shejiyuanze0',
                            label: '设计原则0',
                            children: [{
                                value: 'yizhi0',
                                label: '一致0'
                            }, {
                                value: 'fankui0',
                                label: '反馈0'
                            }, {
                                value: 'xiaolv0',
                                label: '效率0'
                            }, {
                                value: 'kekong0',
                                label: '可控0'
                            }]
                        },
                        {
                            value: 'daohang0',
                            label: '导航0',
                            children: [{
                                value: 'cexiangdaohang0',
                                label: '侧向导航0'
                            }, {
                                value: 'dingbudaohang0',
                                label: '顶部导航0'
                            }]
                        },
                    ]
                },
            ]
        }
    },
    methods: {
        handleMoreChoice(node) {
            this.value = this.value.slice(0) //slice方法是为了触发value反显到input框中,并且不改变原数组
            const nodeList = this.getNodeChildren(node);
            // 取消选中
            if (node.checked) {
                nodeList.forEach(item => {
                    item.doCheck(false)
                    if (this.value.includes(item.path)) {
                        this.value.splice(this.value.indexOf(item.path), 1)
                    }
                })
            } else {  // 确认选中
                nodeList.forEach(item => {
                    item.doCheck(true)
                    if (!this.value.includes(item.path)) {
                        this.value.push(item.path)
                    }
                })
            }
        },
        //获取所有子级
        getNodeChildren(node) {
            let childrenNode = []
            function getChildren(data) {
                childrenNode.push(data)
                if (data.children.length) {
                    for (let index = 0; index < data.children.length; index++) {
                        getChildren(data.children[index])
                    }
                }
            }
            getChildren(node)
            return childrenNode
        },
    },
}
</script>

<style lang="less" scoped>
// /deep/ input {
//     width: 100vw !important;
// }
</style>

还有点优化空间,有时间再继续更新。。。。。 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值