您好,欢迎访问一九零五行业门户网

ES6仿Vue实现双向绑定功能

这次给大家带来es6仿vue实现双向绑定功能,es6仿vue实现双向绑定功能的注意事项有哪些,下面就是实战案例,一起来看一下。
最终效果如下:
构造器(constructor)
构造一个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的选择值,p的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)
数据变化之后更新视图
<p 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> </p> <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}))   })  } }
相信看了本文案例你已经掌握了方法,更多精彩请关注其它相关文章!
推荐阅读:
jquery$. 和 $().使用详解
vue中v-cloak在刷新与加载时闪烁如何处理
以上就是es6仿vue实现双向绑定功能的详细内容。
其它类似信息

推荐信息