Knockout.js绑定可以应用于容器标签和后代吗?

时间:2015-09-28 10:31:11

标签: javascript html knockout.js

让我用一个简单的案例来设置问题。

我有一个HTML表,其行由observableArray控制。它很棒。

如果observableArray中有零元素,我想要一行来说明。我试过这个标记,“有点”有效:

<tbody data-bind="if: $root.data.contacts().length == 0">
    <tr>
        <td>There are no contacts specified yet.</td>
    </tr>
</tbody>

<tbody data-bind="foreach: $root.data.contacts">
        SNIP - a tbody with the rows is here when elements > zero
</tbody>

当我说“有点”时,我的意思是可见的。它确实出现在零元素上并且确实在&gt;处消失了。零元素就像你期望的那样。但是,当您打开DOM检查器(开发工具)并查看内存中的DOM时,您会发现有两个 tbody 部分,而不是一个部分。现在一个 tbody 总是空的,但是两个 tbody 标签不是HTML5正确的,所以必须修复这不是所需的标记

作为Knockout新手,我尝试用虚拟元素解决这个问题:

<!-- ko if: $root.data.contacts().length == 0 -->
<tbody>
    <tr>
        <td>There are no contacts specified yet.</td>
    </tr>
</tbody>
<!-- /ko -->

不幸的是,这对我们的构建过程不起作用:我们在压缩之前缩小HTML并消除注释。

我的印象是KO绑定适用于CONTAINER ELEMENT ITSELF以及后代,但似乎并非如此。有没有办法告诉KO应用于容器元素以及子元素,还是我需要以某种方式更改标记而不是虚拟容器?

2 个答案:

答案 0 :(得分:2)

和你一样,我的第一选择是if绑定的虚拟标签。但由于这不是一个选项,可交换模板怎么样?

var vm = {
  contacts: ko.observableArray()
};

ko.applyBindings(vm);

setTimeout(function() {
  vm.contacts(['One', 'Two', 'Three']);
}, 2500);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<template id="empty-body">
  <tbody>
    <tr>
      <td>There are no contacts specified yet.</td>
    </tr>
  </tbody>
</template>
<template id="normal-body">
  <tbody data-bind="foreach: contacts">
    <tr>
      <td data-bind="text:$data"></td>
    </tr>
  </tbody>
</template>
<table data-bind="template: contacts().length === 0 ? 'empty-body' : 'normal-body'"></table>

答案 1 :(得分:0)

Knockout-Repeat binding将绑定应用于元素本身。它通过使用节点预处理器在运行时用虚拟(基于注释)元素中的repeat绑定包装元素来实现。

&#13;
&#13;
var vm = {
  contacts: ko.observableArray()
};

ko.applyBindings(vm);

setTimeout(function() {
  vm.contacts(['One', 'Two', 'Three']);
}, 2500);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="https://rawgit.com/mbest/knockout-repeat/master/knockout-repeat.js"></script>
<table>
  <tbody data-bind="repeat: !contacts().length && 1">
    <tr>
      <td>There are no contacts specified yet.</td>
    </tr>
  </tbody>
  <tbody data-bind="repeat: contacts().length && 1" data-repeat-bind="foreach: contacts">
    <tr>
      <td data-bind="text:$data"></td>
    </tr>
  </tbody>
</table>
&#13;
&#13;
&#13;