成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

用ES6的class模仿Vue寫(xiě)一個(gè)雙向綁定

waltr / 553人閱讀

摘要:原文地址的博客點(diǎn)擊在線嘗試一下最終效果如下構(gòu)造器構(gòu)造一個(gè)對(duì)象,包含基本的,,初始化編譯器用于解析綁定到輸入框和下拉框的和元素的點(diǎn)擊事件。

原文地址:Bougie的博客

點(diǎn)擊在線嘗試一下

最終效果如下:

構(gòu)造器(constructor)

構(gòu)造一個(gè)TinyVue對(duì)象,包含基本的el,data,methods

class TinyVue{
    constructor({el, data, methods}){
        this.$data = data
        this.$el = document.querySelector(el)
        this.$methods = methods
        // 初始化
        this._compile()
        this._updater()
        this._watcher()
    }
}
編譯器(compile)

用于解析綁定到輸入框和下拉框的v-model和元素的點(diǎn)擊事件@click。
先創(chuàng)建一個(gè)函數(shù)用來(lái)載入事件:

// el為元素tagName,attr為元素屬性(v-model,@click)
_initEvents(el, attr, callBack) {
    this.$el.querySelectorAll(el).forEach(i => {
        if(i.hasAttribute(attr)) {
            let key = i.getAttribute(attr)
            callBack(i, key)
        }
    })
}
載入輸入框事件
this._initEvents("input, textarea", "v-model", (i, key) => {
    i.addEventListener("input", () => {
        Object.assign(this.$data, {[key]: i.value})
    })
})
載入選擇框事件
this._initEvents("select", "v-model", (i, key) => {
    i.addEventListener("change", () => Object.assign(this.$data, {[key]: i.options[i.options.selectedIndex].value}))
})
載入點(diǎn)擊事件

點(diǎn)擊事件對(duì)應(yīng)的是methods中的事件

this._initEvents("*", "@click", (i, key) => {
    i.addEventListener("click", () => this.$methods[key].bind(this.$data)())
})
視圖更新器(updater)

同理先創(chuàng)建公共函數(shù)來(lái)處理不同元素中的視圖,包括input、textarea的value,select的選擇值,div的innerHTML

_initView(el, attr, callBack) {
    this.$el.querySelectorAll(el, attr, callBack).forEach(i => {
        if(i.hasAttribute(attr)) {
            let key = i.getAttribute(attr),
                data = this.$data[key]
            callBack(i, key, data)
        }
    })
}
更新輸入框視圖
this._initView("input, textarea", "v-model", (i, key, data) => {
    i.value = data
})
更新選擇框視圖
this._initView("select", "v-model", (i, key, data) => {
    i.querySelectorAll("option").forEach(v => {
        if(v.value == data) v.setAttribute("selected", true)
        else v.removeAttribute("selected")
    })
})
更新innerHTML

這里實(shí)現(xiàn)方法有點(diǎn)low,僅想到正則替換{{text}}

let regExpInner = /{{ *([w_-]+) *}}/g
this.$el.querySelectorAll("*").forEach(i => {
    let replaceList = i.innerHTML.match(regExpInner) || (i.hasAttribute("vueID") && i.getAttribute("vueID").match(regExpInner))
    if(replaceList) {
        if(!i.hasAttribute("vueID")) {
            i.setAttribute("vueID", i.innerHTML)
        }
        i.innerHTML = i.getAttribute("vueID")
        replaceList.forEach(v => {
            let key = v.slice(2, v.length - 2)
            i.innerHTML = i.innerHTML.replace(v, this.$data[key])
        })
    }
})
監(jiān)聽(tīng)器(watcher)

數(shù)據(jù)變化之后更新視圖

_watcher(data = this.$data) {
    let that = this
    Object.keys(data).forEach(i => {
        let value = data[i]
        Object.defineProperty(data, i, {
            enumerable: true,
            configurable: true,
            get: function () {
                return value;
            },
            set: function (newVal) {
                if (value !== newVal) {
                    value = newVal;
                    that._updater()
                }
            }
        })
    })
}
使用



您輸入的是:{{text1}}+{{text2}}+{{text3}}

您選擇了:{{select}}

TinyVue全部代碼
class TinyVue{
    constructor({el, data, methods}){
        this.$data = data
        this.$el = document.querySelector(el)
        this.$methods = methods
        this._compile()
        this._updater()
        this._watcher()
    }
    _watcher(data = this.$data) {
        let that = this
        Object.keys(data).forEach(i => {
            let value = data[i]
            Object.defineProperty(data, i, {
                enumerable: true,
                configurable: true,
                get: function () {
                    return value;
                },
                set: function (newVal) {
                    if (value !== newVal) {
                        value = newVal;
                        that._updater()
                    }
                }
            })
        })
    }
    _initEvents(el, attr, callBack) {
        this.$el.querySelectorAll(el).forEach(i => {
            if(i.hasAttribute(attr)) {
                let key = i.getAttribute(attr)
                callBack(i, key)
            }
        })
    }
    _initView(el, attr, callBack) {
        this.$el.querySelectorAll(el, attr, callBack).forEach(i => {
            if(i.hasAttribute(attr)) {
                let key = i.getAttribute(attr),
                    data = this.$data[key]
                callBack(i, key, data)
            }
        })
    }
    _updater() {
        this._initView("input, textarea", "v-model", (i, key, data) => {
            i.value = data
        })
        this._initView("select", "v-model", (i, key, data) => {
            i.querySelectorAll("option").forEach(v => {
                if(v.value == data) v.setAttribute("selected", true)
                else v.removeAttribute("selected")
            })
        })
        let regExpInner = /{{ *([w_-]+) *}}/g
        this.$el.querySelectorAll("*").forEach(i => {
            let replaceList = i.innerHTML.match(regExpInner) || (i.hasAttribute("vueID") && i.getAttribute("vueID").match(regExpInner))
            if(replaceList) {
                if(!i.hasAttribute("vueID")) {
                    i.setAttribute("vueID", i.innerHTML)
                }
                i.innerHTML = i.getAttribute("vueID")
                replaceList.forEach(v => {
                    let key = v.slice(2, v.length - 2)
                    i.innerHTML = i.innerHTML.replace(v, this.$data[key])
                })
            }
        })
    }
    _compile() {
        this._initEvents("*", "@click", (i, key) => {
            i.addEventListener("click", () => this.$methods[key].bind(this.$data)())
        })
        this._initEvents("input, textarea", "v-model", (i, key) => {
            i.addEventListener("input", () => {
                Object.assign(this.$data, {[key]: i.value})
            })
        })
        this._initEvents("select", "v-model", (i, key) => {
            i.addEventListener("change", () => Object.assign(this.$data, {[key]: i.options[i.options.selectedIndex].value}))
        })
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94440.html

相關(guān)文章

  • vue for contacts項(xiàng)目總結(jié)

    摘要:用來(lái)主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)??偨Y(jié)做完這個(gè)項(xiàng)目,其中的過(guò)程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過(guò)最后能完成還是挺開(kāi)心的,終于有了一個(gè)從到的項(xiàng)目過(guò)程。雖然只是一個(gè)小小的練手項(xiàng)目,不過(guò)對(duì)于目前的我,感覺(jué)還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...

    tulayang 評(píng)論0 收藏0
  • vue for contacts項(xiàng)目總結(jié)

    摘要:用來(lái)主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)??偨Y(jié)做完這個(gè)項(xiàng)目,其中的過(guò)程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過(guò)最后能完成還是挺開(kāi)心的,終于有了一個(gè)從到的項(xiàng)目過(guò)程。雖然只是一個(gè)小小的練手項(xiàng)目,不過(guò)對(duì)于目前的我,感覺(jué)還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...

    ralap 評(píng)論0 收藏0
  • vue for contacts項(xiàng)目總結(jié)

    摘要:用來(lái)主要前臺(tái)的請(qǐng)求,并處理返回相關(guān)的數(shù)據(jù),做后臺(tái)服務(wù)??偨Y(jié)做完這個(gè)項(xiàng)目,其中的過(guò)程還是挺艱辛的,畢竟都是邊學(xué)邊做,不過(guò)最后能完成還是挺開(kāi)心的,終于有了一個(gè)從到的項(xiàng)目過(guò)程。雖然只是一個(gè)小小的練手項(xiàng)目,不過(guò)對(duì)于目前的我,感覺(jué)還是不錯(cuò)的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...

    ARGUS 評(píng)論0 收藏0
  • 前端面試題總結(jié)——VUE(持續(xù)更新中)

    摘要:前端面試題總結(jié)持續(xù)更新中是哪個(gè)組件的屬性模塊的組件。都提供合理的鉤子函數(shù),可以讓開(kāi)發(fā)者定制化地去處理需求。 前端面試題總結(jié)——VUE(持續(xù)更新中) 1.active-class是哪個(gè)組件的屬性? vue-router模塊的router-link組件。 2.嵌套路由怎么定義? 在 VueRouter 的參數(shù)中使用 children 配置,這樣就可以很好的實(shí)現(xiàn)路由嵌套。 //引入兩個(gè)組件 ...

    SimonMa 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<