您的位置:首页 > Web前端 > JavaScript

非常简单的js双向绑定框架(一)

2015-06-09 09:25 639 查看

初衷

搞了近5个月的angularjs项目,用起来非常顺手。最爽的是两个功能:

1. 控制器的继承特性

2. 数据的双向绑定

3. 表达式控制显示与否

前者减少了很多model的重复声明,赋值。后者大大简化了动态编辑,动态显示。比如我的表格需要根据某一列排序,我只用改动数据模型的顺序,视图会自动更新。

但是,作为“Get your hands dirty”的小项目,用脏值检测和dom树编译太难了,目标1周的话搞不掂。所以借鉴knockoutjs的方法:

var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable(123)
};
ko.applyBindings(myViewModel, document.getElementById('my-view'));


手动的把一个js object绑到某个DOM元素上去。

目标

实现数据的双向绑定(input, textarea, select)

实现控制器继承,控制器的作用范围在html里声明,而不是像knockout一样用js声明

基本事件的绑定,如click

类似ng-show这样的表达式控制显隐

第一个特性:双向绑定

参考这篇blog: pubsub双向绑定

我们用原生js先实现pubsub本身,为了代码的独立性,不像原文一样做dom操作:

<body isi-controller="MainController">
<script type="text/javascript">
var myModel;
window.onload = function() {
myModel = new Model;
myModel.set( "name", "isildur" );
}
</script>
<input type="text" data-bind="name"/>
</body>


var pubsub = (function() {
var _callbacks = {};
var pubsub = {
sub: function(name, callback) {
if( !_callbacks.hasOwnProperty(name) ) {
_callbacks[name] = [];
}
_callbacks[name].push(callback);
},
pub: function(name) {
var args = Array.prototype.slice.call(arguments,1)
if( _callbacks.hasOwnProperty(name) ) {
_callbacks[name].forEach( function(callback) {
callback.apply(this, args);
});
}
}
}
return pubsub;
})();

// listener capture view change event --> publish view.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);
}
}
document.addEventListener('change', changeHandler, false);

// view.change event --> change view
pubsub.sub('view.change', function(propName, newVal) {
var elements = document.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;
}
}
});

var Model = function() {
var model = {
props: {},
set: function(propName, value) {
this.props[propName] = value;
// model change --> publish view.change event
pubsub.pub('view.change', propName, value);
},
get: function(propName) {
return this.props[propName];
}
}
// model.change event --> change model data
pubsub.sub('model.change',function(propName, newVal) {
model.set(propName,newVal);
});
return model;
}


可以看到,我们搞了2个pubsub的”信道”: view.change和model.change

模型的set方法会给view.change信道发消息,改变view

view的监听器会给model.change信道发消息,改变model

这样就完成了双向绑定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: