element模态框dialog中的select组件中选中无反应

1、问题描述

准确说,是在dialogel-from组件中的el-select组件,打开模态框时,对select绑定的数据重新赋值value1,select视图层状态会变成value1,但之后变更option选项,select视图层*不再更新。

一般是在新建或编辑数据,弹出dialog模态框,在弹窗的表单里对该条数据进行编辑修改。

<el-dialog :visible.sync="dialogEdit">
    <el-form ref="editValidateForm" :model="editValidateForm">
    	...
        <el-form-item prop="workType" label="类型:">
            <el-select v-model="editValidateForm.workType" 
                       placeholder="请选择类型" 
                       @change="handleChange">
                <el-option v-for="(item,index) in types" 
                           :key="index" 
                           :label="item.name" 
                           :value="item.value">
                    {{item.name}}
                </el-option>
            </el-select>
        </el-form-item>
    </el-form>
</el-dialog>

editValidateForm在data里会有一组初始数据:

export default {
   name: "test",
   data(){
       return{
           editValidateForm:{
           	...
               workType:'',
           }
       }
   },
   methods:{
   		open(){},
   		handleChange(){}
   }
}

2、问题情况1

如果是单纯地dialogEdit = true打开模态框,不对表单数据进行重新赋值,是不会出现问题的。

如果有问题,可能是vue或者element的版本bug,我用的elemnt2.4.6,没有这个bug,这里也不针对这种情况说明。

3、问题情况2

如果在打开dialog的同时,对这个数据进行赋值:

this.editValidateForm.worktType = 1

会看到select的选中项变为1,但是之后再选其他option无法选中。
其实这里只是视图层没有更新,在select的change方法里监听,this.editValidateForm.worktType的值是改变了的。

出现这个问题好像是因为下拉框数据是循环掉别的接口得来的,因为数据层次太多,render函数没有自动更新,需手动强制刷新

3.1 尝试1

由此,我想到vue文档里说过,利用索引直接设置数组一个原本不存在的项时
this.items[index] = newValue
不会使视图更新,为了针对这种情况,vue提供了set方法vm.$set(target,propertyName/index,value),以此赋值并更新视图。和这里的问题有些像,我尝试了用set方法赋值:

this.$set(this.editValidateForm,'workType','1');

问题解决了,这种方法应该是属于强制刷新,针对我的这种情况是有效的

3.2 尝试2

强制刷新这个点出发,还有一个解决方法,也是vue API文档提供了vm.$forceUpdate()方法:

迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

我们赋值照旧,但是在select的change函数里加上这个方法:

open(){
	..
	this.editValidateForm.worktType = 1
}
handleChange(){
	this.$forceUpdate();
}

同样解决了这个问题。

3.3 尝试3

在编辑时,因为这条数据已存在,点击数据请求数据信息,在success回调里这样对数据进行赋值:

requestApi(params).then(function(res) {
	this.editValidateForm =  res.data;
})

在这种情况下,是没有这类bug的。由此联想即使目标只是给workType这一项重新赋值,也要给整个this.editValidateForm对象赋值:

this.editValidateForm = {
	...
	workType:"1"
}

问题解决。但这样比较繁琐,为了一个属性,就要重新赋值整个对象。

3.4 尝试4

由尝试3,同样是在dialog里,但是给表单中的select组件绑定一个data子属性级的数据,也就是说将绑定的workType移到与editValidateForm同级,也能解决这个问题:

<el-form-item label="类型:">
    <el-select v-model="workType" 
               placeholder="请选择类型">
        <el-option v-for="(item,index) in types" 
                   :key="index" 
                   :label="item.name" 
                   :value="item.value">
            {{item.name}}
        </el-option>
    </el-select>
</el-form-item>
data(){
       return{
      	   workType:'',
           editValidateForm:{
           	... 
           }
       }
   },

3.5 尝试5

因为这是改别人的代码,后来发现虽然上面的方法确实能解决我的问题,但我这里视图不更新真正的原因是上面这行代码,去掉后就不存在这个问题了:

 methods:{
	open(){
		 this.editValidateForm = {};	//问题所在
		 this.editValidateForm.worktType = 1
	},
}

思考了下,觉得应该是这样:先将表单对象editValidateForm置为空对象,那这个对象之前所有的属性包括worktType 都不存在了,之后再通过“.”这样的方式对一个不存在的对象属性进行赋值。这样一来就不是尝试1里说的情况相似,而是就是同样的问题:
https://cn.vuejs.org/v2/guide/list.html

数组更新检测
注意事项
由于 JavaScript 的限制,Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

对象更改检测注意事项
还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性

所以尝试3能解决问题的根源也在于它是对已存在的editValidateForm对象赋值

在vue里,当你对一个不存在的属性或对象直接“.”进行赋值,或者对数组不存在的索引项直接用索引赋值,从控制台打印可以看到数据变更,但无法使视图更新

所以,即使这个form不在dialog里,这样赋值也会不更新视图。遇到这种情况都可以用上面的方法试试

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值