怎么使用ES6的class模仿Vue写一个双向绑定
这篇文章主要介绍“怎么使用ES6的class模仿Vue写一个双向绑定”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么使用ES6的class模仿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的选择值,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)
数据变化之后更新视图
您输入的是:{{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})) }) } }
关于“怎么使用ES6的class模仿Vue写一个双向绑定”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注创新互联行业资讯频道,小编每天都会为大家更新不同的知识点。
本文名称:怎么使用ES6的class模仿Vue写一个双向绑定
新闻来源:http://hbruida.cn/article/jjdopd.html