knockout.js的if绑定可以用来移除元素吗?

3
假设我有以下HTML代码片段:
<div class="group-of-things">
     <span>thing #1</span>
     <span>thing #2</span>
     <span data-bind="if: showThing3">thing #3</span>
</div>

现在假设我有一个CSS,可以将 group-of-things 的最后一个子元素的角落变圆:

.group-of-things > *:last-child { border-radius: 0 5px 5px 0 }

问题在于当showThing3变为false时,thing #3被隐藏(内容被删除),但是包含(第三个)span仍然留在DOM中,结果thing #2没有圆角。

可以通过使用无容器绑定(<!-- ko if: showThing3 -->)来解决此问题,但我想避免使用无容器绑定,因为注释被管道剥离了,我无法控制。

也许可以调整CSS规则以仅考虑可见的子元素(例如,我可以使用css绑定在隐藏元素上添加hidden类)。

是否有更优雅的解决方案,可以实际将涉及的span从DOM中删除?
3个回答

3
为什么不使用可观察数组呢?
<div data-bind="foreach: things" class="group-of-things">
    <span data-bind="text: $data"></span>
</div>

<script>
    model.things = ko.observableArray(["thing #1", "thing #2", "thing #3"]);
    ... 
    model.things.remove( "thing #3" );

我为演示目的简化了代码。尽管如此,你的回答对我所问的问题是有效的。实际代码具有异构列表。 - THX-1138

1

回答 了一个类似的问题,建议使用 Knockout-Repeat binding,该绑定将应用于元素本身。在运行时,它会将元素包装在虚拟(基于注释的)元素中。

var vm = {
    showThing3: ko.observable(true)
};

ko.applyBindings(vm);

setTimeout(function () {
    vm.showThing3(false);
}, 2500);
.group-of-things > * { color: white; padding: 2px; background: blue; }
.group-of-things > *:last-child { border-radius: 0 5px 5px 0 }
<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>

<div class="group-of-things">
    <span>thing #1</span>
    <span>thing #2</span>
    <span data-bind="repeat: showThing3() && 1">thing #3</span>
</div>


这是一个很好的解决方案。我希望OOB的if能够做到这一点。我认为当前的if语义是违反直觉的,许多开发人员期望被if控制的元素是元素本身而不是元素的内容。 - THX-1138

0

一个可以删除附加元素的绑定不会很有用,因为它无法添加自己回来。通常,您可以通过使用无容器绑定来解决此问题。但是,如果这不是一个选项,你需要有点创造性。

  • 您可以尝试将模板存储为带有 browserify 的 JavaScript 字符串。然后可以使用readFileSync来进行操作。Knockout 甚至提供了example这种方法的示例。
  • 您可以创建一个自定义绑定,并将其放在组件 div 上。它将手动添加/删除"thing #3" span。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接