数据响应式及getter/setter

325 阅读3分钟

数据响应式

Vue基本不用手动操作 dom,data 中声明的数据状态改变后会自动重新渲染相关的 dom。

换句话说就是 Vue 自己知道哪个数据状态发生了变化及哪里有用到这个数据需要随之修改。

关于数据响应式的问题

  • 怎样知道数据发生了变化?

Vue3 之前使用了 ES5 的一个 API Object.defineProperty Vue3 中使用了 ES6 的 Proxy,都是对需要侦测的数据进行 变化侦测 ,添加 getter 和 setter ,这样就可以知道数据何时被读取和修改。

  • 怎样知道数据变化后哪里需要修改?

Vue 对于每个数据都收集了与之相关的 依赖 ,这里的依赖其实就是一个对象,保存有该数据的旧值及数据变化后需要执行的函数。每个响应式的数据变化时会遍历通知其对应的每个依赖,依赖收到通知后会判断一下新旧值有没有发生变化,如果变化则执行回调函数响应数据变化(比如修改 dom)。

object.Defineproperty

Object.defineProperty(obj, prop, descriptor)
  • 参数说明:

    obj:必需。目标对象

    prop:必需。需定义或修改的属性的名字

    descriptor:必需。目标属性所拥有的特性

  • 返回值:

    传入函数的对象。即第一个参数obj

针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for..in或Object.keys()遍历。

给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。

这个属性一般是已经定义完却还想加属性的时候用

关于getter/setter

let obj0 = {
  姓: "高",
  名: "圆圆",
  age: 18
};
let obj1 = {
  姓: "高",
  名: "圆圆",
  姓名() {
    return this.姓 + this.名;
  },
  age: 18
};
console.log("需求一:" + obj1.姓名());
// 姓名后面的括号能删掉吗?不能,因为它是函数

姓名不要括号也能得出值

let obj2 = {
  姓: "高",
  名: "圆圆",
  get 姓名() {
    return this.姓 + this.名;
  },
  age: 18
};

console.log("需求二:" + obj2.姓名);

// 总结:getter 就是这样用的。不加括号的函数,仅此而已。

意思就是get可以使得一个函数转变成属性,但是这个属性是计算属性而不是一般的属性,只是以函数的形式表现出来。 那么计算属性是啥? 一般的计算属性值是函数形式,这个函数会返回一个值,并且其函数内部还可能会依赖别的变量 简单来说用法就是在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。除了上例简单的用法, 计算属性还可以依赖多个 Vue 实例的数据,只要其中任一数据变化,计算属性就会重新执行,视图也会更新 。 具体可以参考[Vue.js进阶]从源码角度剖析计算属性的原理

改写姓名

let obj3 = {
  姓: "高",
  名: "圆圆",
  get 姓名() {
    return this.姓 + this.名;
  },
  set 姓名(xxx){
    this.姓 = xxx[0]
    this.名 = xxx.slice(1)
  },
  age: 18
};

obj3.姓名 = '高媛媛'

console.log(`需求三:姓 ${obj3.姓},名 ${obj3.名}`)

// 总结:setter 就是这样用的。用 = xxx 触发 set 函数

note:

set一定要接受一个新的传参。这个参数就是后来传的,传进来的是高媛媛,我们就可以对其操作。

总结:

其实n(...)就是set/get后属性的样子,证明这个是可对其进行读写操作,但实际上这个是一个计算属性,是一个无实际存在的属性。