将knockoutjs连接到已填充的DOM元素

时间:2011-09-05 06:49:48

标签: knockout.js

我正在处理一个页面,该页面是我想要使用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。

2 个答案:

答案 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);
    }
};