记一次el-cascader踩坑经历

1,816 阅读1分钟

先看最终实现效果图。

GIF.gif

需求描述

根据城市,加载区县,根据选中区县加载对应街道。选中区或街道后在高德地图上展示。

问题描述

设置显示的时候没有什么问题。 但是在编辑回显时,若选择了区级的下级街道,el-cascader无法填充对应的值(一片空白。。。)。 比如如上图,我若设置显示 上海 浦东新区/宣桥镇,el-cascader无法设置;但是我若设置 上海 浦东新区是没有问题的。

我猜测可能是由于el-cascader设置了延迟加载,没有触发对应区县,所以无法加载区县级下面的街道。

解决

若当前设置区县级下面的街道时,手动点击区县,让el-cascader实现自动请求加载。但是设置时会有1s左右延迟,如上图。

贴一下关键代码。希望有类似需求的同学可以一起讨论,也希望感兴趣的大佬不吝赐教

<template>
    <div>
        <el-cascader :options="cascaderOpt" v-model="district" :key="cascaderKey" ref="cascaderOptDis"
            v-if="show" style="width:100%"
            clearable placeholder="请选择" :props="props"
            popper-class="cascader-district"
            @change="districtChange"></el-cascader>
    </div>
</template>

<script> 
    let disListOpts = {
        subdistrict: 1,   //返回下一级行政区
        showbiz: true,  //最后一级返回街道信息 
        extensions: 'all', 
        level: 'city'
    };
    let disList = null
    // import _ from 'lodash'
    import AMap from 'AMap'
    export default {
        data() {
            return {
                // 手动输入地址进行关联
                district: [],
                cascaderOpt: [],
                cascaderKey: 1,
                show: true,
                props: {
                    lazy: true,
                    checkStrictly: true,
                    // expandTrigger: 'hover',
                    lazyLoad: (node, resolve) => {
                        if (!disList) {
                            disList= new AMap.DistrictSearch(disListOpts);
                        }
                        if (node && node.level) {
                            disList.setLevel('district')
                            disList.search(node.value, (status, result) => {
                                if(status === 'complete'){
                                    // let districtList = result.districtList[result.districtList.length - 1].districtList
                                    let districtList = []
                                    if (result.districtList.length > 1) {
                                        for(let i = 1; i < result.districtList.length; i++) {
                                            districtList = districtList.concat(result.districtList[i].districtList)
                                        }
                                    } else {
                                        districtList = result.districtList[0].districtList
                                    }
                                    if (!districtList || !districtList.length) {
                                        resolve([]);
                                        return
                                    }
                                    const nodes = districtList
                                        .map(item => ({
                                            value: item.name,
                                            adcode: item.adcode,
                                            label: item.name,
                                            level: item.level,
                                            center: item.center,
                                            boundaries: result.districtList[result.districtList.length - 1].boundaries,
                                            leaf: true
                                        }));
                                    // 通过调用resolve将子节点数据返回,通知组件数据加载完成
                                    resolve(nodes);
                                }
                            });
                        }
                    }
                },
            }
        },
        watch: {
            // 若时新增关联到达区域城市id
            'district': {
                handler: function (val) {
                    if (val) {
                        this.$refs.cascaderOptDis.dropDownVisible = false;
                    }
                },
                deep: true
            },
        },
        methods: {
            clear() {
                this.district = []
            },
            changeValue(arr) {
                setTimeout(() => {
                    this.$nextTick(() => {
                        this.district = arr; 
                    })
                },1000)
            },
            districtChange() {
                let nodes = this.$refs.cascaderOptDis.getCheckedNodes()
                console.log(nodes)
                if (nodes&& nodes[0] && nodes[0].data) {
                    this.$emit('change:district',nodes[0].data,this.district)
                }
            },
            initDistrict(cityName,arr) {
                if (!cityName) {
                    return 
                }
                //行政区划查询
                this.cascaderKey ++
                disList= new AMap.DistrictSearch(disListOpts);
                disList.search(cityName, (status, result) => {
                    if(status === 'complete'&&result.districtList[result.districtList.length - 1].districtList&&result.districtList[result.districtList.length - 1].districtList.length){
                        let districtList = []
                        if (result.districtList.length > 1) {
                            for(let i = 1; i < result.districtList.length; i++) {
                                districtList = districtList.concat(result.districtList[i].districtList)
                            }
                        } else {
                            districtList = result.districtList[0].districtList
                        }
                        this.cascaderOpt = districtList
                            .map(item => ({
                                value: item.name,
                                adcode: item.adcode,
                                label: item.name,
                                // level: item.level,
                                center: item.center,
                                leaf: false
                            }));
                        // 通过调用resolve将子节点数据返回,通知组件数据加载完成
                        // 还需要加载街道
                        console.log(arr)
                        if (arr && arr.length > 1) {
                                this.$nextTick(() => {
                                    // this.district = arr
                                    document.querySelectorAll(".el-cascader-node__label").forEach(el => {
                                        if (el.innerHTML === arr[0]) {
                                            el.click()
                                            this.$refs.cascaderOptDis.dropDownVisible = false;
                                            this.changeValue(arr)
                                        }
                                    });
                                })
                        } else {
                            this.district = arr || []; 
                        }
                    }
                });
            },
        }

    };
</script>


<style lang="scss">
    @import '@/scss/_handle.scss';

    .position-search {
        position: relative;

        .address_items {
            position: absolute;
            z-index: 10;
            max-height: 300px;
            border: solid 1px #E4E7ED;
            border-radius: 4px;
            background: #fff;
            width: 100%;
            overflow-y: auto;
            overflow-x: hidden;
            min-width: 410px;

            .address_item {
                display: flex;
                width: 100%;
                margin-top: 6px;

                &:hover {
                    background-color: #F5F7FA;
                    cursor: pointer;
                }

                .address_item_icon {
                    @include font_color("color-primary");
                    font-size: 15px;
                    margin-right: 6px;
                    margin-left: 15px;
                    width: 20px;
                    line-height: 22px;
                    align-self: flex-start;
                }

                .address_item_word {
                    flex: 1;

                    .title {
                        line-height: 20px;
                        font-size: 14px;
                        text-overflow: ellipsis;
                        white-space: nowrap;
                        @include font_color("color-primary");
                    }

                    .description {
                        font-size: 12px;
                        color: #9DA3AA;
                        text-overflow: ellipsis;
                        // white-space: nowrap;
                        overflow: hidden;
                        line-height: 17px;
                    }

                }
            }

            .address_empty {
                padding-left: 15px;
                line-height: 30px;
                font-size: 12px;
            }
        }
    }
</style>