欢迎大家指导与讨论 : )

  前言

    关于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模式的更多相关文章

  1. 由项目浅谈JS中MVVM模式

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.    背景 最近项目原因使用了durandal.js和knock ...

  2. js架构设计模式——由项目浅谈JS中MVVM模式

    1.    背景 最近项目原因使用了durandal.js和knockout.js,颇有受益.决定写一个比较浅显的总结. 之前一直在用SpringMVC框架写后台,前台是用JSP+JS+标签库,算是很 ...

  3. 原生JS:严格模式详解

    严格模式 本文参考MDN做的详细整理,方便大家参考[MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript) 设计目的 设立”严格模式 ...

  4. dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来

    dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...

  5. 使用单体模式设计原生js插件

    ----------基于上次写的jquery插件进行改造  http://www.cnblogs.com/GerryOfZhong/p/5533773.html 背景:jQuery插件依赖jQuery ...

  6. 浅谈MVVM模式和MVP模式——Vue.js向

    浅谈MVVM模式和MVP模式--Vue.js向 传统前端开发的MVP模式 MVP开发模式的理解过程 首先代码分为三层: model层(数据层), presenter层(控制层/业务逻辑相关) view ...

  7. js架构设计模式——MVVM模式下,ViewModel和View,Model有什么区别

    MVVM模式下,ViewModel和View,Model有什么区别 Model:很简单,就是业务逻辑相关的数据对象,通常从数据库映射而来,我们可以说是与数据库对应的model. View:也很简单,就 ...

  8. 抛弃JQ,回归原生js……

    之前我写过一篇文章叫做<jq不会被淘汰>--而事实上它真的不会被淘汰,因为即使在mvvm框架盛行的今天,原生js的api越来越友好的今天,jq依然在用户量上是霸主-- 但是今天我们要讨论的 ...

  9. Vue.js 和 MVVM 的小细节

    Vue.js 和 MVVM 的小细节 转载 作者:流云诸葛 链接:www.cnblogs.com/lyzg/p/6067766.html MVVM 是Model-View-ViewModel 的缩写, ...

随机推荐

  1. C程序范例(2)——学生管理系统”链表“实现

    1.对于学生管理系统,能够实现的方法有许多,但是今天我们用链表的方法来实现.虽然初学者很可能看不懂,但是不要紧,这是要在整体的系统的学习完C语言之后,我才编写出的程序.所以大家不必要担心.在这里与大家 ...

  2. php实现设计模式之 迭代器模式

    <?php /*迭代器模式: 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.(行为模式) * 1.迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的 ...

  3. Storm的BaseBasicBolt源码解析ack机制

    我们在学习ack机制的时候,我们知道Storm的Bolt有BaseBasicBolt和BaseRichBolt.在BaseBasicBolt中,BasicOutputCollector在emit数据的 ...

  4. css制作漂亮彩带导航条菜单

    点击这里查看效果:http://keleyi.com/keleyi/phtml/divcss/17.htm 效果图: 以下是源代码: <!DOCTYPE html PUBLIC "-/ ...

  5. jquery背景自动切换特效

    查看效果网址:http://keleyi.com/a/bjad/4kwkql05.htm 本特效的jquery版本只支持1.9.0以下. 代码如下: <!DOCTYPE html PUBLIC ...

  6. github的pull request是指什么意思?有什么用处

    github的pull request是指什么意思? 来看看某乎某位阿牛的理解,多么的简单粗暴! 我尝试用类比的方法来解释一下 pull reqeust.想想我们中学考试,老师改卷的场景吧.你做的试卷 ...

  7. SVN版本控制系统学习(中文配置)

    先吐槽下往上搜索的一些SVN下载地址,里面乱七八糟啥都有,下载好后点击安装一不注意啥玩意都安装上了, 什么玩意都有,真心不明白这些推送者是怎么想的.搜集了一个WIN32的百度网盘下载地址: http: ...

  8. angularjs+微信,解决chooseImage不能预览的问题

    在wx.chooseImage的success回调中直接进行数据绑定,却在ng-repeat时发现ng-src不加载微信localId的问题,类似wxLocalResource://imageid98 ...

  9. iOS笔记之NSSet

     一.简介 NSSet到底什么类型,其实它和NSArray功能性质一样,用于存储对象,属于集合: NSSet  , NSMutableSet类声明编程接口对象,无序的集合,在内存中存储方式是不连续的, ...

  10. JVM-加载,链接,初始化

    Java Virtual Machine 动态的加载,链接和初始化类和接口.那么,Class 二进制文件是怎样被 JVM 加载到内存中的?JVM 如何描述一个 Java 类?类或接口怎么才能让 JVM ...