Vue数据代理

68 阅读2分钟

Vue

数据代理

通过一个对象代理另一个对象的属性操作(借助Object.defineProperty方法)

let obj1 = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,'x',{
        get(){
            return obj1.x
        }, // 读取obj2.x时调用getter
        set(value){
            obj1.x = value
        } // 修改obj2.x时调用setter
    }
)

image.png 修改obj2.x的值时obj1.x的值同步变化。

计算属性

要用的属性不存在,通过已有的属性计算得来。
原理:借助Object.defineProperty方法提供的getter()setter()

姓:<span>{{firstName}}</span>
名:<span>{{LastName}}</span>
全名:<span>{{fullName}}</span>

new Vue(
    {
        data(){
            return {
                firstName: '张',
                lastName: '三'
            }
        },
        computed: {
            fullName: {
                getter() {
                    return firstName + '-' + LastName // firstName和lastName是计算属性所依赖的数据
                },
                setter(val) {
                // val是修改后的fullName值
                    const arr = val.split('-')
                    this.firstName = arr[0]
                    this.lastName = arr[1]
                },
            }
        }
    }
)

getter什么时候执行?

  1. 初次读取(fullName)时会执行一次;
  2. getter调用后缓存当前fullName,所依赖的数据发生改变会再次调用。

setter什么时候执行?当fullName被修改时。

计算属性最终会出现在vm实例,如果要被修改,必须写set函数去响应修改,且set中要引起所依赖的数据变化。

计算属性简写

// 只考虑读取不修改时,计算属性可简写为:
computed: {
    fullName() {
        return firstName + '-' + lastName
    }
}

计算属性vs侦听属性

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成(如watch可以进行异步操作)
watch: {
    firstName(newVal){
        setTimeout(()=>{return newVal + '-' + lastName},1000) //1s后返回fullName
    },
    lastName(newVal){
        setTimeout(()=>{return firstName + '-' + newVal},1000)
    }
}

Tips:

  1. 所有被Vue管理的函数最好写成普通函数,this指向vm或组件实例对象
  2. 所有不被Vue管理的函数(如定时器回调函数,ajax回调函数,Promise回调函数),最好写成箭头函数,(js引擎调用函数,但箭头函数没有自己的this,就会向外找,即firstName函数的this),这样this才会指向vm或组件实例对象