很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 ...
随机推荐
- webpack-dev-server最简单的应用
1.安装 npm install webpack-dev-server --save-dev 2.再exports后加多一个对象即可 devServer: { contentBase: ". ...
- linux中查找文件属于那个软件包的方法
一.linux中查找文件属于那个软件包的方法 [root@salt prod]# whereis htpasswdhtpasswd: /usr/bin/htpasswd /usr/share/man/ ...
- openstack学习笔记(一)-openstack的基础知识
一.OpenStack的基础知识 openstack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache2.0许可证(兼容GPLv3以及DFSG)授权的自由软件和 ...
- DevExpress 15.1.sln
Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio VisualStudioVersion = 14 ...
- 使用Unity3D的50个技巧:Unity3D最佳实践
转自:http://www.tuicool.com/articles/buMz63I 刚开始学习unity3d时间不长,在看各种资料.除了官方的手册以外,其他人的经验也是非常有益的.偶尔看到老外这篇 ...
- Pattern Recognition and Machine Learning 模式识别与机器学习
模式识别(PR)领域: 关注的是利⽤计算机算法⾃动发现数据中的规律,以及使⽤这些规律采取将数据分类等⾏动. 聚类:目标是发现数据中相似样本的分组. 反馈学习:是在给定的条件下,找到合适的动作, ...
- 关于升级 phpStudy 中 MySQL 版本至 5.7.17
mysql版本低于5.6 自动更新时间会报错.因此要升级mysql版本.综合网上资料和实际过程中遇到的问题,具体细节和注意事项如下: 1.从官网上下载高版本的 MySQL :https://dev.m ...
- U盘安装
首先插入已经制作为启动盘的U盘,然后开机长按ESC,出现如下界面: 选择KingstonDataTraveler 3.0 按enter键进入,进入加载界面,之后出现如下界面: 这是在已经下载好系统之后 ...
- 转:EMQ(emqttd) 2.x 安装和使用(物联网传输控制协议的Broker)
支持下国产开源. MQTT物联网传输控制协议:<MQTT-3.1.1-CN.pdf> 下载:emqttd-centos64-v2.0-rc.2-20161019.zip 安装: $ unz ...
- paho-mqtt 学习笔记
Installation The latest stable version is available in the Python Package Index (PyPi) and can be in ...