基于 getter 和 setter 撸一个简易的MVVM
Angular 和 Vue
在对Angular的学习中,了解到AngularJS 的两个主要缺点:
- 对于每一次界面时间,Ajax 或者 timeout,都会进行一个脏检查,而每一次脏检查又会在内部循环检查,当界面绑定的model 很多,就会造成严重的性能问题 。
- Angular 混乱的模块,并不能起到命名空间的作用,因而在大项目中组织模块又是一件头疼的事。
但是 Angular 开发中小型的应用是很棒的,也是将 MVC 引入到前端的开始。定一个目标,两年时间理解 《Build Your Own AngularJS》。
Vue 抛弃了Angular 中脏检查的方式,而使用 Javascript 中变量的setter 属性来截获数据变化,更加巧妙和机智。
在 MVVM 时代,浏览器自身属性变得更加重要起来。getter 和 setter 曾被认为是一个无太大用处的一个属性。
为了较为深入的理解 Vue, 自己撸了一个简易版 MVVM 。 先看效果吧 。
<input type="text" v-model="hello" value="">
<div id="template">
{{hello}}
</div>
<div class="template">
{{bind}}
</div>
<script src="app.js"></script>
var vue = new Vue({
ele: '#template',
});
var vue1 = new Vue({
ele: '.template',
data: {
bind: 'hey i am a vue lover'
}
})

开撸开撸
若有关于 getter 和 setter 问题 ,请先移步 MDN 。
申明Vue 对象
function Vue(option) {
this.init(option);
}
初始化
Vue.prototype.init = function(option) {
this._data = option.data || {};
this._method = option.method || {};
this.bingdings = {};
this.elements = typeof option.ele === "string" ? document.querySelectorAll(option.ele) : option.ele;
this.bind();
this.observe();
this.react();
this.initMvvM();
}
将界面上的模型数据绑定到后台
Vue.prototype.bind = function() {
for (var i = 0, length = this.elements.length; i < length; i++) {
var ele = this.elements[i],
html = ele.innerHTML,
spans, span, dataAttr;
html = html.replace(/\{\{(.*?)\}\}/g, function(a, b) {
var span = '<span v-data="' + b + '"></span>';
return span;
})
ele.innerHTML = html;
spans = ele.querySelectorAll('[v-data]');
for (var j = 0, l = spans.length; j < l; j++) {
span = spans[j];
dataAttr = span.getAttribute('v-data');
if (!this.bingdings[dataAttr]) {
this.bingdings[dataAttr] = { value: this._data[dataAttr] || '', ele: [] };
}
this.bingdings[dataAttr].ele.push(span);
span.innerHTML = this.bingdings[dataAttr].value;
span.removeAttribute('v-data');
}
}
}
// 核心部分,使用 setter 观测 _data
Vue.prototype.observe = function() {
var self = this,
eles;
for (var key in self.bingdings) {
Object.defineProperty(self._data, key, {
get: function() {
return self.bingdings[key].value;
},
set: function(newVal) {
if (newVal !== self.bingdings[key].value) {
self.bingdings[key].value = newVal;
eles = self.bingdings[key].ele;
for (var i = 0, l = eles.length; i < l; i++) {
eles[i].innerHTML = newVal;
}
}
}
})
}
}
到这里,_data_ 的赋值已经可以引起界面上dom 的变化。也就是说完成了 model 到view 的数据绑定和响应。
现在来完成 dom 到 view 的事件响应。
Vue.prototype.initMvvM = function() {
var self = this;
var models = document.querySelectorAll('[v-model]'),
model, dataModel;
for (var i = 0, l = models.length; i < l; i++) {
model = models[i];
dataModel = model.getAttribute('v-model');
self._data[dataModel] = model.value;
}
}
// 事件响应
Vue.prototype.react = function() {
var self = this;
var models = document.querySelectorAll('[v-model]'),
model, dataModel;
for (var i = 0, l = models.length; i < l; i++) {
model = models[i];
model.addEventListener('change', function(e) {
dataModel = this.getAttribute('v-model');
self._data[dataModel] = this.value;
})
model.addEventListener('keyup', function(e) {
dataModel = this.getAttribute('v-model');
self._data[dataModel] = this.value;
})
}
}
最后,更新init 函数。
Vue.prototype.init = function(option) {
this._data = option.data || {};
this._method = option.method;
this.bingdings = {};
this.elements = typeof option.ele === "string" ? document.querySelectorAll(option.ele) : option.ele;
this.bind();
this.observe();
this.react();
this.initMvvM();
}
总结
大功告成。
但是相比与真正的Vue还是差了很多,比如 这里的数据绑定仅支持基本类型,函数绑定也没有完成。在Vue 中,每一个监控的属性都会设置依赖,从而陷入避免和 Angular 中一样的循环检查。
另外,在Vue中,数据模版并不是这样使用插入一个span,而是创建一个 文本节点,然后append 到当前父元素上。
这只是一个简易版的,把所有的部分都放在Vue上,非常不合适。 后面会进行重构,把数据监控使用订阅和发布模式封装。
在这之前,需要进行模块化和依赖注入,所以,接下来要完成一个简易的requirejs,会提供三个api ,define, require 和 use。
代码托管到了 github(但是今天的网速不好,改天补充.),
如有错误,希望不吝赐教。
如果您有合适的前端工资机会,也期待您的邮件。
基于 getter 和 setter 撸一个简易的MVVM的更多相关文章
- 基于Win32 SDK实现的一个简易线程池
利用C++实现了一个简易的线程池模型(基于Win32 SDK),方便使用多线程处理任务.共包含Thread.h.Thread.cpp.ThreadPool.h.ThreadPool.cpp四个源文件. ...
- 手把手教你撸一个简易的 webpack
背景 随着前端复杂度的不断提升,诞生出很多打包工具,比如最先的grunt,gulp.到后来的webpack和Parcel.但是目前很多脚手架工具,比如vue-cli已经帮我们集成了一些构建工具的使用. ...
- 曹工说Tomcat2:自己撸一个简易Tomcat Digester
一.前言 框架代码其实也没那么难,大家不要看着源码就害怕,现在去看 Tomcat 3.0的代码,保证还是看得懂一半,照着撸一遍基本上很多问题都能搞定了.这次我们就模拟 Tomcat 中的 Digest ...
- 半天撸一个简易版mybatis
为什么需要持久层框架? 首先我们先看看使用原生jdbc存在的问题? public static void main(String[] args) { Connection connection = n ...
- 撸一个简单的MVVM例子
我个人以为mvvm框架里面最重要的一点就是VM这部分,它要与Model层建立联系,将Model层转换成可以被View层识别的数据结构:其次也要同View建立联系,将数据及时更新到View层上,并且响应 ...
- C#基于Mongo的官方驱动手撸一个Super简易版MongoDB-ORM框架
C#基于Mongo的官方驱动手撸一个简易版MongoDB-ORM框架 如题,在GitHub上找了一圈想找一个MongoDB的的ORM框架,未偿所愿,就去翻了翻官网(https://docs.mongo ...
- 撸了一个简易的配置中心,顺带整合到了SpringCloud
大家好,我是三友~~ 最近突然心血来潮(就是闲的)就想着撸一个简单的配置中心,顺便也照葫芦画瓢给整合到SpringCloud. 本文大纲 配置中心的概述 随着历史的车轮不断的前进,技术不断的进步,单体 ...
- 手撸一个springsecurity,了解一下security原理
手撸一个springsecurity,了解一下security原理 转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理 今天手撸一个简易版本的sp ...
- 基于注解处理器开发自动生成getter和setter方法的插件
昨天无意中,逛到了lombok的网站,并看到了首页的5分钟视频,视频中的作者只是在实体类中写了几个字段,就可以自动编译为含setter.getter.toString()等方法的class文件.看着挺 ...
随机推荐
- 一起来玩echarts系列(一)------箱线图的分析与绘制
一.箱线图 Box-plot 箱线图一般被用作显示数据分散情况.具体是计算一组数据的中位数.25%分位数.75%分位数.上边界.下边界,来将数据从大到小排列,直观展示数据整体的分布情况. 大部分正常数 ...
- web前端基础知识
#HTML 什么是HTML,和他ML... 网页可以比作一个装修好了的,可以娶媳妇的房子. 房子分为:毛坯房,精装修 毛坯房的修建: 砖,瓦,水泥,石头,石子.... 精 ...
- CENTOS 6.5 平台离线编译安装 PHP5.6.6
一.下载php源码包 http://cn2.php.net/get/php-5.6.6.tar.gz/from/this/mirror 二.编译 编译之前可能会缺少一些必要的依赖包,加载一个本地yum ...
- Ubuntu 16.10 安装KolourPaint 4画图工具
KolourPaint 4画图工具简单实用,可以绘画.视频处理和图标编辑: • 绘画:绘制图表和“手绘” • 视频处理:编辑截图和照片;应用特效 • 图标编辑:绘画剪贴和标识透明化 1.在Ubuntu ...
- [APUE]文件和目录(上)
一.文件权限 1. 各种ID 我在读这一章时遇到了各种ID,根据名字完全不清楚什么意思,幸好看到了这篇文章,http://blog.csdn.net/ccjjnn19890720/article/de ...
- Android数据加密之SHA安全散列算法
前言: 对于SHA安全散列算法,以前没怎么使用过,仅仅是停留在听说过的阶段,今天在看图片缓存框架Glide源码时发现其缓存的Key采用的不是MD5加密算法,而是SHA-256加密算法,这才勾起了我的好 ...
- AFNetworking 3.0 源码解读 总结(干货)(下)
承接上一篇AFNetworking 3.0 源码解读 总结(干货)(上) 21.网络服务类型NSURLRequestNetworkServiceType 示例代码: typedef NS_ENUM(N ...
- C#~异步编程再续~await与async引起的w3wp.exe崩溃-问题友好的解决
返回目录 关于死锁的原因 理解该死锁的原因在于理解await 处理contexts的方式,默认的,当一个未完成的Task 被await的时候,当前的上下文将在该Task完成的时候重新获得并继续执行剩余 ...
- Java实现Excel中的NORMSDIST函数和NORMSINV函数
由于工作中需要将Excel中的此两种函数转换成java函数,从而计算内部评级的资本占用率和资本占用金额.经过多方查阅资料和整理,总结出如下两个转换方法 标准正态分布累计函数NORMSDIST: pub ...
- 嵌入式&iOS:回调函数(C)与block(OC)传 参/函数 对比
C的回调函数: callBack.h 1).声明一个doSomeThingCount函数,参数为一个(无返回值,1个int参数的)函数. void DSTCount(void(*CallBack)(i ...