vue雙向綁定原理

<script>
        //發(fā)布者
        class Vue {
            constructor(options) {
                this.options = options
                this.$data = options.data
                this.$el = document.querySelector(options.el)
                this._directives = {} //存放訂閱了對(duì)應(yīng)數(shù)據(jù)的(什么東西)
                //{myText:[訂閱者1,訂閱者2],mybox:[訂閱者1]}
                this.Observer(this.$data)
                this.Compile(this.$el)
            }
            //劫持?jǐn)?shù)據(jù)
            Observer(data) {
                //更新視圖
                for (let key in data) {
                    this._directives[key] = []
                    let _this = this._directives[key]
                    let val = data[key] //當(dāng)前值
                    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 //獲取根節(jié)點(diǎn)下的子元素
                for (let i = 0; i < nodes.length; i++) {
                    let node = nodes[i] //當(dāng)前元素
                    if (node.children.length) {//如果還有子節(jié)點(diǎn)
                        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對(duì)象[innerHTML]=vue對(duì)象.data["myText"]   
            }
        }
    </script>

<body>
    <div id="app">
        <h1>數(shù)據(jù)響應(yīng)式</h1>
        <div>
            <div v-text="myText"></div>
            <input type="text" v-model="myText">
        </div>
    </div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            myText: '大吉大利,今晚吃雞'
        }
    })
</script>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容