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

发布于 2024-12-02 17:04:03 字数 842 浏览 0 评论 0原文

我正在开发一个页面,该页面是 ASP.NET MVC3 应用程序的服务器,我想在其中使用 KnockoutJS。

在视图上,我传递了一个填充模型(我将其转换为 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 已经填充)并且在更新阶段我将插入新值。我想利用内置模板,因此这也可以成为通用解决方案。

问题是在这种情况下一切都会崩溃。如果 init 不执行任何操作,则 update 会失败,因为最后一个参数传入的 bindingContext 似乎是错误的,并且如果我包含 init,它将破坏现有的 HTML。

有人尝试过这个/知道我应该做什么来支持这种情况,还是它与你可以/应该做的事情相去甚远?

另外,我不想为服务器生成的 HTML 使用与 Knockout HTML 不同的单独 DOM 元素。

I'm working on a page which is being server from an ASP.NET MVC3 app that I want to use KnockoutJS in.

On the View I'm getting passed a populated Model (which I'm converting to a KnockoutJS viewModel) and I want to build up some of the DOM server-side. This seems logical since I already have the objects there to generate the initial HTML and it'll provide a better experience to the users as there wont be a delay between the page load and the DOM population (it also means I have basic functionality for non-JavaScript clients).

After doing some research I'm assuming I need to create a custom bindingHandler so I created this:

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

So my thinking was that I create a handler which does nothing in the init phase (as the DOM is already populated) and in the update phase I'll just insert the new value. I'd like to leverage the built-in templating so this can be a generic solution as well.

The problem is that everything falls apart in this scenario. If the init does nothing then the update fails as the bindingContext that comes in as the last argument seems wrong, and if I include the init it'll destroy the existing HTML.

Anyone tried this/ know what I should do to support this scenario or is it just too far removed from what you can/ should do?

Also, I don't want to have a separate DOM element for the server generated HTML than the Knockout HTML.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沒落の蓅哖 2024-12-09 17:04:03

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

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

这里有一个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);
    }
};

希望这有帮助。

I think I understand what your problem is. You are wanting to populate the markup initially for non-js users and simply overwrite it when binding to KO.

For simple bindings like text this is not an issue simply include the data-bind attribute in the markup from the server or include at runtime and away you go. For the template foreach binding things are a little more difficult since it will append values when bound.

Here is a jsfiddle that describes the above scenario and demonstrates the solution below. It's a little basic but should get you started.

The basic idea is to clear the element on init and then delegate the rest to the existing template binding.

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

Hope this helps.

琴流音 2024-12-09 17:04:03

如果有人需要这个来为 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);
    }
};

In case anyone needs this to work for knockout.js 2.0+ (note the bindingContext in update)

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);
    }
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文