前言
在使用iView的Select的时候,Select组件使用了双向绑定
1 | <Select |
cronObj.hour
默认有值假如是*
,在mounted
的时候我们赋值为5
,按道理组件上应该是5
的,但是实际上却是*
。
难道data
中的数据的渲染比mounted
还晚?
实际上不是的,mounted
是在data
或props
之后再执行的,那为什么会出现这个问题呢?
我们可以查看一下源代码:
1 | mounted(){ |
发现iView的Select组件中mounted
中赋值是延迟执行的。
这就知道原因了,因为是延迟执行,所以在data
渲染的时候,以为渲染过了,mounted
回调就开始调用了。
对于两次传入的值,第一次在mounted
中触发,后续的都在watch
中触发,但是mounted
中添加了异步执行,而watch
中没有异步调用,所以后续更改的值反倒被之前的值覆盖。
等延迟执行后返回的是之前data
的值,mounted
设置的值就不生效了。
解决方式
解决方式有以下几种:
使用created
created在渲染之前就覆盖了之前的默认值,这样渲染的时候就是新值了。
1 | created() { |
使用watch+immediate
默认watch的属性在mounted
之前调用,添加immediate: true
后,监听函数在创建后就会调用一次,所以会在mounted
之前先调用。
建议:
监听
props
传入值的情况下使用该方式。
示例:
1 | watch: { |
使用nextTick
Vue会先确保当前的 DOM 更新队列中的所有工作完成,包括组件内部的延迟执行的代码,再执行await this.$nextTick()
后的代码。
1 | async mounted() { |
mounted+setTimeout
通过上面的源码我们发现,赋值是延迟执行的,我们再次赋值也添加延迟,就能都放在延迟的队列中,也会等到之前渲染完再执行。
1 | mounted() { |