109、vue数据劫持

mvvm.js

function Jiechi(options = {}) {
    this.$options = options;//将所有属性挂载到options上
    var data = this._data = this.$options.data;
    observer(data);
    // 这里解决的是把所有data属性存放到实例上面可以让实例直接访问属性。现在是jiechi._data.a要转换成比如jiechi.a
    for (let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key];
            }, set(newVal) {
                this._data[key] = newVal;
            }
        })
    }
    new Compile(options.el, this)
}
function Compile(el, vm) {
    //el 表示替换的范围
    vm.$el = document.querySelector(el);
    console.log(vm.$el);
    // 创建文档碎片把属性都放到里面
    let fragment = document.createDocumentFragment();//将html内容存到内存里
    while (child = vm.$el.firstChild) {
        fragment.appendChild(child);
    }
    console.log(fragment);
    replace(fragment)
    function replace(fragment) {
        Array.from(fragment.childNodes).forEach(function (node) {
            let text = node.textContent.replace(/^\s*|\s*$/g,"");
            let reg = /\{\{(.*)\}\}/;
            if (node.nodeType === 3 && reg.test(text)) {
                // console.log(RegExp.$1)
                let arr=RegExp.$1.split('.');
                let val=vm;
                arr.forEach(function(k){//取this.a.a
                    val=val[k];
                });
                node.textContent=text.replace(/\{\{(.*)\}\}/,val);
            }
            if (node.childNodes.length>0) {
                replace(node);
            }
        });
    }
    vm.$el.appendChild(fragment);
}
//vm.$options
//观察对象给对象增加ObjectDefineProperty
function Observe(data) {//这里写我们的主要逻辑
    for (let key in data) {//把data属性通过object
        let val = data[key];
        //默认遍历data中劫持所有属性------解决劫持对象多层问题保证所有对象都会被劫持
        observer(val);
        //.defineproperty的方式 定义属性
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                return val;
            },
            set(newval) {
                if (newval == val) {//如果设置的值和以前的一样的时候直接返回
                    return;
                }
                val = newval;
                // 解决新加属性添加到劫持数据里
                observer(newval);
            }
        })
    }
}
function observer(data) {
    if (typeof data != 'object') return;
    return new Observe(data);
}



// 发布订阅
// 绑定的方法 都有update属性
function Dep(){
    this.subs=[];
}
Dep.prototype.addSub=function(sub){
    this.subs.push(sub);
}
Dep.prototype.notify=function(){
    this.subs.forEach(sub=>sub.update());
}
function Watcher(fn){
    this.fn=fn;
}
Watcher.prototype.update=function(){
    this.fn();
}




// 下面的数据劫持只是当前第一层数据比如:   a:1
//  如果a:{a:1}就不行了


// function Jiechi(options={}){
//     this.$options=options;//将所有属性挂载到options上
//     var data=this._data=this.$options.data;
//     observer(data);
// }
// //vm.$options
// //观察对象给对象增加ObjectDefineProperty
// function Observe(data){//这里写我们的主要逻辑
//     for(let key in data){//把data属性通过object
//         let val=data[key];
//         //
//         //.defineproperty的方式 定义属性
//         Object.defineProperty(data,key,{
//             enumerable:true,
//             get(){
//                 return val;
//             },
//             set(newval){
//                 if(newval==val){//如果设置的值和以前的一样的时候直接返回
//                     return;
//                 }
//                 val=newval
//             }
//         })
//     }
// }
// function observer(data){
//   return   new Observe(data);
// }

1.html




  



  

{{a.a}}

{{a.b}}

你可能感兴趣的:(109、vue数据劫持)