简单说:Vue.js的数据响应式

352 阅读3分钟

响应式

这个词可能异常的火爆,比如响应式布局响应式编程,“响应式”不难理解,针对事物改变做出自适应的变化,比如响应式布局就是根据页面显示大小对布局做出改变,而最近,看到了Vue.js的数据响应式,那就总结一下,有错误大家可以指出,我会加以改正(~ ̄▽ ̄)~。

正题:一、响应式体现

直接上代码!

<template>
  <div>
    <span>{{ name }}</span>
    <button @click="modifyname">修改name</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      name: "ll",
    };
  },
  methods: {
    modifyname() {
      this.name = "cc";
    },
  },
};
</script>

可以看到,这是一个简单的vue单文件中的内容,当我们点击按钮的时候,通过改变数据,来自动更新视图,所以,当我们使用Vue框架的时候,只需关注页面数据如何变化,因为数据变化后,视图也会自动更新,这让我们从繁杂的 DOM 操作中解脱出来,提高开发效率。

这里插入一个bug:

在使用vue的时候,data最好写成函数的形式,而不是对象,关于这点,在Vue文档中也只是进行了提及,具体原因在一次使用中,我发现到了bug:

data:{
    n:0
   }

这样写完全没问题,但是vue使用非完整版的时候,会进行

render(h) { return h(demo) },

如果你只是渲染了一次demo,并不会出现任何的错误,但是当你去渲染两个demo的时候,它会把data当作同样的对象进行处理,导致有些数据缺失,但是当data为

data() {
    return {
      n:0
    };
  },

此时,即使渲染两次demo,它也会把data作为单独的函数,不会造成上面的结果。

Object.defineProperty()

它和 Vue3 中的 proxy 可以来进行一下对比

  • Object.defineProperty()是针对单独的,个体的值,举个例子:
let person = {}
let personName = 'cc'

//在person对象上添加属性name,值为personName
Object.defineProperty(person, 'name', {
    //但是默认是不可枚举的(for in打印打印不出来),可:enumerable: true
    //默认不可以修改,可:wirtable:true
    //默认不可以删除,可:configurable:true
    get: function () {
        console.log('触发了get方法')
        return personName
    },
    set: function (val) {
        console.log('触发了set方法')
        personName = val
    }
})

//当读取person对象的nam属性时,触发get方法
console.log(person.name)

//当修改personName时,重新访问person.name发现修改成功
personName = 'zs'
console.log(person.name)

// 对person.name进行修改,触发set方法
person.name = 'qq'
console.log(person.name)

当然,这只是一个值,那当我想要监听这个对象所有属性呢?
哦吼,你会发现,它表示很无奈,它必须去一个个遍历,一个个添加监听!而且,最致命的缺点是: 它 新增/删除元素 无法监听,必须去调用另外的api

所以,出现了 proxy

先来看个例子:

//定义一个需要代理的对象
let person = {
    age: 0,
    school: 'xx'
}
//定义handler对象
let hander = {
    get(obj, key) {
        // 如果对象里有这个属性,就返回属性值,如果没有,就返回默认值66
        return key in obj ? obj[key] : 66
    },
    set(obj, key, val) {
        obj[key] = val
        return true
    }
}
//把handler对象传入Proxy
let proxyObj = new Proxy(person, hander)

// 测试get能否拦截成功
console.log(proxyObj.age)//输出0
console.log(proxyObj.school)//输出xx
console.log(proxyObj.name)//输出默认值66

// 测试set能否拦截成功
proxyObj.age = 18
console.log(proxyObj.age)//输出18 修改成功

可以看出,Proxy代理的是整个对象,而不是对象的某个特定属性,不需要我们通过遍历来逐个进行数据绑定。 另外,其实深究的话,你会发现,proxy返回的其实还是一个proxy代理,它是层层代理。 基于上述Object.defineProperty()无法解决的问题,对 proxy 来说就是小菜一碟。

完结

简单记录一下自己在研究 Object.defineProperty() 和 proxy 的区别时候的重点,主要就是它们监听的方法,或者说范围大小的不同,文章有些地方没有去详细的举例子,可以参考一下MDN来理解。