接触过web开发的同学想必都接触过MVVM,业界著名的MVVM框架就有AngelaJS。今天闲来无事,决定自己实现一个简单的MVVM框架玩一玩。所谓简单,就是仅仅实现一个骨架,仅表其意,不摹其形。

分析

MVVM最大的特点莫过于双向绑定了,数据的变化能及时更新到视图上,同时视图的变化也能及时的更新到数据中。

那么怎么实现这样的双向绑定呢?最直接的方式莫过于事件了。

所以,我们需要实现一个事件的订阅与分发机制,这个功能很常见,网上搜一搜一大堆。

有了这么一套事件的订阅与分发机制,我们就可以通过它将Model和View关联起来,这样不管是Model还是View有变化,都可以通过事件通知到对方了。

实现

首先要实现一套事件的订阅与分发机制,直接贴代码了:

function Event() {
this.handlers = {};
} Event.prototype.on = function (eventName, handler) {
if (!this.handlers) {
this.handlers = {};
}
if (this.handlers[eventName]) {
this.handlers[eventName].push(handler);
} else {
this.handlers[eventName] = [handler];
}
} Event.prototype.fire = function (eventName, eventData) {
if (this.handlers[eventName]) {
this.handlers[eventName].forEach(function (handler) {
handler(eventData);
});
}
} Event.prototype.off = function (eventName, handler) {
if (this.handlers[eventName]) {
for (var i = 0; i < this.handlers[eventName].length; i++) {
if (this.handlers[eventName][i] === handler) {
this.handlers[eventName].splice(i, 1);
}
}
}
}

上诉代码实现了某个事件的监听、触发与移除操作。

有了事件,如何将其与View和Model结合起来呢? 继承。

function Model(data) {
this.data = data;
} Model.prototype = new Object(Event.prototype);
Model.prototype.constructor = Model; Model.prototype.set = function (key, value) {
if (this.data[key]) {
this.data[key] = value;
}
this.fire("change", value);
} Model.prototype.get = function (key) {
console.log("key: ", key, " value: ", this.data[key]);
}
function View(model, el) {
this.el = el;
this.model = model; this.init();
} View.prototype.init = function () {
var me = this;
this.model.on("change", function (value) {
me.model.get("value");
if (me.el.type === "text") {
me.el.value = value;
} else {
me.el.innerText = value;
}
});
if (this.el.type === "text") {
this.el.addEventListener("change", function () {
me.model.set("value", this.value);
});
} else {
this.el.addEventListener("click", function () {
var num = new Number(this.innerText || 0);
me.model.set("value", num + 1);
});
} }

View中为了简单处理,直接进行了硬编码,实际应用过程中需要详细处理。

到此,Model和View都有了,下面再加一段代码将他们关联起来:


function MVVM() {
this.cache = {};
} MVVM.prototype.bind = function (data, el) {
var model = new Model(data);
var view = new View(model, el);
var key = "key_" + (new Date()).getTime();
this.cache[key] = {
model: model,
view: view
};
}

测试代码如下:

< !DOCTYPE html>
< html>
< head>
< title>MVVM</title>
< script type="text/javascript" src="./Event.js"></script>
< script type="text/javascript" src="./Model.js"></script>
< script type="text/javascript" src="./View.js"></script>
< style type="text/css">
#inputId {
width: 300px;
height: 30px;
border: 1px solid grey;
margin: 10px;
}
#textId {
width: 300px;
height: 100px;
text-align: center;
border: 1px solid black;
line-height: 100px;
font-size: 20px;
}
< /style>
< /head>
< body>
< div>
< input id="inputId" type="text"></input>
< div id="textId">0</div>
< /div>
< script type="text/javascript" src="./index.js"></script>
< script type="text/javascript">
var mvvm = new MVVM();
mvvm.bind({
value: "text input"
}, document.getElementById("inputId"));
mvvm.bind({
value: "div text"
}, document.getElementById("textId"));
< /script>
< /body>
< /html>

测试代码中绑定了一个输入框和一个div,当输入框中值发生改变时,Model中的值也会相应改变(查看控制台打印信息)。当点击div时,div中的文本数字会加一,对应Model中的数据也会改变。

到此所有的功能就实现完了,虽说简单了点,但是基本意思算是都到了,收工~~。

如何实现一个简单的MVVM框架的更多相关文章

  1. 基于vue实现一个简单的MVVM框架(源码分析)

    不知不觉接触前端的时间已经过去半年了,越来越发觉对知识的学习不应该只停留在会用的层面,这在我学jQuery的一段时间后便有这样的体会. 虽然jQuery只是一个JS的代码库,只要会一些JS的基本操作学 ...

  2. 230行实现一个简单的MVVM

    作者:mirone链接:https://zhuanlan.zhihu.com/p/24451202来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. MVVM这两年在前端届 ...

  3. 用Python写一个简单的Web框架

    一.概述 二.从demo_app开始 三.WSGI中的application 四.区分URL 五.重构 1.正则匹配URL 2.DRY 3.抽象出框架 六.参考 一.概述 在Python中,WSGI( ...

  4. 一个简单的web框架实现

    一个简单的web框架实现 #!/usr/bin/env python # -- coding: utf-8 -- __author__ = 'EchoRep' from wsgiref.simple_ ...

  5. 自己实现的一个简单的EF框架(反射实现)

    我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...

  6. koa2源码解读及实现一个简单的koa2框架

    阅读目录 一:封装node http server. 创建koa类构造函数. 二:构造request.response.及 context 对象. 三:中间件机制的实现. 四:错误捕获和错误处理. k ...

  7. Core1.1环境下,自己实现的一个简单的CRUD框架(反射实现)

    我实现了一个简单的EF框架,主要用于操纵数据库.实现了对数据库的基本操纵--CRUD 这是项目结构 这是一个 core 下的 DLL 写了一个数据库工厂,用于执行sql语句.调用sql语句工厂 写了一 ...

  8. 动手造轮子:实现一个简单的 AOP 框架

    动手造轮子:实现一个简单的 AOP 框架 Intro 最近实现了一个 AOP 框架 -- FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计. 整体设计 概览 I ...

  9. 徒手撸一个简单的RPC框架

    来源:https://juejin.im/post/5c4481a4f265da613438aec3 之前在牛逼哄哄的 RPC 框架,底层到底什么原理得知了RPC(远程过程调用)简单来说就是调用远程的 ...

随机推荐

  1. xampp本地服务器+HBuilder配置php环境

    HBuilder配置PHP环境: 下载,运行HBuilder编辑器 打开右侧小窗口,点击设置图标—>设置web服务器—>外置web服务器                    输入你想要浏 ...

  2. 【EfF】 贪婪加载和延迟加载 (virtual去掉关闭延迟加载)

    EntityFramework(EF)贪婪加载和延迟加载的选择和使用 贪婪加载:顾名思议就是把所有要加载的东西一 次性读取 1 using (var context = new MyDbContext ...

  3. .net core in Docker 部署方案(随笔)

    前一段时间由于项目需要 .net core 在docker下的部署,途中也遇到很多坑,看了各同行的博客觉得多多少少还是有些问题,原本不想写此篇文章,由于好友最近公司也需要部署,硬是要求,于是花了些时间 ...

  4. My97DatePicker常用日期格式

    WdatePicker({ minDate: '%y-%M-%d', maxDate: '#F{$dp.$D(\'GradeEndDate\',{d:-1});}' }); WdatePicker({ ...

  5. Selenium API(二)

    1.定位一组元素 WebDriver提供了8种定位一组元素的方法. driver.find_elements_by_css_selector() driver.find_elements_by_tag ...

  6. 为什么要使用MQ消息中间件?

    在面试大型互联网公司的时候,很可能会被问到消息队列的问题: 1.在何种场景下使用了消息中间件? 2.为什么要在系统里引入消息中间件? 3.如何实现幂等? 链式调用是我们在写程序时候的一般流程,为了完成 ...

  7. 微信小程序获取用户手机号,服务器解码demo

    原理:通过微信登陆接口wx.login得到encryptedData . iv  .code.经过接口处理code得到sessionkey.最后官方demo得到解密后的手机号.(接口处理这一步也可以在 ...

  8. hdp 2.06 安装备忘

    1,官方安装说明文档 http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.6.0-Win/bk_installing_hdp_for_windo ...

  9. CentOS7.4关闭防火墙

    //临时关闭 systemctl stop firewalld //禁止开机启动 systemctl disable firewalld Removed symlink /etc/systemd/sy ...

  10. Windows Server 2008 R2中IIS7.5配置完网站权限不足问题的解决办法:

    Windows Server 2008 R2中IIS7.5配置完网站权限不足问题的解决办法:常见问题:HTTP 错误 500.0 - Internal Server Error无法显示页面,因为发生内 ...