对Vue数据响应式的个人理解

文章出处部分来源

一.一张图追踪数据响应式变化

数据响应式是Vue 最独特的特性之一,是其非侵入性的响应式系统。数据模型仅仅是普通的 JavaScript 对象。而当你修改它们时,视图会进行更新。

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装 vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。

image.png

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。尽管如此我们还是有一些办法来回避这些限制并保证它们的响应性

二.vue数据响应式的含义是什么?

vue能实现对实例中声明过的数据进行监听。当数据发生变化时,试图会根据变化内容进行重新渲染页面,从而简化程序员的工作。

三.如何做到数据响应式?

通过 object.defineProperty(),配合 getter 和 setter 实现监听,同时引入代理,负责对象的属性读写,代码如下:
复制代码
// 需求五:就算用户擅自修改 myData,也要拦截他

let myData5 = {n:0}
let data5 = proxy2({ data:myData5 }) // 括号里是匿名对象,无法访问

function proxy2({data}{
  let value = data.n
  Object.defineProperty(data, 'n', {
    get(){
      return value
    },
    set(newValue){
      if(newValue<0)return
      value = newValue
    }
  })
  // 就加了上面几句,这几句话会监听 data

// data5 就是 obj
console.log(`需求五:${data5.n}`)
myData5.n = -1
console.log(`需求五:${data5.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`需求五:${data5.n},设置为 1 成功了`)

复制代码

vm = new Vue({data:myData}),会让vm成为myData的代理,对myData的所有睡醒进行建空,防止myData发生变化。只有代理vm知道了变化,才能根据变化重新渲染视图。

四.如何给数据新增key

1.普通的对象

使用Vue.set 或者this.set(set(加是为了防止命名冲突)

methods: {
    setB() {
      Vue.set(this.obj, 'b', 1)
			// 等价于 this.$set(this.obj, 'b', 1)
    }
  }

复制代码

结果:
新增key,自动创建代理和监听,触发UI更新

2.数组对象

代码:

class VueArray extends Array{
	push(...args){
		const oldLength = this.length
		super.push(...args)
		console.log('你push了')
		for(let i = oldLength; i<this.length; i++){
			Vue.set(this, i ,this[i])
		}
	}
}

//这不是Vue的真实实现,只是展示下思路

复制代码

原理就是新增一层原型,供vue使用。

具体就这么多,后面了解深入之后再进行更新。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享