文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2023-06-17 09:43

关注

今天小编给大家分享一下怎么使用ES6的class写一个双向绑定的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

最终效果如下:

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

构造器(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_\-]+) *\}}/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])  }) }})

监听器(watcher)

数据变化之后更新视图

<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> <h2>您输入的是:{{text1}}+{{text2}}+{{text3}}</h2> <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> <h2>您选择了:{{select}}</h2></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}))  }) }}

以上就是“怎么使用ES6的class写一个双向绑定”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯