美文网首页
双向绑定简单实现

双向绑定简单实现

作者: coffee1949 | 来源:发表于2021-03-22 18:34 被阅读0次

    https://www.jb51.net/article/172633.htm

    function Vue(options){
        this.$data = options.data
        this.$el = document.querySelector(options.el)
    
        this.derevtive = {}
    
        this.Observer(this.$data)
        this.Compile(this.$el)
    }
    
    Vue.prototype.Observer = function(data){
        for(let key in data){
            this.derevtive[key] = []
            let direct = this.derevtive[key]
            let oldVal = data[key]
    
            Object.defineProperty(this.$data, key, {
                get(){
                    return oldVal
                },
                set(newVal){
                    if(newVal !== oldVal){
                        oldVal = newVal
                        direct.forEach(item=>{
                            item.updata()
                        })
                    }
                }
            })
        }
    }
    
    Vue.prototype.Compile = function(node){
        let nodes = node.children
        for(let i=0,len=nodes.length;i<len;i++){
            let nodeChild = nodes[i]
            if(nodeChild.children.length){
                this.Compile(nodeChild)
            }
    
            if(nodeChild.hasAttribute('v-text')){
                let attr = nodeChild.getAttribute('v-text')
                this.derevtive[attr].push(new Watcher({
                    nodeChild,
                    type: 'innerText',
                    vm: this,
                    attr
                }))
            }
    
            if(nodeChild.hasAttribute('v-model')){
                let attr = nodeChild.getAttribute('v-model')
                this.derevtive[attr].push(new Watcher({
                    nodeChild,
                    type: 'value',
                    vm: this,
                    attr
                }))
                nodeChild.addEventListener('input', ()=>{
                    this.$data[attr] = nodeChild.value
                })
            }
        }
    }
    
    
    function Watcher(options){
        this.nodeChild = options.nodeChild
        this.type = options.type
        this.vm = options.vm
        this.attr = options.attr
        this.updata()
    }
    
    Watcher.prototype.updata = function(){
        this.nodeChild[this.type] = this.vm.$data[this.attr]
    }
    

    https://zhuanlan.zhihu.com/p/282763032

    class Vue {
        constructor(options){
            this.$data = options.data
            this.$el = document.querySelector(options.el)
            
            this.derevtive = {}
    
            this.Observer(this.$data)
            this.Compile(this.$el)
        
        }
    
        // 数据劫持,代理所有的数据
        Observer(data){
            for(let key in data){
                
                this.derevtive[key] = []
                let direct = this.derevtive[key]
                let oldVal = data[key]
    
                Object.defineProperty(this.$data, key, {
                    get(){
                        return oldVal
                    },
                    set(newVal){
                        if(newVal !== oldVal){
                            oldVal = newVal
                            // 这里数据更新了,发布消息通知视图更新,
                            // this.derevtive里面存储了所有的数据的全部watcher实例,在解析指令的过程中创建
                            direct.forEach(item=>{
                                item.updata()
                            })
    
                        }
                    }
                })
    
    
            }
        }
    
        // 指令解析
        Compile(node){
            let nodes = node.children
            for(let i=0,len=nodes.length;i<len;i++){
                let nodeChild = nodes[i]
                if(nodeChild.children.length){
                    this.Compile(nodeChild)
                }
    
                if(nodeChild.hasAttribute('v-text')){
                    let attr = nodeChild.getAttribute('v-text')
    
                    this.derevtive[attr].push(new Watcher({
                        nodeChild,
                        type: 'innerText',
                        vm: this,
                        attr: attr
                    }))
    
                }
    
                if(nodeChild.hasAttribute('v-model')){
                    let attr = nodeChild.getAttribute('v-model')
    
                    this.derevtive[attr].push(new Watcher({
                        nodeChild,
                        type: 'value',
                        vm: this,
                        attr: attr
                    }))
    
                    nodeChild.addEventListener('input', ()=>{
                        this.$data[attr] = nodeChild.value
                    })
                }
    
            }
        }
    
    }
    
    class Watcher {
        constructor(options){
            this.nodeChild = options.nodeChild
            this.type = options.type
            this.vm = options.vm
            this.attr = options.attr
            this.updata()
        }
    
        updata(){
            this.nodeChild[this.type] = this.vm.$data[this.attr]
        }
    }
    

    相关文章

      网友评论

          本文标题:双向绑定简单实现

          本文链接:https://www.haomeiwen.com/subject/wfqthltx.html