摘要:原文地址的博客点击在线尝试一下最终效果如下构造器构造一个对象,包含基本的,,初始化编译器用于解析绑定到输入框和下拉框的和元素的点击事件。
原文地址:Bougie的博客
点击在线尝试一下
最终效果如下:
构造一个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)
数据变化之后更新视图
_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() } } }) }) }使用
TinyVue全部代码
您输入的是:{{text1}}+{{text2}}+{{text3}}
您选择了:{{select}}
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})) }) } }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/94440.html
摘要:用来主要前台的请求,并处理返回相关的数据,做后台服务。总结做完这个项目,其中的过程还是挺艰辛的,毕竟都是边学边做,不过最后能完成还是挺开心的,终于有了一个从到的项目过程。虽然只是一个小小的练手项目,不过对于目前的我,感觉还是不错的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用来主要前台的请求,并处理返回相关的数据,做后台服务。总结做完这个项目,其中的过程还是挺艰辛的,毕竟都是边学边做,不过最后能完成还是挺开心的,终于有了一个从到的项目过程。虽然只是一个小小的练手项目,不过对于目前的我,感觉还是不错的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:用来主要前台的请求,并处理返回相关的数据,做后台服务。总结做完这个项目,其中的过程还是挺艰辛的,毕竟都是边学边做,不过最后能完成还是挺开心的,终于有了一个从到的项目过程。虽然只是一个小小的练手项目,不过对于目前的我,感觉还是不错的。 showImg(https://oc1gyfe6q.qnssl.com/17-3-30/43434844-file_1490879850754_14751...
摘要:前端面试题总结持续更新中是哪个组件的属性模块的组件。都提供合理的钩子函数,可以让开发者定制化地去处理需求。 前端面试题总结——VUE(持续更新中) 1.active-class是哪个组件的属性? vue-router模块的router-link组件。 2.嵌套路由怎么定义? 在 VueRouter 的参数中使用 children 配置,这样就可以很好的实现路由嵌套。 //引入两个组件 ...
阅读 1692·2021-11-22 15:33
阅读 1954·2021-10-08 10:04
阅读 3521·2021-08-27 13:12
阅读 3367·2019-08-30 13:06
阅读 1440·2019-08-29 16:43
阅读 1362·2019-08-29 16:40
阅读 694·2019-08-29 16:15
阅读 2726·2019-08-29 14:13