欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mvvm实现一个简单的vue

程序员文章站 2022-03-16 08:45:43
vue,基于mvvm模式下的一个前端框架 mvvm模式下简单的实现数据代理,数据劫持 1.是用Object.defineProperty 实现数据代理 2.使用发布订阅者模式,配合 Object.defineProperty,实现数据劫持 数据劫持包括依赖收集和依赖促发 (只考虑最简单的方式,并且没 ......

vue,基于mvvm模式下的一个前端框架

  mvvm模式下简单的实现数据代理,数据劫持

  1.是用object.defineproperty 实现数据代理

  2.使用发布订阅者模式,配合 object.defineproperty,实现数据劫持

    数据劫持包括依赖收集和依赖促发

  (只考虑最简单的方式,并且没有包括具体的依赖收集,我模拟的依赖收集,依赖收集得是在模板解析的时候,需要使用正则匹配出vue的一般指令和表达式)

/* 实现一个简易的vue */
class myvue {
    constructor (option) {
        let _self = this
        this._data = option.data
        this.proxydata(_self)
        /* 使用发布订阅者模式实现数据劫持 */
        this.datahijacking(_self)

        /* 实现一下模拟依赖收集 */
        /* 本身模板解析时,会使用正则去匹配表达式和一般指令
            匹配成功的表示是和一般指令都会调用以此数据劫持上的get方法
        */
        /* 假知我们传入的就是name 和 age */
        this._data.name;
        this._data.name;
        this._data.name;       
        this._data.age;
        this._data.age;
        /* 上面代表模板解析的时候一共调用的三次name 和 两次age */
    }
    /* 实现vue对_data数据的代理 */
    proxydata(_self) {
        /* 遍历传入的data的所有属性 */
        object.keys(_self._data).foreach(key=>{
            object.defineproperty(_self,key,{
                configurable:true,
                enumerable: true,
                get () {
                    return _self._data[key]
                },
                set (val) {
                    _self._data[key] = val
                }
            })
        })
    }
    /* 对_data数据劫持 */
    datahijacking(_self) {
        object.keys(_self._data).foreach(key=>{
            let value = _self._data[key]
            var dep = new dep();
            object.defineproperty(_self._data,key,{
                configurable:true,
                enumerable: true,
                get () {
                    dep.addsubs(dep.id,new watch(key))
                    return value
                },
                set (val) {
                    dep.notify(val)
                }
            })
        })
    }
}

var uid = 0;
class dep {
    constructor () {
        this.id = uid++;
        this.handlers = []
    }
    /* 依赖添加 */
    addsubs (id,fn) {
        if(!this.handlers[id]) {
            this.handlers[id] = []
        }
        this.handlers[id].push(fn)
    }
    /* 依赖促发 */
    notify (val) {
        if(this.handlers) {
            this.handlers[this.id].foreach(fn=>{                
                fn.update(val);
            })
        }
    }
}
/* 具体订阅者 */
class watch {
    constructor (name) {
        this.name = name
    }
    update (val) {
        /* 模拟试图更新 */
        console.log('视图更新了'+val)
    }
}

let vm = new myvue({data:{
    name: 'czklove',
    age: '17'
}})
console.log(vm)

vm.name = 'czklovel11'