我正在处理一个页面,该页面是我想要使用KnockoutJS的ASP.NET MVC3应用程序中的服务器。
在View上我传递了一个填充模型(我正在转换为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。
任何人都试过这个/知道我应该做些什么来支持这种情况,或者它与你能做什么/应该做的太远了?
此外,我不希望为服务器生成的HTML提供单独的DOM元素而不是Knockout HTML。
答案 0 :(得分:8)
我想我明白你的问题是什么。您希望最初为非js用户填充标记,并在绑定到KO时简单地覆盖它。
对于像文本这样的简单绑定,这不是一个问题,只需在服务器的标记中包含data-bind属性,或者在运行时包含,然后就可以了。对于模板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);
}
};
希望这有帮助。
答案 1 :(得分: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);
}
};