美文网首页
vue双向绑定原理

vue双向绑定原理

作者: 阿水日记 | 来源:发表于2019-06-15 19:20 被阅读0次
<script>
        //发布者
        class Vue {
            constructor(options) {
                this.options = options
                this.$data = options.data
                this.$el = document.querySelector(options.el)
                this._directives = {} //存放订阅了对应数据的(什么东西)
                //{myText:[订阅者1,订阅者2],mybox:[订阅者1]}
                this.Observer(this.$data)
                this.Compile(this.$el)
            }
            //劫持数据
            Observer(data) {
                //更新视图
                for (let key in data) {
                    this._directives[key] = []
                    let _this = this._directives[key]
                    let val = data[key] //当前值
                    Object.defineProperty(this.$data, key, {
                        get: function () {
                            return val
                        },
                        set: function (newVal) {
                            if (newVal !== val) {
                                val = newVal
                                //[订阅者1,订阅者2]
                                _this.forEach(watch => {
                                    watch.update()
                                });
                            }
                        }
                    })
                }


            }
            //解析指令
            Compile(el) {
                let nodes = el.children //获取根节点下的子元素
                for (let i = 0; i < nodes.length; i++) {
                    let node = nodes[i] //当前元素
                    if (node.children.length) {//如果还有子节点
                        this.Compile(node)
                    }
                    if (node.hasAttribute("v-text")) { //查找v-text
                        let attrVal = node.getAttribute("v-text")
                        this._directives[attrVal].push(new Watch(node, attrVal, this, 'innerHTML'))
                    }

                    if (node.hasAttribute("v-model")) { //查找vmodel
                        let attrVal = node.getAttribute("v-model")
                        this._directives[attrVal].push(new Watch(node, attrVal, this, 'value'))
                        let _this = this
                        node.addEventListener("input", (function () {
                            return function () {
                                //更新视图到模型
                                _this.$data[attrVal] = node.value
                            }
                        })())
                    }
                }
            }
        }
        //订阅者
        class Watch {
            constructor(el, vm, mySelf, attr) {
                this.el = el
                this.vm = vm
                this.mySelf = mySelf
                this.attr = attr
                this.update()
            }
            update() {
                this.el[this.attr] = this.mySelf.$data[this.vm]
                //div对象[innerHTML]=vue对象.data["myText"]   
            }
        }
    </script>

<body>
    <div id="app">
        <h1>数据响应式</h1>
        <div>
            <div v-text="myText"></div>
            <input type="text" v-model="myText">
        </div>
    </div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            myText: '大吉大利,今晚吃鸡'
        }
    })
</script>

相关文章

网友评论

      本文标题:vue双向绑定原理

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