daily-share icon indicating copy to clipboard operation
daily-share copied to clipboard

数据双休绑定,数据劫持,数据代理(2020-2-1)

Open yaogengzhu opened this issue 5 years ago • 3 comments

数据双休绑定,数据劫持,数据代理

function Lesson(options = {} ) {
    this.$options = options
    var data = this._data = this.$options.data
    // 数据观察
    observe(data)
   // 数据代理到this
    for(let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key]
            },
            set(newVal) {
                if (this._data[key] === newVal ) {
                    return
                }
                this._data[key] = newVal
            }
        })
    }
}

function observe(data) {
   // 判断data是不是一个对象 
   if (type data !== 'object')  return 
    return new Observe(data)
}

function Observe(data) {  // 数据双向绑定的逻辑
    for(let key in data) {
        let val = data[key]
        observe(val) // 观察
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                return val
            },
            set(newVal) {
                if (val === newVal ) {
                    return
                } 
                val = newVal
                observe(newVal)
            }
        })
    }

}

yaogengzhu avatar Feb 01 '20 04:02 yaogengzhu

编译的一个过程

function Lesson(options= {}) {
    this.$options = options
    var data = this._data = this.$options.data
    observe(data)
    for(let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key]
            },
            set(newVal) {
                if (this._data[key] === newVal) return
                this._data[key] = newVal
            }
        })
    }
    //这里做编译
    new Compile(options.el, this)
}

function observe(data) {
    if (typeof data !== 'object' ) return 
    return new Observe(data)
}   

function Observe(data) {
    // 处理具体的Objcet.defineProperty的逻辑
    for (let key in data) {
        let val = data[key]
        observe(val)
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                return val
            },
            set(newVal) {
                if (val === newVal) return
                val = newVal
                observe(newVal)
            }
        })
    }
}

function Compile(el, vm) {
    vm.$el = document.querySelector(el)
    let fragement = document.createDocumentFragment()
    while( child = vm.$el.firstChild) {
        fragement.appendChild(child)
    }
    // 处理fargement
    // console.log(Array.from(fragement.firstChild))
    
    // let arr = Array.from(fragement.firstChild)
    replace(fragement)
    function replace(fragement) {
        Array.from(fragement.childNodes).forEach( node => {
            let text = node.textContent
            let reg = /\{\{(.*)\}\}/
            // console.log(node.nodeType)
            if (node.nodeType === 3 && reg.test(text)) {
                // console.log(RegExp.$1)
                let arr = RegExp.$1.split('.')
                let val = vm
                arr.forEach( k => {
                    val = val[k]
                })
                node.textContent = text.replace(reg, val)
            }
            if (node.childNodes) {
                replace(node)
            }
        })
    }
    vm.$el.appendChild(fragement)
}

yaogengzhu avatar Feb 01 '20 06:02 yaogengzhu

新增发布订阅模式

function Lesson(options= {}) {
    this.$options = options
    var data = this._data = this.$options.data
    observe(data)
    for(let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key]
            },
            set(newVal) {
                if (this._data[key] === newVal) return
                this._data[key] = newVal
            }
        })
    }
    //这里做编译
    new Compile(options.el, this)
}

function observe(data) {
    if (typeof data !== 'object' ) return 
    return new Observe(data)
}   

function Observe(data) {
    // 处理具体的Objcet.defineProperty的逻辑
    let dep = new Dep()
    for (let key in data) {
        let val = data[key]
        observe(val)
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                Dep.target && dep.addSubs(Dep.target)
                return val
            },
            set(newVal) {
                if (val === newVal) return
                val = newVal
                observe(newVal)
                dep.notify()
            }
        })
    }
}

function Compile(el, vm) {
    vm.$el = document.querySelector(el)
    let fragement = document.createDocumentFragment()
    while( child = vm.$el.firstChild) {
        fragement.appendChild(child)
    }
    // 处理fargement
    // console.log(Array.from(fragement.firstChild))
    
    // let arr = Array.from(fragement.firstChild)
    replace(fragement)
    function replace(fragement) {
        Array.from(fragement.childNodes).forEach( node => {
            let text = node.textContent
            let reg = /\{\{(.*)\}\}/
            // console.log(node.nodeType)
            if (node.nodeType === 3 && reg.test(text)) {
                // console.log(RegExp.$1)
                let arr = RegExp.$1.split('.')
                let val = vm
                arr.forEach( k => {
                    val = val[k]
                })
                new Watcher(vm, RegExp.$1,function(newVal) {
                    node.textContent = text.replace(reg, newVal)
                })  
                node.textContent = text.replace(reg, val)
            }
            if (node.childNodes) {
                replace(node)
            }
        })
    }
    vm.$el.appendChild(fragement)
}

function Dep() {
    this.subs = []
}
Dep.prototype.addSubs = function(fn) {
    this.subs.push(fn)
}
Dep.prototype.notify = function() {
    // console.log(this.subs)
    this.subs.forEach( fn => {
        // console.log()
        fn.update()
    } )
}

function Watcher(vm, exp, fn) {
    this.vm = vm
    this.exp = exp
    this.fn = fn
    Dep.target = this
    let val = vm
    let arr = exp.split('.')
    arr.forEach( k => {
        val = val[k]
    })  
    Dep.target = null  
}

Watcher.prototype.update = function() {
    let val = this.vm
    let arr = this.exp.split('.')
    arr.forEach( k => {
        val = val[k]
    })
    this.fn(val)
}

yaogengzhu avatar Feb 02 '20 13:02 yaogengzhu

数据双向绑定

function Lesson(options= {}) {
    this.$options = options
    var data = this._data = this.$options.data
    observe(data)
    for(let key in data) {
        Object.defineProperty(this, key, {
            enumerable: true,
            get() {
                return this._data[key]
            },
            set(newVal) {
                if (this._data[key] === newVal) return
                this._data[key] = newVal
            }
        })
    }
    //这里做编译
    new Compile(options.el, this)
}

function observe(data) {
    if (typeof data !== 'object' ) return 
    return new Observe(data)
}   

function Observe(data) {
    // 处理具体的Objcet.defineProperty的逻辑
    let dep = new Dep()
    for (let key in data) {
        let val = data[key]
        observe(val)
        Object.defineProperty(data, key, {
            enumerable: true,
            get() {
                Dep.target && dep.addSubs(Dep.target)
                return val
            },
            set(newVal) {
                if (val === newVal) return
                val = newVal
                observe(newVal)
                dep.notify()
            }
        })
    }
}

function Compile(el, vm) {
    vm.$el = document.querySelector(el)
    let fragement = document.createDocumentFragment()
    while( child = vm.$el.firstChild) {
        fragement.appendChild(child)
    }
    // 处理fargement
    // console.log(Array.from(fragement.firstChild))
    
    // let arr = Array.from(fragement.firstChild)
    replace(fragement)
    function replace(fragement) {
        Array.from(fragement.childNodes).forEach( node => {
            let text = node.textContent
            let reg = /\{\{(.*)\}\}/
            // console.log(node.nodeType)
            if (node.nodeType === 3 && reg.test(text)) {
                // console.log(RegExp.$1)
                let arr = RegExp.$1.split('.')
                let val = vm
                arr.forEach( k => {
                    val = val[k]
                })
                new Watcher(vm, RegExp.$1,function(newVal) {
                    node.textContent = text.replace(reg, newVal)
                })  
                node.textContent = text.replace(reg, val)
            }
            if (node.nodeType === 1) {
                // 表示该元素是元素节点
                // console.log(node.attributes)
                let nodeAttrs = node.attributes
                Array.from(nodeAttrs).forEach( attr => {
                    // console.log(attr)
                    let name = attr.name
                    let exp = attr.value
                    if (name.indexOf('v-') === 0) {
                        node.value = vm[exp]
                    }
                    new Watcher(vm, exp, function(newVal) {
                        node.value = newVal
                    })

                    node.addEventListener('input', function(e) {
                        let value = e.target.value
                        vm[exp] = value
                    })
                })

            }

            if (node.childNodes) {
                replace(node)
            }
        })
    }
    vm.$el.appendChild(fragement)
}

function Dep() {
    this.subs = []
}
Dep.prototype.addSubs = function(fn) {
    this.subs.push(fn)
}
Dep.prototype.notify = function() {
    // console.log(this.subs)
    this.subs.forEach( fn => {
        // console.log()
        fn.update()
    } )
}

function Watcher(vm, exp, fn) {
    this.vm = vm
    this.exp = exp
    this.fn = fn
    Dep.target = this
    let val = vm
    let arr = exp.split('.')
    arr.forEach( k => {
        val = val[k]
    })  
    Dep.target = null  
}

Watcher.prototype.update = function() {
    let val = this.vm
    let arr = this.exp.split('.')
    arr.forEach( k => {
        val = val[k]
    })
    this.fn(val)
}

其中关键代码

            if (node.nodeType === 1) {
                // 表示该元素是元素节点
                // console.log(node.attributes)
                let nodeAttrs = node.attributes
                Array.from(nodeAttrs).forEach( attr => {
                    // console.log(attr)
                    let name = attr.name
                    let exp = attr.value
                    if (name.indexOf('v-') === 0) {
                        node.value = vm[exp]
                    }
                    new Watcher(vm, exp, function(newVal) {
                        node.value = newVal
                    })

                    node.addEventListener('input', function(e) {
                        let value = e.target.value
                        vm[exp] = value
                    })
                })

            }

yaogengzhu avatar Feb 07 '20 12:02 yaogengzhu