vue怎么触发视图更新
date
Nov 13, 2021
slug
view-update
status
Published
tags
Vue
type
Post
summary
vue怎么触发视图更新
在vue文档中的响应式原理一节,说明了什么情况下视图不会更新,但是没有详细说明为什么。本文旨在记录下自己学习的疑惑
思考这几个问题
根据文档 1不会。 2 会
Vue 不能检测以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
这是为什么?
因为数组的更新没触发拦截器,我们知道vue的响应式原理是
使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty
怎样会触发Object.defineProperty更新
首先拦截器只会对每个对象的每个属性监听,所以只能根据对象的每个属性拦截
- 对于数组,数组内部更改拦截不到,只有对list整体更改才能否拦截到
- 对于对象也一样
- 这是因为 比如
obj.list.a = 1
对于obj.list
是rhs
也就是get
操作,没有对obj.list
做set
操作,拦截器是对属性做set
操作,所以拦截不到
vue内部遍历了data所有属性给这些属性加了拦截器,递归遍历
vue数组方法
为什么开头的例子2中,对数组push了能被检测到更新呢? push也是修改list的属性不是修改data,所以首先不会被拦截器拦截到
为什么push能被监听到,是因为vue重写了数组方法,用这些方法能触发视图更新
数组中的对象
Proxy
proxy是数组代理, 对obj的任何属性修改都会进入set方法,最大的特点就是对任何属性做监听,因为他不是对属性的拦截器。是对对象本身的代理
不光能对存在的属性代理。不存在的也能监听
proxy比较灵活。但是为什么vue不用这个呢?因为vue2出来的时候没有proxy,在vue3会换成proxy
练习
不会console111因为没有在template里注册,因为规则是对template依赖收集,用到了才更新
不会console111,因为虽然a触发set了但是值没变化,这种情况不会触发视图更新和update钩子
会更新,因为数组是引用数据类型,两个不是同一个变量
总结:怎么触发视图更新
- 被拦截器拦截到set
- 被模板依赖收集到(有render不用)
- set的value有更改