knockout.js的学习笔记3

上一节主要是说viewModel各个域中相互通知,本节开始介绍viewModel与节点的相互通知。

我们在body上添加如下HTML片断:

The name is < span data-bind = "text: fullName" id = "node" ></ span >

然后将第一节提到的$.applyBindings疯狂删减到这样:

$.applyBindings = function (model, node){
     var str = node.getAttribute( "data-bind" );
     str = "{" +str+ "}"
     var bindings = eval( "0," +str);
     for ( var key in bindings){ //如果直接eval肯定会报错,因为它找到fullName
         console.log(key)
     }
}
window.onload = function (){
     var model = new MyViewModel();
     var node = document.getElementById( "node" );
     $.applyBindings(model, node)
}

意料中的失败,因为fullName在window中找不到。knockoutjs里面有一个叫buildEvalWithinScopeFunction处理此问题:

$.buildEvalWithinScopeFunction =  function (expression, scopeLevels) {
      var functionBody = "return (" + expression + ")" ;
      for ( var i = 0; i < scopeLevels; i++) {
          functionBody = "with(sc[" + i + "]) { " + functionBody + " } " ;
      }
      return new Function( "sc" , functionBody);
  }

然后将applyBindings 改成这样:

$.applyBindings = function (model, node){
     var str = node.getAttribute( "data-bind" );
     str = "{" +str+ "}"
     var fn = $.buildEvalWithinScopeFunction(str,2);
     var bindings = fn([node,model])
     console.log(bindings.text == model.fullName) //到这里我们就把viewModel与节点关联起来了
}

在data-bind定义两个东西,一个是viewModel中的域,另一个是对应的操作,在这里是text!在knockout中有一个叫ko.bindingHandlers的对象,里面储放着各种操作,格式如下:

init可以猜测是用于第一次绑定元素时调用的,update是每次viewModel调用的。

现在我们是玩玩,不用大动干戈。

到这里,我们就可以把Planet Earth正确地显示在span中,但当viewModel中的FullName发生改变时,span并没有发生改变,缘由是我们没有把它们绑在一起。很简单,我们把$.applyBindings里面的逻辑都整进一个$.computed 中就行了。

大家可以下载回来看看效果:点我

 
 
标签:  knockoutjs

你可能感兴趣的:(KnockoutJS)