美文网首页前端Vue专辑VueVue.js
elementUI下拉单选框出现双重选中bug解决方案

elementUI下拉单选框出现双重选中bug解决方案

作者: HoPGoldy | 来源:发表于2018-12-16 10:26 被阅读5次

    问题重现

    这个bug是我在工作的时候处理过的一个问题,今天特地将bug问题剥离出来记录一下以作备忘。话不多说,直接上图:


    bug示例

    问题排查

    当时我看到之后第一反应以为下拉框启用了多选,去检查了一下后发现

    el-select(v-model="options.selected.value")
        el-option(v-for="item, index in options.list" 
                  :key="index" 
                  :label='item.name' 
                  :value='item.value')
    

    没开multiple啊



    然后去检查了下逻辑代码,发现这个下拉选单的内容是在初始化时动态加载的,获取到内容后先赋值给下拉选单的列表,然后取列表第一个内容当作默认选中值。

    加载代码段

    ...
    mounted() {
        this.getSelectList().then(resp => {
            this.options.list = resp.data
            this.options.selected = resp.data[0]
        })
    }
    ...
    

    data代码段

    data: () => ({
        options: {
            selected: {},
            list: []
        }
    }),
    

    这里我们用promise模拟一个数据请求

    getSelectList() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                const resp = {
                    data: [
                        { value: 1, name: '选项1' },
                        { value: 2, name: '选项2' },
                        { value: 3, name: '选项3' },
                        { value: 4, name: '选项4' }
                    ]
                }
                resolve(resp)
            }, 1000)
        })
    }
    

    检查了一下发现好像并没有什么不对,随后一起检查这个bug的同事把请求的内容直接放在本地data里测试了一下,bug消失了。那问题肯定就出现在在加载列表内容的那两行代码里。其实现在已经很明显了,我们直接祭出杀器Vue Devtools检查一下运行时的状态再确认一下。

    Vue Devtools
    当我们点击选项3的时候,发现不止是selected的值被改变了,list[0]值也被修改了!水落石出,这是一个由数据浅拷贝引发的bug。
    由于selected在赋值时只是进行了浅拷贝,所以selected其实是list[0]的一个引用,所以list[0]的值也会被el-select修改成被选中的值,页面在渲染时发现list[0]的key和被选中的key相同,自然就显示成选中状态了。

    问题解决

    只需要把浅拷贝换成深拷贝即可,这里我们直接用JSON.parse()JSON.stringify()深拷贝一下,这样selected和list[0]就不会相互干扰了。

    mounted() {
        this.getSelectList().then(resp => {
            this.options.list = resp.data
            this.options.selected = JSON.parse(JSON.stringify(resp.data[0]))
        })
    }
    

    问题总结

    • 在发现出现数据污染的情况,特别是数据里包含数组或对象(这个基本避免不了),或者从数组里取值赋给某个值的时候,要优先考虑深浅拷贝的问题。
    • Vue Devtools真好用。

    相关文章

      网友评论

        本文标题:elementUI下拉单选框出现双重选中bug解决方案

        本文链接:https://www.haomeiwen.com/subject/zmetkqtx.html