摘要:原文地址的博客點擊在線嘗試一下最終效果如下構造器構造一個對象,包含基本的,,初始化編譯器用于解析綁定到輸入框和下拉框的和元素的點擊事件。
原文地址:Bougie的博客
點擊在線嘗試一下
最終效果如下:
構造一個TinyVue對象,包含基本的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和元素的點擊事件@click。
先創建一個函數用來載入事件:
// 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})) })載入點擊事件
點擊事件對應的是methods中的事件
this._initEvents("*", "@click", (i, key) => { i.addEventListener("click", () => this.$methods[key].bind(this.$data)()) })視圖更新器(updater)
同理先創建公共函數來處理不同元素中的視圖,包括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
這里實現方法有點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]) }) } })監聽器(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() } } }) }) }使用
TinyVue全部代碼
您輸入的是:{{text1}}+{{text2}}+{{text3}}
您選擇了:{{select}}
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})) }) } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94440.html
摘要:用來主要前臺的請求,并處理返回相關的數據,做后臺服務。總結做完這個項目,其中的過程還是挺艱辛的,畢竟都是邊學邊做,不過最后能完成還是挺開心的,終于有了一個從到的項目過程。雖然只是一個小小的練手項目,不過對于目前的我,感覺還是不錯的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用來主要前臺的請求,并處理返回相關的數據,做后臺服務。總結做完這個項目,其中的過程還是挺艱辛的,畢竟都是邊學邊做,不過最后能完成還是挺開心的,終于有了一個從到的項目過程。雖然只是一個小小的練手項目,不過對于目前的我,感覺還是不錯的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用來主要前臺的請求,并處理返回相關的數據,做后臺服務。總結做完這個項目,其中的過程還是挺艱辛的,畢竟都是邊學邊做,不過最后能完成還是挺開心的,終于有了一個從到的項目過程。雖然只是一個小小的練手項目,不過對于目前的我,感覺還是不錯的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:前端面試題總結持續更新中是哪個組件的屬性模塊的組件。都提供合理的鉤子函數,可以讓開發者定制化地去處理需求。 前端面試題總結——VUE(持續更新中) 1.active-class是哪個組件的屬性? vue-router模塊的router-link組件。 2.嵌套路由怎么定義? 在 VueRouter 的參數中使用 children 配置,這樣就可以很好的實現路由嵌套。 //引入兩個組件 ...
閱讀 1714·2021-11-22 15:33
閱讀 2085·2021-10-08 10:04
閱讀 3543·2021-08-27 13:12
閱讀 3418·2019-08-30 13:06
閱讀 1467·2019-08-29 16:43
閱讀 1391·2019-08-29 16:40
閱讀 785·2019-08-29 16:15
閱讀 2745·2019-08-29 14:13