Vue的双向绑定用着确实方便,但自动档虽好,手动档也不是一无是处,而且自动更新会出现各种坑,在特定的情况下,还真的要手工触发“刷新”操作,目前有几种方案可以选择:
- 通过Vue 的key-changing优化组件
- 使用v-if标记
- 使用内置的forceUpdate方法
通过vue key
实现,原理很简单,vue使用key
标记组件身份,当key
改变时就是释放原始组件,重新加载新的组件。所以当key 值变更时,会自动的重新渲染。这应该是目前最优雅的解决办法了。
官网原文:
key
的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。
也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用:
- 完整地触发组件的生命周期钩子
- 触发过渡
例如:
<transition> <span :key="text">{{ text }}</span> </transition>
当 text
发生改变时,span 总是会被替换而不是被修改,因此会触发过渡。
下面是一个样例,当组件的数据更新时,会触发watch
函数,使得key
值变化,达到强制渲染组件的目的。
<template> <third-comp :message="menuData" :key="menuKey"/> </template> <script> export default{ data(){ return { menuKey:1, menuData: "", } }, watch:{ menuData(){ ++this.menuKey } } } </script>
使用v-if标记
当数据变更后,通过watch
监听,先去销毁当前的组件,然后再重现渲染。使用 v-if
可以解决这个问题。
使用案例如下,同样是使用watch
监听,通过变更v-if
的值,强制触发组件渲染。需要注意的是,使用了$nextTick()
方法。
<template> <third-comp v-if="reFresh"/> </template> <script> export default{ data(){ return { reFresh:true, menuTree:[] } }, watch:{ menuTree(){ this.reFresh= false // 在DOM渲染之后再把reFresh设置为原来的值,达到更新组件的效果 this.$nextTick(()=>{ this.reFresh = true }) } } } </script>
[ 注意 ]
Vue.nectTick()
是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick
,则可以在回调中获取更新后的DOM,这个方法作用是当数据被修改后使用这个方法,会回调获取更新后的dom再render出来。
简而言之,如果你在数据改变之后的操作跟改变之后的DOM有关,那么就应该使用Vue.nextTick()
使用内置的forceUpdate方法
这个方法在实际使用时,有存在无效的情况,斟酌使用。
组件内置$forceUpdate
方法,使用前需要在配置中启用。
使用案例:
import Vue from 'vue' Vue.forceUpdate() export default { methods: { handleUpdateClick() { // built-in this.$forceUpdate() } } }
我来说两句