Knockout双向绑定
knockout双工绑定基于 observe 模式,性能高。核心就是observable对象的定义。这个函数最后返回了一个也叫做 observable 的函数,也就是用户定义值的读写器(accessor)。
this.firstName=ko.observable(“Bert”);
this.firstName();
this.firstName(“test”);
ko.observable做了什么
ko.observable = function (initialValue) {
var _latestValue = initialValue; //保留上一次的参数,与observable形成闭包
function observable() {
if (arguments.length > ) {
// Write,Ignore writes if the value hasn't changed
if (observable.isDifferent(_latestValue, arguments[])) {
observable.valueWillMutate();
_latestValue = arguments[];
if (DEBUG) observable._latestValue = _latestValue;
observable.valueHasMutated();
}
return this; // Permits chained assignments
}
else {
// Read
ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
return _latestValue;
}
}
ko.subscribable.call(observable);
ko.utils.setPrototypeOfOrExtend(observable, ko.observable['fn']);
if (DEBUG) observable._latestValue = _latestValue;
/**这里省略了专为 closure compiler 写的语句**/
return observable;
}
通过 ko.subscribable.call(observable); 使这个函数有了被订阅的功能,让 firstName 在改变时能通知所有订阅了它的对象。其实就是维护了一个回调函数的队列,当自己的值改变时,就执行这些回调函数。根据上面的代码,回调函数是在 observable.valueHasMutated(); 执行的。
ko.computed做了什么
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
$.computed = function(obj, scope){
//computed是由多个$.observable组成
var getter, setter
if(typeof obj == "function"){
getter = obj
}else if(obj && typeof obj == "object"){
getter = obj.getter;
setter = obj.setter;
scope = obj.scope;
}
var v
var ret = function(neo){
if(arguments.length ){
if(typeof setter == "function"){//setter不一定存在的
if(v !== neo ){
setter.call(scope, neo);
v = neo;
}
}
return ret;
}else{
v = getter.call(scope);
return v;
}
}
return ret;
}
$.dependencyDetection = (function () {
var _frames = [];
return {
begin: function (ret) {
_frames.push(ret);
},
end: function () {
_frames.pop();
},
collect: function (self) {
if (_frames.length > ) {
self.list = self.list || [];
var fn = _frames[_frames.length - ];
if ( self.list.indexOf( fn ) >= )
return;
self.list.push(fn);
}
}
};
})();
$.valueWillMutate = function(observable){
var list = observable.list
if($.type(list,"Array")){
for(var i = , el; el = list[i++];){
el();
}
}
}
双向绑定如何实现
$.buildEvalWithinScopeFunction = function (expression, scopeLevels) {
var functionBody = "return (" + expression + ")";
for (var i = ; i < scopeLevels; i++) {
functionBody = "with(sc[" + i + "]) { " + functionBody + " } ";
}
return new Function("sc", functionBody);
}
$.applyBindings = function(model, node){
var nodeBind = $.computed(function (){
var str = "{" + node.getAttribute("data-bind")+"}"
var fn = $.buildEvalWithinScopeFunction(str,);
var bindings = fn([node,model]);
for(var key in bindings){
if(bindings.hasOwnProperty(key)){
var fn = $.bindingHandlers["text"]["update"];
var observable = bindings[key]
$.dependencyDetection.collect(observable);//绑定viewModel与UI
fn(node, observable)
}
}
},node);
return nodeBind
}
$.bindingHandlers = {}
$.bindingHandlers["text"] = {
'update': function (node, observable) {
var val = observable()
if("textContent" in node){
node.textContent = val;
}
}
}
window.onload = function(){
var model = new MyViewModel();
var node = document.getElementById("node");
$.applyBindings(model, node);
}
KO使用
1、ko绑定方式,立即执行用于需要后处理的一些数值
//点击事件
data-bind="click:$root.fun1.bind($param1,param2)"
//立即执行
data-bind="attr: { src : $root.fun2(param1,param2) }”
//缺省参数
data-bind="event: { mouseover: myFunction }"
<script type="text/javascript">
var viewModel = {
myFunction: function(data, event) {
if (event.shiftKey) {
//do something different when user has shift key down
} else {
//do normal action
}
}
};
ko.applyBindings(viewModel);
</script>
注意:在bind方式传递参数时,data和event两个参数依然被缺省传递。 新加入的参数,在使用时排在第一位,定义时只能排在$data后面
2、event事件
<input type="text" placeholder="输入关键字搜索" data-bind="event:{keyup:$root.fun1.bind($data,$element)}">
3、
self.weeklyRecommend(this); //监控对象整体发生变化时响应
self.weeklyRecommend(ko.mapping.fromJs(this)); //可以监控对象下每个元素的改变
4、ko事件注册
ko.bindingHandlers.singleExamHover = {
init: function(element, valueAccessor){
$(element).hover(
function(){
//todo
},
function(){
//todo
}
);
},
update:function(element, valueAccessor){
var _value = ko.unwrap(valueAccessor());
if(_value){
$(element).addClass("current");
}else{
$(element).removeClass("current");
}
}
};
<div class="h-set-homework" data-bind="singleExamHover:question.checked”>
5、事件冒泡
By default, Knockout will allow the click event to continue to bubble up to any higher level event handlers。
If necessary, you can prevent the event from bubbling by including an additional binding that is named clickBubble and passing false to it
<div data-bind="click: myDivHandler">
<button data-bind="click: myButtonHandler, clickBubble: false">
Click me
</button>
</div>
Normally, in this case myButtonHandler would be called first, then the click event would bubble up to myDivHandler. However, the clickBubble binding that we added with a value of false prevents the event from making it past myButtonHandler.
6、$data
$data and $root are equivalent. Inside a nested binding context, this parameter will be set to the current data item (e.g., inside a with: person binding, $data will be set to person). $data is useful when you want to reference the viewmodel itself, rather than a property on the viewmodel.<div data-bind="click:changeEditor.bind($data,$element,param1,param2)"></div>
<script>
changeEditor : function(ele,param1,param2){
console.log(this)
console.log(ele==event.currenttarget)
}
</script>
Knockout双向绑定的更多相关文章
- Knockout 双向绑定的理解
今天做了个需求就是上传图片,然后在代码中通过jQuery给一个标签赋值,经过前台的debug,发现这个值赋值成功了,但是提交到后台的请求里就没了,然后经历了一顿度娘,结果中发现了问题. 既然knock ...
- ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定
本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...
- 前端MVVM框架avalon揭秘 - 双向绑定原理
avalon大家可能不熟悉,但是Knockout估计或多或少听过用过,那么说说KO的几个概念 监控属性(Observables)和依赖跟踪(Dependency tracking) 声明式绑定(Dec ...
- 数据的双向绑定 Angular JS
接触AngularJS许了,时常问自己一些问题,如果是我实现它,会在哪些方面选择跟它相同的道路,哪些方面不同.为此,记录了一些思考,给自己回顾,也供他人参考. 初步大致有以下几个方面: 数据双向绑定 ...
- vue.js初级入门之最基础的双向绑定操作
首先在页面引入vue.js以及其他需要用到的或者可能要用到的插件(这里我多引用了bootstrap和jquery) 引用的时候需要注意文件的路径,准备工作这样基本就完成了,下面正式开始入门. vue. ...
- RAC textView的双向绑定
今天在写关于textView的数据绑定时原先写法是这样的: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #78 ...
- AnjularJS系列3 —— 数据的双向绑定
第三篇,双向的数据绑定 数据绑定是AnguarJS的特性之一,避免书写大量的初始代码从而节约开发时间 数据绑定指令提供了你的Model投射到view的方法.这些投射可以无缝的,毫不影响的应用到web应 ...
- 我的angularjs源码学习之旅3——脏检测与数据双向绑定
前言 为了后面描述方便,我们将保存模块的对象modules叫做模块缓存.我们跟踪的例子如下 <div ng-app="myApp" ng-controller='myCtrl ...
- Angularjs 双向绑定机制解析
文章转自:http://www.2cto.com/kf/201408/327594.html AngularJs 的元素与模型双向绑定依赖于循环检测它们之间的值,这种做法叫做脏检测,这几天研究了一下其 ...
随机推荐
- HostsConfig文件修改器
Hosts文件修改器 HostsConfig v1.1 免费版 最近工作需要,经常需要更换各种域名的内外网配置,频繁的修改HOSTS文件,很多的时间都用在的修改HOSTS文件上,工作效率大大降低,课余 ...
- 第96天:CSS3 背景详解
一.背景大小 background: url("images/bg.jpg") no-repeat;控制背景的大小1.具体数值background-size: 500px 500p ...
- 题解 P1781 【宇宙总统】
小金羊发现用的方法和python大佬们的方法还是不一样... (大概是我太弱了qAq) emmm... (Mode:Python 3)Code: a=int(input()) #几个数 L=list( ...
- Django路由分发
1. 先自己手动在项目APP01以及APP02下面各有一个urls.py.当请求来了的时候,先到工程中的urls找路由分发,然后再转到各个App中. 现在总共有3个url 2. 工程中的urls如下: ...
- oracle 如何查看pga
进去命令行 输入 sqlplus username/password@dbname 回车 进入数据库输入 show parameter pga 回车
- tmp_table_size ---> 优化 MYSQL 经验总结
数据库连接突然增多到1000的问题 查看了一下,未有LOCK操作语句. 但是明显有好多copy to tmp table的SQL语句,这条语读的时间比较长,且这个表会被加读锁,相关表的update语句 ...
- 【转载 save】vim键位图。
留图,备用,copy from 网络
- 【bzoj1029】【JSOI2007】建筑抢修
1029: [JSOI2007]建筑抢修 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 6417 Solved: 2883[Submit][Statu ...
- python基础----多态与多态性、super函数用法、继承原理
一.多态与多态性 ㈠多态: 多态指的是一类事物有多种形态, ...
- stout代码分析之零
最近在使用mesos做高可用设计,在编译的过程中注意到mesos依赖stout,一个仅仅含有头文件的c++基础库.stout代码简洁,设计优雅,值得一读. stout从内容上可细分为以下几块: Pri ...