原生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 的缩写, ...
随机推荐
- 3、ASP.NET MVC入门到精通——Entity Framework增删改查
这里我接上讲Entity Framework入门.从网上下载Northwind数据库,新建一个控制台程序,然后重新添加一个ado.net实体数据模型. EF中操作数据库的"网关"( ...
- GJM :多人在线游戏的设计思路
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- 从头开始搭建一个dubbo+zookeeper平台
本篇主要是来分享从头开始搭建一个dubbo+zookeeper平台的过程,其中会简要介绍下dubbo服务的作用. 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后 ...
- 【requireJS源码学习02】data-main加载的实现
前言 经过昨天的学习,我们大概了解到了requireJS的主要结构,这里先大概的回顾一下 首先从总体结构来说,require这里分为三块: ① newContext之前变量声明或者一些工具函数 ② n ...
- mysql存储过程详解
mysql存储过程详解 1. 存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的S ...
- 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(三)显示地图坐标系模块
config.xml文件的配置如下: <widget left="3" bottom="3" config="widgets/Coordinat ...
- footer置底
html代码: <div class="container"> <div cass="header"></div> < ...
- 基于物理渲染的渲染器Tiberius计划
既然决定实现一个光栅化软件渲染器,我又萌生了一个念头:实现一个基于物理渲染的渲染器.
- ASP.NET MVC中Unobtrusive Ajax的妙用
Unobtrusive Javascript有三层含义:一是在HTML代码中不会随意的插入Javsscript代码,只在标签中加一些额外的属性值,然后被引用的脚本文件识别和处理:二是通过脚本文件所增加 ...
- js中的运算总结(未完待续
[74由几个1几个5几个10几个20组成] var num = 74; for(one = 0; one <= num; one++){ for(five = 0; five <= num ...