【问题标题】:Knockout recursive template selective binding淘汰递归模板选择性绑定
【发布时间】:2013-04-19 23:14:40
【问题描述】:

在这个例子中,我有一个嵌套模板来显示类似缩进输出的树视图,但是在叶节点上呈现的 HTML 不是我所期望的。如何让叶子节点呈现预期的 html 并且不包含子容器 div?

如果我将 if 绑定放在模板绑定之外,我会收到一个 javascript 错误:

Uncaught Error: Multiple bindings (if and template) are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.

注意:使用 if 绑定注释 <!-- ko if: children().length > 0 --> 确实可以删除不需要的元素,但生成的 html 中充满了 cmets,我希望保持干净,因为我可能有数百个叶节点。

我尝试使用 2 个模板,一个带容器,一个不带容器,并为名称设置条件,但模板始终呈现 nodeTempl:data-bind="template: { name: (children().length > 0) ? 'nodeTempl' : 'leafTempl', foreach: children }"

我想我真的想根据当前正在处理的孩子的状态应用不同的模板。

一个叶子节点是这样渲染的

<div>
    <div data-bind="text: name">Node 1-1-1</div>            
    <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
</div>

但我希望它呈现如下:

<div>
    <div data-bind="text: name">Node 1-1-1</div>            
</div>

设置如下:

HTML

<style type="text/css">
    .indent-1 {
        margin-left: 20px;
    }
</style>

<script id="nodeTempl" type="text/html">
    <div>
        <div data-bind="text: name"></div>            
        <div class="indent-1" data-bind="template: {if: children().length > 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>
</script>

<div data-bind="template: { name: 'nodeTempl', foreach: children }"></div>    

脚本

var node = function (config) {
    var self = this;
    self.name = ko.observable(config.name);
    self.children = ko.observableArray([]);
    if ($.isArray(config.children)) {
        for (var i = 0; i < config.children.length; i++) {
            self.children.push(new node(config.children[i]));
        }
    }
};

ko.applyBindings(new node(
    {
        name: 'root',
        children: [
            { name: 'Node1', children: [{name: 'Node 1-1', children: [{name: 'Node 1-1-1'}]},{name: 'Node 1-2'}]},
            {name: 'Node2',children: [{name: 'Node 2-1'},{name: 'Node 2-2'}]},
            {name: 'Node3'},
        ]
    }
    ));

输出

<div data-bind="template: { name: 'nodeTempl', foreach: children }">
    <div>
        <div data-bind="text: name">Node1</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }">
    <div>
        <div data-bind="text: name">Node 1-1</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }">
    <div>
        <div data-bind="text: name">Node 1-1-1</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>
</div>
    </div>

    <div>
        <div data-bind="text: name">Node 1-2</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>
</div>
    </div>

    <div>
        <div data-bind="text: name">Node2</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }">
    <div>
        <div data-bind="text: name">Node 2-1</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>

    <div>
        <div data-bind="text: name">Node 2-2</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>
</div>
    </div>

    <div>
        <div data-bind="text: name">Node3</div>            
        <div class="indent-1" data-bind="template: {if: children().length &gt; 0,  name: 'nodeTempl', foreach: children }"></div>
    </div>
</div>

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    您在正确的轨道上建议您需要两个模板。模板name参数可以是返回数组中每一项的模板名称的函数。

    你可以像这样创建一个函数:

    function nodeTemplate(node) {
        return node.children().length > 0 ? 'nodeTempl' : 'nodeLeafTempl';
    }
    

    然后改变你的观点:

    <script id="nodeTempl" type="text/html">
        <div>
            <div data-bind="text: name"></div>            
            <div class="indent-1" data-bind="template: {name: nodeTemplate, foreach: children }"></div>
        </div>
    </script>
    
    <script id="nodeLeafTempl" type="text/html">
        <div>
            <div data-bind="text: name"></div>            
        </div>
    </script>
    
    <div data-bind="template: { name: nodeTemplate, foreach: children }"></div> 
    

    【讨论】:

      猜你喜欢
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      • 2018-08-06
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多