原生JS实现MVVM模式
欢迎大家指导与讨论 : )
前言
关于MVVM的原理大家可以参考这篇文章。《【翻译】Object.observe()带来的数据绑定变革 》http://www.tuicool.com/articles/ZVVNBv。
文章中的代码为笔者实践时写的小demo,可以运行。
代码
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<title>Document</title>
</head> <body> <div id="app">
<h1>作用域A</h1>
<input type="text" two-way-bind="test">
<h1 bind="test"></h1>
</div>
<hr /> <div id="apple">
<h1>作用域B</h1>
<input type="text" two-way-bind="test">
<h1 bind="test"></h1>
</div>
<hr /> <script type="text/javascript">
// vm -> view model; v -> view
// 自定义两个绑定“指令”一个是从vm->v的绑定,一个是双向绑定
var directive_bind = ['bind', 'two-way-bind'];
// 常量 声明该类型仅仅是vm->v 的DOM渲染
var DOM = 'DOM'
// 常量 声明该类型是双向绑定
var TWOWAY = 'TWOWAY'
// 新增两个作用域,用的是元素ID
var vm = new mvvm('app');
var vm2 = new mvvm('apple') // 这是一个构造函数
// 用来返回一个可以被监测变化、有固定范围的vm
function mvvm(rootEle) {
this.scope = rootEle
// 监听vm
observe(this)
// 确定作用域 —— 同时为v -> vm做事件监听
fineScope(this)
} function observe(vm) {
// 监听vm对象模型的改变
Object.observe(vm, function(changes) {
changes.forEach(function(change, i) {
switch (change.type) {
case 'add':
fineScope(vm)
break;
case 'delete':
fineScope(vm);
break;
case 'update':
fineScope(vm);
break;
default:
break;
}
})
})
} // vm的改变引起v的改变 此处是 vm -> v
function updateView(ele, value, type) {
if (type === DOM) {
if (value) {
ele.innerHTML = value
} else {
ele.innerHTML = ''
} } else if (type == TWOWAY) {
if (value) {
ele.value = value
} else {
ele.value = ''
}
}
} function fineScope(vm) {
var vmRootEle = document.getElementById(vm.scope)
// 递归遍历该作用域下的所有DOM
findChild(vmRootEle, vm)
} function findChild(ele, vm) {
// 查找所有自定义属性:bind、two-way-bind
for (var i = 0; i < directive_bind.length; i++) {
// 如果DOM有我们的自定义绑定属性
if (ele.getAttribute(directive_bind[i]) && directive_bind[i] === 'bind') {
// 则按 vm->v的方向进行渲染
updateView(ele, vm[ele.getAttribute('bind')], DOM)
} else if (ele.getAttribute(directive_bind[i]) && directive_bind[i] === 'two-way-bind') {
var attr = ele.getAttribute('two-way-bind')
// 同理
updateView(ele, vm[attr], TWOWAY)
// 有点不同,这里是双向绑定,需要为该DOM增加事件监听
twoWayBind(ele, attr, vm)
}
}
// 递归遍历
if (ele.hasChildNodes()) {
var sonNodes = ele.childNodes;
for (var j = 0; j < sonNodes.length; j++) {
if (sonNodes[j].nodeType === 1) {
findChild(sonNodes[j], vm)
}
}
}
} function twoWayBind(ele, prop, vm) {
// 局限性:本DOM只是用了input[text],如果要监听其他input[x]应该要用对应的监听方法
ele.oninput = function() {
vm[prop] = ele.value
}
}
</script>
</body> </html>
原生JS实现MVVM模式的更多相关文章
- 由项目浅谈JS中MVVM模式
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1. 背景 最近项目原因使用了durandal.js和knock ...
- js架构设计模式——由项目浅谈JS中MVVM模式
1. 背景 最近项目原因使用了durandal.js和knockout.js,颇有受益.决定写一个比较浅显的总结. 之前一直在用SpringMVC框架写后台,前台是用JSP+JS+标签库,算是很 ...
- 原生JS:严格模式详解
严格模式 本文参考MDN做的详细整理,方便大家参考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript) 设计目的 设立”严格模式 ...
- dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来
dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...
- 使用单体模式设计原生js插件
----------基于上次写的jquery插件进行改造 http://www.cnblogs.com/GerryOfZhong/p/5533773.html 背景:jQuery插件依赖jQuery ...
- 浅谈MVVM模式和MVP模式——Vue.js向
浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...
- js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别
MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...
- 抛弃JQ,回归原生js……
之前我写过一篇文章叫做<jq不会被淘汰>--而事实上它真的不会被淘汰,因为即使在mvvm框架盛行的今天,原生js的api越来越友好的今天,jq依然在用户量上是霸主-- 但是今天我们要讨论的 ...
- Vue.js 和 MVVM 的小细节
Vue.js 和 MVVM 的小细节 转载 作者:流云诸葛 链接:www.cnblogs.com/lyzg/p/6067766.html MVVM 是Model-View-ViewModel 的缩写, ...
随机推荐
- python基础之文件处理
读和写文件 读写文件是最常见的IO操作.Python内置了读写文件的函数,用法和C是兼容的. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直 ...
- eclipse js 报错解决办法
最近项目中的js一直红叉叉,本人本来就是那种看见回收站有东西想清理的那种强迫症患者, 所以对于这种红叉叉更是心烦.这个我已经忍了好久了.今天 见这哥们犀利的解决了这个eclipes的bug.很是激动, ...
- WebApi系列~FromUri参数自动解析成实体的要求
回到目录 关于webapi我之前写了一些文章,大家可以根据目录去浏览,今天要说的是个怪问题,也是被我忽略的一个问题,当你的Url参数需要被Api自动解析成实体的属性,实事上是要有条件的,不是所以属性都 ...
- jquery投色子动画
可以点击这里体验效果:http://keleyi.com/keleyi/phtml/jqtexiao/26.htm 效果图: 代码如下: <!DOCTYPE HTML> <html& ...
- 最大似然判别法和Bayes公式判别法
最大似然判别法 Bayes公式判别法
- ArcGIS中国工具应用:固定比例尺固定纸张批量打印
ArcGIS中国工具应用:固定比例尺固定纸张批量打印 下载地址:http://files.cnblogs.com/files/gisoracle/a3batchprint.zip 固定A3,比例尺1: ...
- 用UILocalNotification实现一个闹钟(Swift)
之前项目需求要实现一个闹钟,github上找了半天发现都是很旧的代码了,所以就准备自己写一个,刚好最近在学习Swift,就用Swift写了一个demo放在这里:https://github.com/P ...
- reason: '[<__NSDictionary0 0x7fda88f00c90> setValue:forUndefinedKey:]: this class is not key value c
reason: '[<__NSDictionary0 0x7fda88f00c90> setValue:forUndefinedKey:]: this class is not key v ...
- PHP魔术常量
与J2E相比PHP没有九个内置对象,但他有八个魔术变量分别是: '__LINE__' 文件中的当前行号. '__FILE__ 文件的完整路径和文件名. '__DIR__' 文件所在的目录. '__FU ...
- iOS---A valid provisioning profile for this executable was not found
把Target中的Code Signing Identity也设置成iPhone Develop就ok了,这样一切都说的通了,唯一不合理的就是在Project切换Code Signing Identi ...