国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

用ES6的class模仿Vue寫一個雙向綁定的示例代碼

2019-11-19 13:59:26
字體:
供稿:網(wǎng)友

本文介紹了用ES6的class模仿Vue寫一個雙向綁定的示例代碼,分享給大家,具體如下:

最終效果如下:

構(gòu)造器(constructor)

構(gòu)造一個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。

先創(chuàng)建一個函數(shù)用來載入事件:

// 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}))})

載入點擊事件

點擊事件對應(yīng)的是methods中的事件

this._initEvents('*', '@click', (i, key) => { i.addEventListener('click', () => this.$methods[key].bind(this.$data)())})

視圖更新器(updater)

同理先創(chuàng)建公共函數(shù)來處理不同元素中的視圖,包括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

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

let regExpInner = //{{ *([/w_/-]+) */}}/gthis.$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)聽器(watcher)

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

<div id="app"> <input type="text" v-model="text1"><br> <input type="text" v-model="text2"><br> <textarea type="text" v-model="text3"></textarea><br> <button @click="add">加一</button> <h1>您輸入的是:{{text1}}+{{text2}}+{{text3}}</h1> <select v-model="select">  <option value="volvo">Volvo</option>  <option value="saab">Saab</option> </select> <select v-model="select">  <option value="volvo">Volvo</option>  <option value="saab">Saab</option> </select> <h1>您選擇了:{{select}}</h1></div><script src="./TinyVue.js"></script><script> let app = new TinyVue({  el: '#app',  data: {   text1: 123,   text2: 456,   text3: '文本框',   select: 'saab'  },  methods: {   add() {    this.text1 ++    this.text2 ++   }  } })</script>

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}))  }) }}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 邯郸市| 吉首市| 长汀县| 临颍县| 淮阳县| 辽中县| 克什克腾旗| 靖江市| 天峨县| 盐池县| 海城市| 都安| 井陉县| 全南县| 太湖县| 抚顺县| 石棉县| 汤阴县| 海城市| 新郑市| 苗栗县| 潜山县| 界首市| 聂拉木县| 莱阳市| 新丰县| 大渡口区| 攀枝花市| 汾阳市| 江阴市| 禹州市| 招远市| 保定市| 东乡族自治县| 富顺县| 汽车| 庆元县| 瓮安县| 德令哈市| 东乌珠穆沁旗| 遂川县|