非常简单的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
这样就完成了双向绑定
相关文章推荐
- checkbox属性checked="checked"通过js已设置,但是不勾选
- 认识ExtJs的开发包(基础必备)
- 了解JSONP
- 【最小生成树+贪心】BZOJ1821: [JSOI2010]Group 部落划分 Group
- 转: when.js原理和核心实现
- Errors occurred during the build. Errors running builder 'JavaScript Validator' on project 'XXX'.
- Errors occurred during the build. Errors running builder 'JavaScript Validator' on project 'XXX'.
- JS 获取url,html文件名,参数值
- 智能社JavaScript学习笔记——JS运动基础
- 在JSP页面中使用Ajax主题时的引入
- 读书笔记--JavaScript设计模式:Module模式(为类提供私有和公有封装)
- 作用域—JS学习笔记2015-6-8(第52天)
- JavaScript中join()方法的使用简介
- 在JavaScript中操作数组之map()方法的使用
- JavaScript中pop()方法的使用教程
- 简介JavaScript中的push()方法的使用
- JavaScript中reduce()方法的使用详解
- 在JavaScript中处理数组之reverse()方法的使用
- 详解JavaScript中shift()方法的使用
- JavaScript中的some()方法使用详解