2011-09-05 59 views
9

我工作这正从我希望在使用KnockoutJS一个ASP.NET MVC3应用程序服务器的网页上。连接knockoutjs到一个已经填充的DOM元素

在查看我获得通过一(我正在转换为KnockoutJS viewModel),我想构建一些DOM服务器端。这似乎是合乎逻辑的,因为我已经有对象来生成最初的HTML,并且它将为用户提供更好的体验,因为这不会是页面加载和DOM群体之间的延迟(这也意味着我具有非基本功能-JavaScript客户端)。

之后做一些研究,我假设我需要创建一个自定义bindingHandler所以我创造了这个:

ko.bindingHandlers.serverForEach = { 
    init: function() { /* no-op */ }, 
    update: function() { 
     //call off to the built in loop handler 
    } 
}; 

所以我的想法是,我创建了一个处理程序,其无助于init阶段(如DOM已经被填充)并且在update阶段我只需插入新值。我想利用内置的模板,所以这也可以是一个通用的解决方案。

问题是,在这种情况下,一切都崩溃了。如果init什么都不做,那么update会失败,因为作为最后一个参数出现的bindingContext看起来是错误的,并且如果包含init,它将销毁现有的HTML。

任何人都试过/知道我应该怎么做才能支持这种情况,或者它离你能/应该做的事情太远了吗?

此外,我不希望有一个单独的DOM元素为服务器生成的HTML比Knockout HTML。

回答

8

我想我明白你的问题是什么。您希望最初为非js用户填充标记,并在绑定到KO时简单覆盖它。

对于像文本这样的简单绑定,这不是一个问题,只需将数据绑定属性包含在服务器的标记中,或者在运行时包含数据绑定属性即可。对于模板foreach来说,绑定的东西有点难度,因为绑定时会附加值。

Here is a jsfiddle描述上述情况并演示下面的解决方案。这有点基本,但应该让你开始。

其基本思路是清除init中的元素,然后将其余部分委托给现有的模板绑定。

ko.bindingHandlers.serverForEach = { 
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     // clear the list first 
     $(element).children().remove(); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) { 
     ko.bindingHandlers['template'].update(element, valueAccessor, allBindingsAccessor, viewModel); 
    } 
}; 

希望这会有所帮助。

2

如果有人需要这个为knockout.js工作2.0+(注意更新bindingContext

ko.bindingHandlers.serverForEach = { 
init: function(element, valueAccessor) { 
     $(element).children().remove(); 
     return ko.bindingHandlers.template.init(element, valueAccessor); 
    }, 
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { 
     return ko.bindingHandlers.template.update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext); 
    } 
}; 
相关问题