Vue2数据响应式的理解

467 阅读2分钟

总结

  • Vue2数据响应式的实现是通过ES6的setter和getter这两个API还有Object.defineProperty函数来实现的,主要是new Vue后Vue对options内的data进行了一系列的操作,让data能够拥有响应式,

一、数据响应式是什么

  • 你被打一拳你喊疼,那你就是响应式

  • 当一个物体能对外界的刺激做出反应,它就是响应式的

  • Vue的data是响应式,Vue知道属性变了就能调用render(data)

  • UI = render(data)

代码验证

const vm = new Vue({data:{ n : 0 }})

  • 如果修改vm.n,那么UIn就会响应我

  • Vue2就是通过Object.defineProperty实现数据响应式,你传给Vue一个data,Vue会把这个data做监听和代理的操作,以达到数据响应式的效果

二、getter/setter 怎么理解

  • 用于对属性的读写进行监控(观察)

  • getter: 读取属性

  • setter:改写属性

代码实例


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

console.log(obj2.姓名);// 高圆圆
obj3.姓名 = "刘诗诗";
console.log(`姓${obj3.姓},名${obj3.名}`); //姓刘,名诗诗

三、Object.defineProperty() 怎么理解

  • 可以给对象添加属性Value

  • 可以个对象添加getter/setter

  • 可以给对象的属性进行代理

代理是什么

  • 是一种设计模式,类似于房东、中介和租客的关系

  • 为了对数据进行监控,监控能防止属性变了,但Vue不知道,这样就不能响应数据了

代码实例

// 需求:定义n的值,n小于0就不运行,n大于0则正常运行,要防止用户直接访问到数据

let data1 = proxy({data:myData}) //匿名的数据 不能被直接访问

function proxy({data}){ //
    let value = data.n   // 这里直接覆盖了data.n的值 也就是myData5的n
    Object.defineProperty(data,'n'{
        get(){
        return value
        },
        set(newValue){
            if(newValue<0)return
            value = newValue
        }
    })  // 就加了上面几句话,就能监听data

    const obj = {}
    Object.defineProperty(obj,'n',{
        get(){
            return data.n
        },
        set(value){
            if(value<0)return
            data.n = value
        }
    })
    return obj // obj就是代理
}

console.log(`${data1.n}`)
myData5.n = -1
console.log(`${data1.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`${data1.n},设置为 1 成功了`)

// let data1 = proxy({ data:myData })
// let vm = new Vue({data: myData})
// 几乎和Vue一样

四、数据响应式关于数组的处理

  • 因为数组不能提前知道它的长度,大多数时候数组是需要进行增删改处理的

  • 在把数组传给Vue时,Vue监听到了当时数组的key,后续增加的key用常规的方式并不具备数据响应的能力

解决方法

  • Vue给数组定义了一个重新封装拥有7个API的原型,这个原型是在数组的原型上增加的一层原型链,给开发者提供了数组的数据响应式功能

  • 具体使用方法看一下文档即可了解列表渲染 — Vue.js (vuejs.org)

需要注意的Vue不能监测以下数组的变动

  1. 当你利用索引直接设置一个数组项时

  2. 当你修改数组的长度时

代码示例


var vm = new Vue({ 
    data: { 
        items: ['a', 'b', 'c'] 
    } 
})  

vm.items[1] = 'x' // 不是响应性的 
vm.items.length = 2 // 不是响应性的

  1. 一定要用Vue提供的7个API操作数组($set也行)

五、数据响应式关于对象的处理

  • 假如你Vue的data没有定义a数据,而你却使用了a数据,Vue就会报错

代码示例

var vm = new Vue({ 
    data:{ 
        a:1 
    } 
}) 

// `vm.a` 是响应式的 

vm.b = 2 
// `vm.b` 是非响应式的

如果需要添加响应式property

  • 需要用到Vue.set或者this.$set

代码示例

// Vue.set
Vue.set(vm.someObject, 'b', 2)

// this.set
this.$set(this.someObject,'b',2)
  • 这两个方法是完全一样的用哪个都行