uniapp数据更新视图不更新的问题
强制更新如果你发现你自己需要在 Vue 中做一次强制更新,99.9% 的情况,是你在某个地方做错了事。你可能还没有留意到数组或对象的变更检测注意事项,或者你可能依赖了一个未被 Vue 的响应式系统追踪的状态。然而,如果你已经做到了上述的事项仍然发现在极少数的情况下需要手动强制更新,那么你可以通过 $forceUpdate 来做这件事。this.$forceUpdate()更新某一个元素视图Vue.
响应式原理
当我们在 Vue.js 中修改响应式对象的属性时,Vue.js 会自动对修改进行追踪,并在必要时自动更新视图,这是 Vue.js 的响应式系统的核心特性。
Vue.js 的响应式系统是通过数据劫持实现的。在 Vue.js 内部,每个组件实例包含一个拦截器——observe
,它可以对组件中的所有数据进行监听。当我们对组件中的数据进行修改时,observe
就会被触发,进而更新对应的视图。这种数据劫持的机制,是依靠 Object.defineProperty
这个 API 实现的。Object.defineProperty
方法可以劫持一个对象,并在对象的 getter 和 setter 被访问时,拦截它们的访问以实现数据劫持。
对于修改对象属性或数组元素,Vue.js 会通过 Vue.set()
和 Vue.delete()
方法来实现响应式更新。当我们通过直接修改数组索引的方式更新数组时,例如:this.list[1] = {name: '小美', age: 18}
。这种方式虽然也能生效,但 Vue.js 无法检测到该变更。因为 Vue.js 的追踪机制是在对象初始化时,将对象的数据转换成 getter 和 setter 的形式,并对它们进行监听。因此,如果我们没有使用 Vue.set()
或 Vue.delete()
方法实现更新,Vue.js 就无法发现变化。
使用 Vue.set()
和 Vue.delete()
方法会通知 Vue.js 进行更新视图。这两个方法内部都是通过调用响应式对象的 __ob__
观测者(Observer
)的 dep
通知依赖这个属性的所有 watcher 更新视图。
使用 Vue.set()
方法修改数组或对象属性时会给要修改的对象的属性值,包括新增的属性,上下文对象添加一个响应式标记。同时,当我们向一个对象上添加一个不存在的新属性时,会在该对象上使用 Vue.set()
方法来触发响应式更新。在执行 Vue.set()
方法时,它会根据传入的数据源、具体数据及要赋的值,将其中符合条件的数据添加上响应式标记。当数据源中的已有属性值发生变化时,这个响应式标记会被触发,通知绑定了这个数据的组件更新对应的视图。
强制更新
在 Vue 中,当我们需要强制更新组件时,99.9% 的情况都是因为在某个地方出现了问题。可能是因为我们没有注意到响应式对象的变更检测注意事项,或者依赖了一个未被 Vue 的响应式系统追踪的状态。
如果我们已经注意到了上述的问题并修复了,但仍然需要手动强制更新时,我们可以使用 $forceUpdate() 方法。代码如下:
this.$forceUpdate()
更新响应式对象
Vue.set() 方法可以向响应式对象中添加一个新的 property,并确保这个新 property 同样是响应式的,且能触发视图更新。Vue.set() 方法必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property(比如 this.myObject.newProperty = ‘hi’)。
调用 Vue.set() 方法的语法为:this.$set(target, key, value)。其中:
- target:要更改的数据源,可以是对象或数组。
- key:要更改的具体数据。
- value:重新赋的值。
以下是几种使用 Vue.set() 方法的示例:
data() {
return {
list: [
{
name: '小明',
age: 18
},
{
name: '小美',
age: 12
}
],
text: '我是未修改的字符串值'
}
}
// 修改列表中小美的所有数据
this.$set(this.list, 1, {
name: '小美',
age: 18
})
// 修改列表中小美的年龄为18岁
this.$set(this.list[1], 'age', 18)
// 修改某个字符串属性
this.$set(this, 'text', '我是修改后的字符串值')
通过以上例子我们可以看到,Vue.set() 方法在修改响应式对象时非常实用。
更多推荐
所有评论(0)