怎么使用ES6的class写一个双向绑定(class,es6,编程语言)

时间:2024-05-04 07:49:23 作者 : 石家庄SEO 分类 : 编程语言
  • TAG :

最终效果如下:

怎么使用ES6的class写一个双向绑定

构造器(constructor)

构造一个TinyVue对象,包含基本的el,data,methods

classTinyVue{constructor({el,data,methods}){this.$data=datathis.$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)){letkey=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)){letkey=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)elsev.removeAttribute('selected')})})

更新innerHTML

这里实现方法有点low,仅想到正则替换{{text}}

letregExpInner=/\{{*([\w_\-]+)*\}}/gthis.$el.querySelectorAll("*").forEach(i=>{letreplaceList=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=>{letkey=v.slice(2,v.length-2)i.innerHTML=i.innerHTML.replace(v,this.$data[key])})}})

监听器(watcher)

数据变化之后更新视图

<divid="app"><inputtype="text"v-model="text1"><br><inputtype="text"v-model="text2"><br><textareatype="text"v-model="text3"></textarea><br><button@click="add">加一</button><h2>您输入的是:{{text1}}+{{text2}}+{{text3}}</h2><selectv-model="select"><optionvalue="volvo">Volvo</option><optionvalue="saab">Saab</option></select><selectv-model="select"><optionvalue="volvo">Volvo</option><optionvalue="saab">Saab</option></select><h2>您选择了:{{select}}</h2></div><scriptsrc="./TinyVue.js"></script><script>letapp=newTinyVue({el:'#app',data:{text1:123,text2:456,text3:'文本框',select:'saab'},methods:{add(){this.text1++this.text2++}}})</script>

TinyVue全部代码

classTinyVue{constructor({el,data,methods}){this.$data=datathis.$el=document.querySelector(el)this.$methods=methodsthis._compile()this._updater()this._watcher()}_watcher(data=this.$data){letthat=thisObject.keys(data).forEach(i=>{letvalue=data[i]Object.defineProperty(data,i,{enumerable:true,configurable:true,get:function(){returnvalue;},set:function(newVal){if(value!==newVal){value=newVal;that._updater()}}})})}_initEvents(el,attr,callBack){this.$el.querySelectorAll(el).forEach(i=>{if(i.hasAttribute(attr)){letkey=i.getAttribute(attr)callBack(i,key)}})}_initView(el,attr,callBack){this.$el.querySelectorAll(el,attr,callBack).forEach(i=>{if(i.hasAttribute(attr)){letkey=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)elsev.removeAttribute('selected')})})letregExpInner=/\{{*([\w_\-]+)*\}}/gthis.$el.querySelectorAll("*").forEach(i=>{letreplaceList=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=>{letkey=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}))})}}
 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:怎么使用ES6的class写一个双向绑定的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:ES6中Proxy与Reflect怎么实现重载下一篇:

26 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18