设为首页 加入收藏

TOP

mvvm实现一个简单的vue
2019-09-17 18:59:28 】 浏览:25
Tags:mvvm 实现 一个 简单 vue

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'

 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇阿里云人脸比对API封装 下一篇可能是全网最详细的express--midd..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目