美文网首页
Vue 的数据响应式

Vue 的数据响应式

作者: 我是Msorry | 来源:发表于2021-01-03 08:24 被阅读0次

深入响应式原理文档

从下面这个小例子带你走进Vue数据响应式

const myData = {
  n: 0
}
 console.log(myData) 

new Vue({
  data: myData,
  template: `
    <div>{{n}}</div>
  `
}).$mount("#app");

setTimeout(()=>{
  myData.n += 10
  console.log(myData) 
},3000)

Object {n: 0}
Object {n: (...)}

一个对象作为数据传递给Vue后,变得不一样了,究竟发生了什么?

const vm = new Vue({data:myData})做了什么?

1.vm成为myData的代理(proxy),如果没有vmthis会代指这个对象
2.对myData的所有属性进行监听,一旦myData的属性发生变化,vm立即知道
3.属性变化后,调用render(data),UI = render(data)

const data = {a:1,b:2}

function proxy({data}) {
  const obj = {}
  for (let key in data) {
    //监听data
    let value = data[key]
    Object.defineProperty(data, key, {
        get() {
            return value
          },
          set(v) {
            value = v
          }
      })
      // obj 就是代理
    Object.defineProperty(obj, key, {
      get() {
          return data[key]
        },
        set(value) {
          data.n = value
        }
    })

  }
  return obj 
}
console.log(data)
let vm = proxy({data:data})
console.log(data)
//在外部修改数据,看vm是否也跟着发生变化
data.a = 2
console.log(vm.a)

Object {a: 1,b: 2}
Object {a: (...),b: (...)}
2

同理,Vue对methods和computed也有处理

数据响应式

当数据发生改变后,Vue会通知到使用该数据的代码,自动视图更新

Vue只监听第一层属性的变化,不监听嵌套属性,否则效率低

因为obj.b没有在data中没有,所以不会被监听,undefined状态的数据Vue不会渲染到页面

new Vue({
  data: {
    obj: {
      a: 0 // obj.a 会被 Vue 监听 & 代理
    }
  },
  template: `
    <div>
      {{obj.b}}
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      this.obj.b = 1; //请问,页面中会显示 1 吗?
    }
  }
}).$mount("#app");

解决办法

1.用.set方法

Vue.set(this.obj,"b",1)
this.$set(this.obj,"b",1)
console.log(Vue.set===this.$set)//true,这两种方式一模一样

Vue.set做了两件事:新增属性,并自动地对这个属性创建代理和监听
Vue发现这个属性从undefined的状态变成1,触发render,更新页面

2.提前在data中声明好,初始值设为undefined


但是,当为数组时,无法提前声明,每次用Vue.set很麻烦

new Vue({
  data: {
    array: ["a", "b", "c"]
  },
  template: `
    <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods: {
    setD() {
      this.array[3] = "d"; //请问,页面中会显示 'd' 吗?
      // 等下,你为什么不用 this.array.push('d')
    }
  }
}).$mount("#app");

解决方法

this.array.push(value)
console.log(this.array)

通过控制台可以看出,push方法变了,Vue篡改了数组的API
变异方法文档

Vue的变异方法实现思路(并不是源码)

Vue会给这个数组加一层原型,对于数组的变化,自动Vue.set
篡改push方法,对于Array的变化通过Vue.set通知给Vue

class VueArray extends Array{
  push(...args){
      const oldLength = this.length //this 当前数组
      super.push(...args)//调用父类的push
      for(let i = oldLength;i < this.length;i++){
        Vue.set(this,i,this[i])
      }
  }
}

const vueArrayPrototype = { 
  push: function(){ 
        return Array.prototype.push.apply(this, arguments) 
  } 
} 
vueArrayPrototype.__proto__ = Array.prototype //不是标准属性

const array = Object.create(vueArrayPrototype) array.push(1)

总结

  1. const vm = new Vue({data:myData}) 这个语句中,this就是vmvmmyData的代理,所以this.n能够读取
  2. Vue没有办法监听和代理新的Key
  3. 要使用set来新增Key,创建代理和监听,更新UI
  4. 最好提前把属性都写出来,不要新增Key
  5. 但是数组做不到「不新增Key」
  6. 数组也可以用set来新增Key,创建代理和监听,更新UI
  7. Vue为解决这个困扰,篡改7个数组API
  8. 这7个API会自动处理监听和代理,并更新UI

https://www.jianshu.com/p/4dff7c2cdaaa

相关文章

  • 前端面试题【Day02】

    本篇绪论 1,Vue响应式原理 1,Vue响应式原理 在vue实例中声明的数据就是响应式的。响应式:数据发生改变,...

  • 2020-12-25

    Vue数据响应式 响应式:当一个物体对外界刺激做出反应,就是响应式。例如:我打你一拳你知道躲。 Vue 数据响应式...

  • Vue的响应式浅析

    1 Vue如何实现响应式? Vue的响应式是建立在监听data中的数据. 2 在Vue2中响应式的实现 Vue通过...

  • Vue源码03-响应式原理

    这节将专门讲解vue MVVM响应式处理 Vue采用的是 实现数据的响应式 数据劫持 Observer类 Obse...

  • 学习vue的响应式 mvvm -01 数据响应式

    理解VUE的设计思想:VUE的核心是MVVM MVVM框架的三要素:数据响应式 模板引擎以及渲染 数据响应式:监听...

  • Vue数据响应式

    1.什么是数据响应式 在 Vue 中,当 data 中的数据发生改变时,视图会进行更新,这就是Vue数据响应式的概...

  • 深入理解Vue数据响应式

    Vue数据响应式主要研究的是 Vue 构造选项中 data 属性的特性 深入响应式 官方文档 网址: https:...

  • VUE中数据响应式原理

    1.vue数据响应式的原理2.数据属性的四大特性3.访问器属性4.getter和setter vue数据响应式主要...

  • 双向绑定

    数据响应式原理 vue实现数据响应式的原理就是利用了Object.defineProperty(),重新定义了对象...

  • Vue 数据响应式原理

    前言 Vue.js 的核心包括一套“响应式系统”。 “响应式”,是指当数据改变后,Vue 会通知到使用该数据的代码...

网友评论

      本文标题:Vue 的数据响应式

      本文链接:https://www.haomeiwen.com/subject/rkorjktx.html