美文网首页vue
v-model原理

v-model原理

作者: 名字一定要够长才可爱 | 来源:发表于2019-07-11 15:09 被阅读0次

    1. v-model是什么?

    • 在表单控件或者组件上实现双向绑定

    2. v-model 原理:

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

    2-1. Object.defineProperty()

    • Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
    Object.defineProperty(obj, prop, desc)
    
    1. obj 需要定义属性的当前对象
    2. prop 当前需要定义的属性名
    3. desc 属性描述符
    • 注意: 一般通过为对象的属性赋值的情况下,对象的属性可以修改也可以删除,但是通过Object.defineProperty()定义属性,通过描述符的设置可以进行更精准的控制对象属性。

    属性描述符

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

    1>. 数据描述符 - 特有的两个属性(value,writable)
    let Person = {}
    Object.defineProperty(Person, 'name', {
      value: 'jack',
      writable: true // 是否可以改变
    })
    
    2>. 存取描述符 - 是由一对 getter、setter 函数功能来描述的属性
    • get:一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
    • set:一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined。
    let Person = {}
    let temp = null
    Object.defineProperty(Person, 'name', {
      get: function () {
        return temp
      },
      set: function (val) {
        temp = val
      }
    })
    
    数据描述符和存取描述均具有以下描述符:
    • configrable 描述属性是否配置,以及可否删除
    • enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中

    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);
    

    相关文章

      网友评论

        本文标题:v-model原理

        本文链接:https://www.haomeiwen.com/subject/pfzrkctx.html