怎么使用ES6的class写一个双向绑定
导读:本文共3291.5字符,通常情况下阅读需要11分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 最终效果如下:构造器(constructor)构造一个TinyVue对象,包含基本的el,data,methodsclassTinyVue{constructor({el,data,methods}){this.$data=datathis.$el=document.querySelector(el)this.$methods=methods//初始化... ...
音频解说
目录
(为您整理了一些要点),点击可以直达。最终效果如下:
构造器(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写一个双向绑定的详细内容,希望对您有所帮助,信息来源于网络。