用ES6的class模仿Vue写一个双向绑定的例子

本篇文章主要介绍了用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的选择值,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_-]+) *}}/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)

数据变化之后更新视图

 
 
 
  

您输入的是:{{text1}}+{{text2}}+{{text3}}

   Volvo  Saab    Volvo  Saab  

您选择了:{{select}}

let app = new TinyVue({ el: '#app', data: { text1: 123, text2: 456, text3: '文本框', select: 'saab' }, methods: { add() { this.text1 ++ this.text2 ++ } } })

登录后复制

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}))  }) }}

登录后复制

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Vue2.0 多 Tab切换组件的封装介绍

关于Vue表单demo v-model双向绑定的问题

以上就是用ES6的class模仿Vue写一个双向绑定的例子的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2747708.html

(0)
上一篇 2025年3月8日 04:26:39
下一篇 2025年3月6日 12:04:50

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • ES6 Class 继承与 super的介绍

    这篇文章主要介绍了关于es6 class 继承与 super的介绍,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 Class 继承与 super class 可以 extends 自另一个 class。这是一个不错的语法,技…

    2025年3月8日 编程技术
    200
  • js中如何取代if-else和switch

    这篇文章主要介绍了关于js中如何取代if-else和switch,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 1.前言 相信很多人有这样的经历,在项目比较忙的时候,都是先考虑实现,用当时以为最好的方式先实现方案,在项目不忙…

    2025年3月8日 编程技术
    200
  • 遍历器Iterator访问数据集合的统一接口的方法

    这篇文章给大家介绍的内容是关于遍历器iterator访问数据集合的统一接口的方法,有着一定的参考价值,有需要的朋友可以参考一下。 导语 遍历器Iterator是ES6为访问数据集合提供的统一接口。任何内部部署了遍历器接口的数据集合,对于用户…

    编程技术 2025年3月8日
    200
  • ES6新增语法有哪些?快速学习

    let关键字     ES5中用var声明变量,而在ES6中新增了let关键字来声明变量。那么为什么要新增let呢?   首先,我们来看一下var关键字。 function foo() {var sum = 0;for (var i = 0…

    2025年3月8日
    200
  • 什么是模块?深刻理解ES6模块

    1.模块 1.1 什么是模块?什么是模块化? 玩过fps游戏的朋友应该知道,一把装配完整的m4步枪,一般是枪身+消音器+倍镜+握把+枪托。 如果把M4步枪看成是一个页面的话,那么我们可以做如下类比枪身 -> 消音器 -> 倍镜 …

    2025年3月8日
    200
  • 总结js中Array的方法的用法

    本篇文章给大家带来的内容是关于总结js中array的方法的用法,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 JS Array的一些方法在实际中很常用,这里整理记录下来,一是为了常常回顾,二也是方便大家 Map map()…

    编程技术 2025年3月8日
    200
  • 可以把js中的对象转成url参数的函数介绍(代码实例)

    本篇文章给大家带来的内容是关于可以把js中的对象转成url参数的函数介绍(代码实例)),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 这个函数呢是自己在写基于Vue+ElementUI管理后台时用到的,,下面列出来两种使用…

    编程技术 2025年3月8日
    200
  • ES6中Set和Map,Map与其它数据结构之间转换的解析

    本篇文章给大家带来的内容是关于es6中set和map,map与其它数据结构之间转换的解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 ES6 的 Set: ES6 提供了新的数据结构──Set。它类似于数组,但是成员的值…

    编程技术 2025年3月8日
    200
  • js中的类向传统类模式转变的构造函数详解(附示例)

    本篇文章给大家带来的内容是关于js中的类向传统类模式转变的构造函数详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 前言 JS基于原型的‘类’,一直被转行前端的码僚们大呼惊奇,但接近传统模式使用class关键字…

    编程技术 2025年3月8日
    200
  • 浅析es6中Promise(附实例)

    本篇文章给大家带来的内容是关于浅析es6中promise(附实例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 Promise 的基本使用可以看阮一峰老师的 《ECMAScript 6 入门》。 我们来聊点其他的。 回调…

    编程技术 2025年3月8日
    200

发表回复

登录后才能评论