2. 数据响应式

114 阅读3分钟

getter和setter

示例代码:myData 居然变了

一开始是 {n:0},传给 new Vue 之后立马变成 {n: (...)} 【浏览器控制台可见】

{n: (...)} 是个什么玩意,为什么表现和 {n:0} 一致?

我们需要先学习一下 ES6特性 的 getter 和 setter

示例代码:不加括号的函数调用

学完之后呢?还是不理解 {n: (...)} 呀

Object.defineProperty

【用于添加新的属性,注意get不要return xxx,否则死循环,因为get本身不存在】

uTools_1684291106730.png

Object.defineProperty用法

可以给对象添加属性 value
可以给对象添加 getter / setter
getter / setter 用于对属性的读写进行监控

代理和监听

示例代码

代理(设计模式)

对 myData 对象的属性读写,全权由另一个对象 vm 负责
那么 vm 就是 myData 的代理(类比房东租房)
比如 myData.n 不用,偏要用 vm.n 来操作 myData.n

vm = new Vue({data: myData})
一、会让 vm 成为 myData 的代理(proxy)
二、会对 myData 的所有属性进行监控
为什么要监控,为了防止 myData 的属性变了, vm 不知道
vm 知道了又如何?知道属性变了就可以调用 render(data) 呀!
UI = render(data)

uTools_1684292752383.png

什么是响应式

我打你一拳,你会喊疼,那你就是响应式的
若一个物体能对外界的刺激做出反应,它就是响应式的
Vue 的 data 是响应式
const vm = new Vue({data: {n: 0}})
我如果修改 vm.n,那么 UI 中的 n 就会响应我
Vue 2 通过 Object.defineProperty 来实现数据响应式

响应式网页是啥? 如果我改变窗口大小,网页内容会做出响应,那就是响应式网页 比如 www.smashingmagazine.com/ 但是你要注意,用户没事不会拖动网页大小的

Object.defineProperty 的问题

Object.defineProperty(obj, 'n' , {...})

必须要有一个 'n',才能监听 & 代理 obj.n 对吧

如果前端开发者比较水,没有给 n 怎么办

示例一:Vue 会给出一个警告

示例二:Vue 只会检查第一层 属性

此时如果我点击 set b,请问视图中不会显示 1 ,因为 Vue 没法监听一开始不存在的 obj.b

解决办法

一、把 key 都声明好,后面不再加属性 二、使用 Vue.set 或者 this.$set

Vue.set 和 this.$set

  • 作用
新增 key
自动创建代理和监听(如果没有创建过)
触发 UI 更新(但并不会立刻更新)
  • 举例 this.$set(this.object, 'm', 100)

data中的数组

没有办法提前声明所有key,新增数组除了Vue.set,尤雨溪还引入了变异方法

他将数组的7个API篡改,调用后会更新UI

篡改演示(并非源码):

class VueArray extends Array{
  push(...args){
    const oldLength = this.length // this 就是当前数组
    super.push(...args)
    console.log('你 push 了')
    for(let i = oldLength; i<this.length; i++){
      Vue.set(this, i, this[i])
      // 将每个新增的 key 都告诉 Vue
    }
  }
}

对象中新增的 key

  • Vue 没有办法事先监听和代理
  • 要使用 set 来新增 key,创建监听和代理,更新 UI
  • 最好提前把属性都写出来,不要新增 key
  • 但数组做不到「不新增 key」

数组中新增的 key

  • 用 set 新增 key,会更新 UI,但不会创建监听和代理
  • 不过尤玉溪篡改了 7 个 API 方便你对数组进行增删
  • 这 7 个 API 会更新 UI,但不会自动处理监听和代理
  • this.array[n] = xxx,即不会更新 UI,也不会自动处理监听和代理

结论:数组新增 key 最好通过 7 个 API :push、pop、shift、unshift、splice、sort、reverse()