将现有DOM元素绑定到视图模型

时间:2014-08-01 14:06:55

标签: knockout.js

我想使用knockoutjs显示数组中的数据,我可以使用这样的foreach绑定来实现:

<ul data-bind="foreach: elements">
    <li data-bind="text: data1"></li>
    <li data-bind="text: data2"></li>
    <li data-bind="text: data3"></li>
</ul>

这样可以正常工作,但问题是它只能在页面完全加载后完成,我不喜欢这样,因为我可以在服务器上构建初始列表,这样它就可以加载数据方式快点。我会从服务器那里得到这样的东西:

<ul>
    <li>Data1 value</li>
    <li>Data2 value</li>
    <li>Data3 value</li>
</ul>

是否可以将这些列表元素绑定到视图模型数组?

2 个答案:

答案 0 :(得分:4)

这可以使用jQuery来解析服务器生成的列表,然后填充KO observableArray,然后调用applyBindings,它将服务器列表替换为KO绑定列表。

http://jsfiddle.net/dLbc4/1/


更多信息

正如上述评论者指出的那样,这不是纯粹的KO做事方式。但是,一些JS框架现在会预先渲染服务器上的初始内容,然后在页面显示给用户后应用它们的绑定。原因包括:

  • 效果 - 立即显示完整构建的页面
  • SEO - 一个完全构建的HTML文档可用于搜索引擎
  • 旧的浏览器/移动支持 - 这些设备可以使用预建的HTML页面,虽然没有做太多的事情

执行此操作的框架示例:

这些允许使用相同代码库的页面的服务器呈现版本;即,使用相同的逻辑在服务器和客户端上创建HTML。

这可能与KO有关吗?我不知道为什么不这样做,或许这里有一个有趣的项目(或者有人知道某个项目吗?)。相同的服务器端数据库可以通过API提供静态HTML页面和实际数据,以便稍后呈现KO。最大的挑战是单个代码库问题,否则你最终会在服务器上呈现HTML的服务器端逻辑(用PHP或Python等),然后JavaScript逻辑通过客户端上的KO呈现HTML。

这是一个快速的小提示,显示了原始问题中HTML的实际概念:

http://jsfiddle.net/dLbc4/1/

在此概念中,您将在服务器HTML中添加所有KO绑定,而不是服务器预先呈现的实际数据。为了演示这个,我添加了一个向列表中添加新元素的简单示例。除了&text文本之外,所有的KO声明都在那里:$ data&#39;结合。

<ul class="preload" data-bind="foreach: elements">
    <li>Data1 value</li>
    <li>Data2 value</li>
    <li>Data3 value</li>
</ul>

<input type="text" name="new" data-bind="value: new_element">
<button data-bind="click: add_element">add</button>

因此页面已完成&#39; - SEO,性能等的理想选择。现在我们需要一些代码来提取数据值并将它们添加到视图模型中。这是我的VM - 它处理元素列表以及水果列表,只是为了展示一些步骤,使这个通用而不是完全硬编码,只支持一个名为&#39; elements&#39; :

AppViewModel = function() {
    // 'Elements' list suport
    this.elements = ko.observableArray();
    this.add_element = function(data, event) {
        this.elements.push(this.new_element());
    }
    this.new_element = ko.observable();

    // 'Fruits' list support
    this.fruits = ko.observableArray();
    this.add_fruit = function(data, event) {
        this.fruits.push(this.new_fruit());
    }
    this.new_fruit = ko.observable();
}

最后,这里是使用KO呈现的内容替换服务器上的静态HTML的代码,该内容绑定到VM。您可以检查它是否有效,因为“添加”#39;小提琴中的按钮将分别添加新元素或新水果。代码略显通用,因为相同的代码处理元素列表和水果列表。但是,您可以看到它假设您的list子元素始终是li - 所以需要一些工作!

initKO = function() {
    // Start with an empty view model
    var app_vm = new AppViewModel();

    // Handle any list tagged with class="preload"
    $(".preload").each(function(i, el) {
        // Extract the data from the HTML and populate the view model
        var array_name = $(el).attr("data-bind").split(":")[1].trim();
        $(el).children().each(function(j, child) {
            app_vm[array_name].push($(child).text());    
        });

        // Empty the prebuilt static HTML
        $(el).empty();

        // Add a new node for binding
        $(el).append($("<li data-bind='text: $data'></li>"));
    });

    // Call applyBindings to rebuild the HTML via KO
    ko.applyBindings(app_vm);
}

// Do all this after document.ready. The page initially appears with the 
// server-provided static HTML. We then replace this HTML with a KO-rendered
// DOM.
$(document).ready(function() {
    initKO();
});

答案 1 :(得分:0)

查看Erik Schierboom的解决方案:https://github.com/ErikSchierboom/knockout-pre-rendered。它基本上可以满足您的需求

相关问题