很easy的js双向绑定框架(二):控制器继承
初衷
上一篇已经实现了数据的双向绑定,但model的控制范围是整个文档。在实际project中必需要有作用范围,以便做ui模块的拆分。
这一篇,我们希望实现像angularjs一样的控制器继承:
1. 父controller的Model能够在子controller里被訪问到
2. 子controller的model不影响父controller
3. controller继承关系在html中指定。而不是js中指定
目标
html里,用isi-controller属性去声明控制器:
<body>
<div isi-controller="ParentController">
<input data-bind="name">
<div isi-controller="SubController">
<input data-bind="name">
</div>
</div>
</body
希望上面的input name 改了。以下的会跟着变,而以下的变了,上面的不变。
js里,用和上面isi-controller属性值同名的函数定义控制器:
function ParentController() {
var model = new Model();
model.set('name', 'parent');
}
function ParentController() {
var model = new Model();
model.set('name', 'sub');
}
对用户来说,仅仅要写这些。就完事儿了。
实现
版本号1
这个版本号採用最简单直观的思路:框架去找$(‘[isi-controller]’)的元素。然后给这些元素分别去绑定监听器、运行控制器函数
代码先列了:
index.html:
<html>
<head>
<title>simple MVVM</title>
<script src="js/ParentController.js"></script>
<script src="js/SubController.js"></script>
<script src="js/frame_v2.js"></script>
</head>
<body isi-controller="ParentController">
<input type="text" data-bind="name">
<div isi-controller="SubController">
<input type="text" data-bind="name">
</div>
</body>
</html>
ParentController.js:
function ParentController() {
var model = new Model();
model.set('name', 'parent');
}
SubController.js:
function SubController() {
var model = new Model();
model.set('name','sub');
}
frame_v2.js: (对比上一篇,主要修改在绑监听器和new Model的自己主动化)
var pubsub = ... //见上一篇
var Model = ... //见上一篇
// listener capture view changes --> publish model.change event
var changeHandler = function(event) {
var target = event.target,
propName = target.getAttribute('data-bind');
if( propName && propName !== '' ) {
pubsub.pub('model.change', propName, target.value);
}
event.stopPropagation();
}
/*----------- Init --------------*/
window.onload = function() {
/* first step:
* find controllers' dom
*/
var controllerRanges = document.querySelectorAll('[isi-controller]');
/* second step:
* bind listeners for each controllers' range,
* view.change event --> change each controllers' range
*/
for(var i=0, len=controllerRanges.length; i<len; i++) {
controllerRanges[i].addEventListener('change', changeHandler, false);
// view.change event --> change view
(function(index){
pubsub.sub('view.change', function(propName, newVal) {
var elements = controllerRanges[index].querySelectorAll('[data-bind=' + propName +']'),
tagName;
for(var i=0,l=elements.length; i<l; i++) {
tagName = elements[i].tagName.toLowerCase();
if(tagName==='input' || tagName==='textarea' || tagName==='select') {
elements[i].value = newVal;
} else {
elements[i].innerHTML = newVal;
}
}
});
})(i);
}
/* third step:
* execute each controller function
*/
for(var i=0, len=controllerRanges.length; i<len; i++) {
var controllerName = controllerRanges[i].getAttribute('isi-controller');
eval(controllerName+'()');
}
}
看看效果:
悲剧了。
没有实现第二个初衷:子控制器不影响父控制器。
这个问题该怎样解决呢?
版本号二,子不影响父
细致看代码,之所以会出现故障,是由于view.change信道的作用范围是有问题的。无论哪个model发出的view.change事件,两个控制器的view都会改变。
所以,我们给公布view.change事件的时候,多公布一个控制器名。好让接收view.change的时候知道应不应该修改html:
var Model = function(controllerName) {
var model = {
controllerName:controllerName,
props: {},
set: function(propName, value) {
this.props[propName] = value;
pubsub.pub('view.change', propName, value, this.controllerName); //就是这里!
}
}
控制器里new Model的时候注意把controller的名字初始化进去:
ParentController.js:
function ParentController() {
var model = new Model('ParentController');
model.set('name', 'parent');
}
最后接收view.change信道消息的时候,推断下controllerName:
pubsub.sub('view.change', function(propName, newVal, controllerName) {
....
thisControllerName = controllerRanges[index].getAttribute('isi-controller'),
if(thisControllerName !== controllerName)
return;
....
}
当然。监听器公布model.change的时候也是一样。要把控制器名称公布出去。代码就不贴了。
再看看效果:
妥了
全部代码:
github/victorisildur
很easy的js双向绑定框架(二):控制器继承的更多相关文章
- Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)
Vue.js双向绑定的实现原理 解析 神奇的 Object.defineProperty 这个方法了不起啊..vue.js和avalon.js 都是通过它实现双向绑定的..而且Object.obser ...
- Vue.js双向绑定的实现原理
Vue.js最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统.本文仅探究几乎所有Vue的开篇介绍都会提到的hello world双向绑定是怎样实现的.先讲涉及的知识点,再参考源码,用尽可能少 ...
- Vue.js双向绑定原理
Vue.js最核心的功能有两个,一个是响应式的数据绑定系统,另一个是组件系统.本文仅仅探究双向绑定是怎样实现的.先讲涉及的知识点,再用简化的代码实现一个简单的hello world示例. 一.访问器属 ...
- vue.js双向绑定之--select获取text
在大多数情况下select下拉菜单都是value和text设置不同的值的,value一般来说是与后台交互的值,而text是前端用来显示的文本: 但是,vue.js对到表单的双向绑定时如果option设 ...
- js 双向绑定
//双向绑定实例 <input name="" ng-bind-123="name" /> function DataBinder( object_ ...
- Angular js 双向绑定时字符串的转换成 数字类型的问题
问题: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <scrip ...
- js 双向绑定数据
let aaa = []; let bbb = [1,2,3]; let ccc = [0,9,8]; aaa = bbb; //此时aaa与bbb被绑定(aaa指向bbb的指向) ,若使用push则 ...
- js双向绑定和地址传递带来的痛苦解决方案之对象拷贝
function cloneObj(obj) { var newObj = {}; if (obj instanceof Array) { newObj = []; } for (var key in ...
- node.js面向对象实现(二)继承
http://blog.sina.com.cn/s/blog_b5a53f2e0101nrdi.html 继承是面向对象中非常重要的一个概念,那么在Node.js中如何实现继承呢? node.js在u ...
随机推荐
- verynginx +nginx_upstream_check_module模块,负载均衡检查模块。
yum -y install git yum -y install patch yum -y install pcre-devel yum install -y zlib-devel mkdir ...
- 常见社工破解WPA2密码方法及防范措施
0×00前言 何为社工?社工是一种通过利用受害者心理弱点,如本能反应.好奇心.同情心.信任.贪婪等进行诸如欺骗.盗取.控制等非法手段的一种攻击方式.在无线安全中也可以利用社工做到许多非法操作.下面举几 ...
- http://blog.csdn.net/szwangdf/article/details/23432783
http://blog.csdn.net/szwangdf/article/details/23432783
- win 8 远程桌面文件复制问题(图)
用win7连接远程桌面.能够非常方便的在宿主机之间文件复制粘贴. 但用win8.1远程连接桌面时,却发现不能拷贝文件了.查看网上资料,最后总结实现此步骤例如以下: win+R,执行mstsc.例如以下 ...
- java源码阅读LinkedList
1类签名与注释 public class LinkedList<E> extends AbstractSequentialList<E> implements List< ...
- Guice 学习(五)多接口的实现( Many Interface Implementation)
1.接口 /* * Creation : 2015年6月30日 */ package com.guice.InterfaceManyImpl; public interface Service { p ...
- org.hibernate.exception.ConstraintViolationException: could not delete:
转自:http://fireinwind.iteye.com/blog/848515 异常描述: org.hibernate.exception.ConstraintViolationExceptio ...
- 在Dell XPS 13安装WIN10和ubuntu双系统
新入了Dell的XPS 13超级本,之所以买这个本子,就是看中它轻便且续航持久.这款本子也是为数不多的能够和苹果的13'' mac book air一较高下的本子.在重量上,占地面积和综合性价比上,还 ...
- Java 1.7 ReentrantReadWriteLock源代码解析
因为本人水平与表达能力有限,有错误的地方欢迎交流与指正. 1 简单介绍 可重入读写锁时基于AQS实现的,典型的用法如JDK1.7中的演示样例: class RWDictionary { private ...
- World Wind Java开发之三 显示状态栏信息
先来看下本篇博客索要达到的效果: 找到源代码下的gov.nasa.worldwind.util下的StatusBar.java文件,能够看到状态栏显示的信息主要包含视点高度以及相应空间点三维坐标以及是 ...