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
原文地址:https://www.cnblogs.com/Leo_wl/p/2554967.html