理解 Vue 的 MVVM 模式

MVVM 模式实现

MVVM模式又称双向数据绑定,是数据影响视图,视图影响数据的模式

Vue: 实 现方式使用数据劫持+ 发布订阅模式,其核心为 Object.defineProperty 不兼容IE8以下
Angualr:  使用脏值检测
这次主要介绍 Vue 如何通过 Object.defineProperty() 实现 MVVM

Object.defineProperty(obj, ‘propertyName’, {
    value: Value,
    enumerable: boolean, //默认为fasle 其他属性为不可枚举 无法使用for遍历
    configurable: boolean, //默认false时不能进行删除
    writable: boolean, // 默认为false时无法修改
    // 当有writable和value时不可以使用set get
    //获取obj的值时调用
    get() {
        return 'silverwing'
    },
    //当给obj赋值时调用,参数为赋值的参数
    set(val) {
        console.log(val)
    }
})

数据劫持

使用 Object.defineProperty定义所有属性

Vue 实现 MVVM 的方式主要通过data里面的值 递归的进行数据劫持达到深度响应(因为每次赋予一个新对象时会给这个新对象增加数据劫持)

让我们手动模拟这么一个实现过程:
先创建 一个 html(任意名字) 和 mvvm.js 在同一个目录下

先创建 一个 html(任意名字) 和 mvvm.js 在同一个目录下

*.html




    
    
    
    Document


    



mvvm.js

function Soyas(options = {}) {
    this.$options = options // 将所有属性挂在在了$options
    // this._data
    var data = this._data = this.$options.data;
    observe(data)
}
function observe(data) {
    if (typeof data !== 'object')
        return new Observe(data)
}
// 观察对象增加Object.defineProperty
function Observe(data) { // 这里写主要逻辑
    for (let key in data) { // 把 data 属性 通过Object.defineProperty方式定义属性
        let val = data[key];
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                return val;
            },
            set(newVal) { // 更改值的时候
                if (newVal === val) {
                    // 设置的值和旧值一样的时候
                    return;
                }
                val = newVal; // 如果以后获取值的时候将刚才设置的值放回去
            }
        })
    }
}

控制台查看

理解 Vue 的 MVVM 模式_第1张图片

这样就完成了一个简单的数据劫持

但是任然存在问题

理解 Vue 的 MVVM 模式_第2张图片

当赋予一个对象时候我们仍需要对内部的对象进行数据劫持,以达到深度响应

如果没有进行数据劫持的情况下,属性不具有 set() get() 方法,此时是无法实现数据相应的

function Observe(data) { // 这里写主要逻辑
    for (let key in data) { // 把 data 属性 通过Object.defineProperty方式定义属性
        let val = data[key];
        observe(val); // 添加劫持
        Object.defineProperty(data, key, {
            ...
            set(newVal){
                ...
                observe(newVal) // 返回对象进行劫持
            }
        })
    }
}

再次查看控制台


理解 Vue 的 MVVM 模式_第3张图片


如此即可完成数据的每层对象进行劫持达到深度响应的效果

此时我们还需要做一件事,我们每次通过 soyas._data 这种方式访问并不优雅

我们可以通过数据代理达到 soyas.property 的方式访问

function Soyas(options = {}) {
    ...
    // this 代理了 this._data;
    for (let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key];
            },
            set(newVal) {
                this._data = newVal

            }
        })
    }
}

添加完上述代码后


理解 Vue 的 MVVM 模式_第4张图片


Very Good!一切OK

总结:

——Soyas 类内部 通过调用一个 observe 进行数据劫持到达到双向数据绑定

——达到深度响应我们需要在 Observe 遍历数据,和返回新值时候 递归调用 observe,对每一个对象进行数据劫持

——通过对象的内部使用 Object.defineProperty 使用 this 代理 this._data


你可能感兴趣的:(Vue)