vue的響應式原理簡化代碼

vue.js

import {Dep} from './dep'
import {Compiler} from './compiler'
class Observe{
    obj:Object;

    constructor(obj){
      this.obj = obj;
      this.walk();
    }
    walk(){
        let keys = Object.keys(this.obj)
        for(let i = 0; i<keys.length; i++){
            defineReactive(this.obj,keys[i],this.obj[keys[i]])
        }
    }
}
function defineReactive(obj:Object,key:String,val:any) {
    var dep = new Dep();
    Object.defineProperty(obj,key,{
        enumerable: true,
        configurable: true,
        get:function () {
            if(Dep.target){
                console.log(Dep.target)
                dep.addSub(Dep.target)
            }
            return val
        },
        set:function (newVal) {
            val = newVal;
           // childOb = observe(newVal)
            console.log(8,dep)
            dep.notify()
        }
    })
}

export default class Vue{
options:Object;

constructor(options){
 this.options = options
 new Observe(this.options.data)
    let id = this.options.el;
   let element = document.getElementById(id);
    let dom  = new Compiler(element,this)
    element.appendChild(dom)
}
}

dep.js

var uid = 0;
export class Dep{
    static target: ?Watcher;
    id:Number;
    subs:Array;

    constructor(){
        this.id = uid++;
        this.subs = [];
    }

    addSub(sub){
        this.subs.push(sub)
    }

    notify(){
        const subs = this.subs.slice();
        for(let i=0;i<subs.length;i++){
            console.log('fabu',subs[i])
            subs[i].update();
        }
    }
}

watcher.js

import {Dep} from './dep'
export class Watcher{
    vm:Object;
    node:Object;
    name:String;
    type:String;
    value:any

    constructor(vm,node,name,type){
        Dep.target = this;
        this.vm = vm;
        this.node = node;
        this.name = name;
        this.type = type;
        this.update();
    }

    update(){
        this.get();
        console.log('34444',this.node[this.type])
        this.node[this.type] = this.value;
    }
    get(){
        this.value = this.vm.options.data[this.name];
    }
}

compiler.js

import {Watcher} from  './watcher'
export class Compiler{
    node:any;
    vm:Object;
    constructor(node,vm){
        this.node = node;
        this.vm = vm;
        this.$frag = this.nodeTofragement(this.node,this.vm)
        return this.$frag;
    }
    compileElemnt(node,vm){
        let reg = /\{\{(.*)\}\}/;
        var vm = this.vm
        if(node.nodeType == 1){
            let attr = node.attributes;
            for(let i = 0;i<attr.length;i++){
                if(attr[i].nodeName == 'v-model'){
                    let name = attr[i].nodeValue;
                    node.addEventListener('input', e => {
                        vm.options.data[name] = e.target.value;
                    });
                    console.log('w1')
                    new Watcher(vm,node,name,'value')
                }
            }
        }
        if(node.nodeType == 3){
            if(reg.test(node.nodeValue)){
                let name = RegExp.$1;
                node.nodeValue = vm.options.data[name];
                console.log('w2')
                new Watcher(vm,node,name,'nodeValue')
            }
        }
    }
    nodeTofragement(node,vm){
        let fragment = document.createDocumentFragment();
        let child;
        while(child = node.firstChild){
          this.compileElemnt(child,vm);
          fragment.appendChild(child)
        }
        return fragment;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章