前端小伙伴们有没有遇到过这样的场景,iviewUI组件库中select双向绑定数据时,修改了绑定值,但是页面中渲染的值还是之前的值,不管是去打印还是使用vue插件去查看变量,均显示绑定值已修改,可是页面始终显示修改之前的数据,是不是很困恼,心中简直是卧槽、卧槽、卧槽。
我之前做过很暴力的事情,就是在select标签上绑定v-if,在修改v-modal的值时,对v-if对应的变量先赋值false,紧接着赋值true,如果还不行就加个延时settimeout。当时还为自己的机智洋洋得意,现在想想属实是真没文化,吃了读书少的亏。
最近重新阅读vue官网文档时,读到了这段话:
key
当 Vue.js 用 v-for
正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,而不是移动 DOM 元素来匹配数据项的顺序, Vue 将简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个类似 Vue 1.x 的 track-by="$index"
。
这个默认的模式是有效的,但是只适用于不依赖子组件状态或临时 DOM 状态(例如:表单输入值)的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
属性。理想的 key
值是每项都有唯一 id。这个特殊的属性相当于 Vue 1.x 的 track-by
,但它的工作方式类似于一个属性,所以你需要用 v-bind
来绑定动态值(在这里使用简写):
<div v-for="item in items" :key="item.id"> <!-- 内容 --></div>复制代码
建议尽可能使用 v-for
来提供 key
,除非迭代 DOM 内容足够简单,或者你是故意要依赖于默认行为来获得性能提升。
因为它是 Vue 识别节点的一个通用机制, key
并不特别与 v-for
关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。
划重点了,划重点了,划重点了,重要的事说三遍,
因为它是 Vue 识别节点的一个通用机制, key
并不特别与 v-for
关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。
因为它是 Vue 识别节点的一个通用机制, key
并不特别与 v-for
关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。
因为它是 Vue 识别节点的一个通用机制, key
并不特别与 v-for
关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。
我觉着key可以为我做点什么,之后我又看了一下react中diff算法的文章(vue原理与之一致),发现这个key果真厉害的不要不要的。
key值的作用主要用来减少没必要的diff算法的对比,对于同一个组件或者节点来说,只要父节点状态或属性发生改变,该组件就会进行diff 对比,即使该组件没有发生改变;如果为该组件引入key值,在进行diff对比前先做一次校验,判断该组件是否需要diff对比,也可以判断该 组件是直接更新操作还是销毁或者新建操作,从而提高了diff算法的效率;特别在渲染同级同结构的组件们时,key可以为它们加上了身份的 标志,在rerender时,可以通过key来判断该组件是否已经存在,是否需要跟新或者销毁,新建等操作,提高了diff算法在同级节点上的操作。 原理: 因为在reactelement中有一个属性是key,该属性默认是为空值,所以一般情况下,只要组件不加上key值,react是不会去校验组件 的key,而是直接采用diff算法进行对比,一旦组件加上了key值,react就会在渲染时对该组件的身份进行校验,首先校验新旧组件的key值 是不是一致,不一致的话,该组件直接销毁,然后在新建该组件;如果一致,则比较组件的属性是否发生变化,如果发生变化,则采用diff算 法进行对比,然后得出差异对象,如果属性没发生变化,则认为该组件不需要改变;
回到文章一开始提到的问题,我的理解是select这部分的dom被就近复用了,因此有时才会出现修改v-modal的值之后页面显示的是之前的值,因此,我就想到了,为什么不能在select上绑定key值,说做就做。
<select v-modal="selectValue" :key="selectkey" @onChange="selectChange">
<option>111</option>
...
</select>
每次修改值的时候我会让selectKey自增一下,也就是说让select的身份标识发生变化,得到重新渲染,这样就规避掉绑定值不生效的现象了,也规避掉v-if带来的闪一下的不良体验。
亲测有效,希望遇到相同问题的小伙伴能够用得上。