这可以使用 jQuery 来解析服务器生成的列表,然后填充 KO observableArray,然后调用 applyBindings,它将服务器列表替换为 KO 绑定列表。
http://jsfiddle.net/dLbc4/1/
更多信息
正如上面的评论者所指出的,这不是纯粹的 KO 做事方式。但是,一些 JS 框架现在会在服务器上预渲染初始内容,然后在页面显示给用户后应用它们的绑定。原因包括:
- 性能 - 立即显示完整的页面
- SEO - 一个完整的 HTML 文档可供搜索引擎使用
- 旧版浏览器/移动设备支持 - 这些设备可以使用预构建的 HTML 页面,尽管对它的作用不大
执行此操作的框架示例:
这些允许使用相同代码库的页面的服务器呈现版本;即,相同的逻辑用于在服务器和客户端上创建 HTML。
KO可以做到吗?我不明白为什么不这样做,也许这里有一个有趣的项目可以做到这一点(或者有人已经知道一个项目了吗?)。同一个服务器端数据库可以通过 API 提供静态 HTML 页面和实际数据,以便 KO 稍后呈现。最大的挑战是单一的代码库问题,否则你最终会在服务器上渲染 HTML 的服务器端逻辑(用 PHP 或 Python 或其他),然后在客户端通过 KO 的 JavaScript 逻辑渲染 HTML。
这里是一个快速的小提琴,展示了原始问题中 HTML 的概念:
http://jsfiddle.net/dLbc4/1/
在这个概念中,除了由服务器预渲染的实际数据之外,您在服务器 HTML 中添加所有 KO 绑定。为了演示这一点,我添加了一个向列表添加新元素的简单示例。除了 'text: $data' 绑定之外,所有的 KO 语句都在那里。
<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>
所以页面是“完整的”——非常适合 SEO、性能等。现在我们需要一些代码来提取数据值并将它们添加到视图模型中。这是我的虚拟机——它处理元素列表和水果列表,只是为了演示一些步骤来使这个通用而不是完全硬编码为只支持一个称为“元素”的结构:
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();
}
最后,这是用绑定到 VM 的 KO 渲染内容替换来自服务器的静态 HTML 的代码。您可以检查它是否有效,因为小提琴中的“添加”按钮将分别添加新元素或新水果。代码有点通用,因为相同的代码处理元素列表和水果列表。但是,您可以看到它假定您的列表子元素将始终是一个 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();
});