element-ui 级联选择器cascader动态加载的问题

前段时间项目里有一个树状单位结构的需求,第一反应就是用elementui里的cascader 级联选择器来做。

本来以为是通过接口直接获取到所有单位树后配置一下就可以了,看了需求文档后发现原来是要通过动态加载的方式来获取。

需求:
1.进入页面之后根据当前的单位Id调用第一个接口来获取第一级的单位,并默认展示。
2.如果当前单位有下级单位则显示箭头,点击调用第二个接口获取下级单位。

很快啊,看着elementui官方文档,写了一个简单的demo,如下:

<template>
    <div class="main">
        <el-cascader :props="props"></el-cascader>
    </div>
</template>
<script>
export default {
    data(){
        return {
            placeholder:"",
            defaultName:"",
            props:{
                label:'text',
                value:'id',
                lazy: true,
                lazyLoad:(node, resolve) =>{  
                    if(node.level == 0 ){
                        this.queryTree(node, resolve)
                    }else {
                        this.queryMoreTree(node, resolve)
                    }
                },
            }
        }
    },
    methods:{
        //获取第一级单位
        queryTree(node, resolve){
            setTimeout(() => {
                let res = [{id:"1",text:"北京",hasChildren:true}];
                res.forEach(item => {
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:item.leaf
                    }
                })
                console.log(res)

                resolve(res)
            }, 500);

        },
        //获取下级单位
        queryMoreTree(node, resolve){
            setTimeout(() => {
                let res = [
                	{id:"1-1",text:"昌平区",hasChildren:true},
                	{id:"1-2",text:"东城区",hasChildren:true},
                	{id:"1-3",text:"朝阳区",hasChildren:true},
                	{id:"1-4",text:"沙河",hasChildren:false}
                ]
                res.forEach(item =>  {
                    item.leaf = !item.hasChildren;
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:!item.hasChildren
                    }
                })
                console.log(res)
                resolve(res)

            }, 500);

        }
    }

}
</script>

因为只是个demo,所以我用了settimeout来模拟异步获取数据。
我们返回的数据中有一个hasChildren的字段,为true时表示这个单位下是有子单位的。然后在这个地方我被折磨了好久!

在return的对象中,leaf是判断当前节点是否有下级的字段,当leaf为false时是有下级,为true时没有下级。leaf也就是控制每个节点是否显示箭头的的属性。
在这里插入图片描述

然后我就想当然的给leaf属性赋值为 item.!haschildren,但是!不生效!尝试着直接赋值 true,不生效!

最后没办法了,把官方文档里的例子拷过来,去看看为什么它的就可以控制。

props:{
	lazy: true,
    lazyLoad (node, resolve) {
    	const { level } = node;
        setTimeout(() => {
        	const nodes = Array.from({ length: level + 1 })
            .map(item => ({
            	value: ++id,
                label: `选项${id}`,
                leaf: level >= 2
             }));
            // 通过调用resolve将子节点数据返回,通知组件数据加载完成
            console.log(nodes) //在这里输出查看节点
            resolve(nodes);
        }, 1000);
  	}
}

上边是官方案例中的写法,我在输出了nodes后发现
在这里插入图片描述

他的对象里是有leaf属性的。
然后我就尝试了一下给我自己拿到数据中添加这个属性:

		//获取第一级单位
		queryTree(node, resolve){
            setTimeout(() => {
                let res = [{id:"1",text:"北京",hasChildren:true}];
               	res.forEach(item => {
                    item.leaf = !item.hasChildren //给item添加leaf属性
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:item.leaf
                    }
            	})
              	resolve(res)
            }, 500);
        },
        //获取下级单位
        queryMoreTree(node, resolve){
            setTimeout(() => {
                let res = [
                	{id:"1-1",text:"昌平区",hasChildren:true},
                	{id:"1-2",text:"东城区",hasChildren:true},
                	{id:"1-3",text:"朝阳区",hasChildren:true},
                	{id:"1-4",text:"沙河",hasChildren:false}
                ]
                res.forEach(item =>  {
                    item.leaf = !item.hasChildren //给item添加leaf属性
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:item.leaf
                    }
                })
                resolve(res)
            }, 500);

        }

在这里插入图片描述

成功了!

接下来还有几个问题:
1.假如昌平区下还有数个子单位,但是我现在需要直接选中昌平区。
2.选择完单位后,input框里会显示从北京开始一直到选中单位的所有路径。而我只想显示当前选中单位。
3.选择完单位后需要将选中的单位id覆盖掉当前的单位id,并将级联选择器下拉框隐藏掉。
4.进入页面后,input框里需要默认显示第一级中的第一个单位。

前两个问题其实很好解决,官方文档给出了明确的方法。
第三个问题有一个选中选项后的方法,我们在这里边进行处理。
第四个默认显示的问题,我尝试着用 v-model 给cascader绑定默认值,但是不生效。
百度了好几种方法,但是我没看懂…
最后灵机一动,用了一个取巧的方法。 上完整版代码:

<template>
    <div class="main">
        <el-cascader 
        :props="props"  
        :show-all-levels="false" 
        :placeholder = "placeholder"
        @change="handleChange" 
        change-on-select 
        ref="cascader" 
        >
        </el-cascader>
    </div>
</template>


<script>
export default {
    data(){
        return {
            placeholder:"",
            props:{
                label:'text',
                value:'id',
                lazy: true,
                lazyLoad:(node, resolve) =>{  
                    if(node.level == 0 ){
                        this.queryTree(node, resolve)
                    }else {
                        if(!node.leaf){ //当本节点有子单位时才调用接口
                            this.queryMoreTree(node, resolve)
                        }
                    }
                }
            }
        }
    },
    methods:{
    	//选中单位之后的操作
        handleChange(item) {
            this.id = item[item.length - 1];
            this.$refs.cascader.dropDownVisible = false
        },
        //获取第一级单位
        queryTree(node, resolve){
        	//此处要将本单位id作为参数提交
            setTimeout(() => {
                let res = [{id:"1",text:"北京",hasChildren:true}];
                this.placeholder = res[0].text
                res.forEach(item => {
                    item.leaf = !item.hasChildren
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:item.leaf
                    }
                })
                console.log(res)
                resolve(res)
            }, 500);
        },
        //获取下级单位
        queryMoreTree(node, resolve){
        	//注意此处要将node.value,也就是点击的节点单位的id,作为查询被点击单位下级单位的参数提交
            setTimeout(() => {
                let res = [
                	{id:"1-1",text:"昌平区",hasChildren:true},
                	{id:"1-2",text:"东城区",hasChildren:true},
                	{id:"1-3",text:"朝阳区",hasChildren:true},
                	{id:"1-4",text:"沙河",hasChildren:false}
                ]
                res.forEach(item =>  {
                    item.leaf = !item.hasChildren;
                    return {
                        value:item.id,
                        label:item.text,
                        leaf:item.leaf
                    }
                })
                resolve(res)
            }, 500);

        }
    }

}
</script>


<style lang = "less" scoped>

::placeholder{
   color:rgb(69, 68, 102)
}
    


</style>

show-all-levels = ‘false’ 只显示当前选中单位。
change-on-select 属性可以让你选择每个节点的单位。
@change是在选中某节点后触发,在这里我们将当前选定单位的id覆盖原单位id。并且给级联选择器一个ref值,在选中某单位后将选择器下拉框隐藏。

最后我给级联选择器动态绑定了一个placeholder占位符,将第一次获取到的数据中首个单位的名字赋值给它。然后在css中将占位符的字体颜色设置为选中后的颜色。

效果图:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值