vue

v-model原理

2019-07-11  本文已影响0人  名字一定要够长才可爱

1. v-model是什么?

2. v-model 原理:

vue的双向绑定是由数据劫持结合发布者-订阅者模式实现的,那么什么是数据劫持?vue是如何进行数据劫持的?说白了就是通过Object.defineProperty()来劫持对象属性的setter和getter操作,在数据变动时做你想要做的事情。

2-1. Object.defineProperty()

Object.defineProperty(obj, prop, desc)
  1. obj 需要定义属性的当前对象
  2. prop 当前需要定义的属性名
  3. desc 属性描述符

属性描述符

通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符,下面分别描述下两者的区别:

1>. 数据描述符 - 特有的两个属性(value,writable)
let Person = {}
Object.defineProperty(Person, 'name', {
  value: 'jack',
  writable: true // 是否可以改变
})
2>. 存取描述符 - 是由一对 getter、setter 函数功能来描述的属性
let Person = {}
let temp = null
Object.defineProperty(Person, 'name', {
  get: function () {
    return temp
  },
  set: function (val) {
    temp = val
  }
})
数据描述符和存取描述均具有以下描述符:

2-2. 如何使用Object.defineProperty实现数据劫持

function render() {
    console.log('模拟试图渲染');
}

let obj = {
    name: 'jiajia',
    location: {
        x: 100,
        y: 100
    }
}

let methods = ['pop', 'shift', 'unshift', 'sort', 'reverse', 'splice', 'push'];
// 先获取原先原型上的方法
let arrayProto = Array.prototype;
// 创建一个自己的原型 并且重写methods这些方法
let proto = Object.create(arrayProto);
methods.forEach(method => {
    proto[method] = function () {
        render();
        arrayProto[method].call(this, ...arguments);
    }
})

// 定义响应式
function defineReactive(data, key, value) {
    observer(value);
    Object.defineProperty(data, key, {
        get() {
            return value;
        },
        set(newValue) {
            observer(newValue);
            if (newValue !== value) {
                render();
                value = newValue;
            }
        }
    })
}

function observer(obj) {
    // 重写数组方法
    if (Array.isArray(obj)) {
        obj.__proto__ = proto;
        return;
    }
    // 把所有的属性定义成set/get的方式
    if (typeof (obj) == 'object') {
        for (let key in obj) {
            defineReactive(obj, key, obj[key]);
        }
    }
}
observer(obj);
上一篇下一篇

猜你喜欢

热点阅读