简体   繁体   English

Knockout.js 使用 foreach 和 $index 与 if 绑定

[英]Knockout.js using foreach and $index with if binding

I'm trying to display the elements from an iterated list grouped inside divs 3 by 3. I've used the value of $index but I can't figure out why is not looking right.我正在尝试显示迭代列表中的元素,该列表按 3 列分组在 div 内。我使用了$index的值,但我不知道为什么看起来不正确。

<div class="row" data-bind="foreach: displaySel">
     <div class="col-md-2">
          <!--ko if: $index() % 3 === 0-->
          <div data-bind="attr:{id: 'div_'+$index()}">
          <!--/ko -->
               <div data-bind="attr:{id: 'g_'+$data.hId}" style="position:relative;">
                    <div>other things here</div>
               </div>
          <!--ko if: ($index() % 3 === 2 || $index() === displaySel.length - 1)-->
          </div>
          <!--/ko -->
    </div>
</div>

The first div should open before the first element info and close after the third.第一个 div 应该在第一个元素信息之前打开并在第三个元素信息之后关闭。 The second div will open before the fourth and close after another three and so on till the list ends.第二个 div 将在第四个之前打开并在另外三个之后关闭,依此类推,直到列表结束。 What's the best approach here?这里最好的方法是什么?

You cannot (or should not, I forget) really use Knockout in an imperative way like that, where you manually do or do not generate opening/closing tags.您不能(或不应该,我忘记了)真正以这样的命令方式使用 Knockout,您可以手动生成或不生成打开/关闭标签。 Instead, you need to nest things properly.相反,您需要正确地嵌套事物。

Put differently, treat <:-- ko if. ... -->换句话说,对待<:-- ko if. ... --> <:-- ko if. ... --> and <!-- /ko --> as proper close/end tags that always need to wrap around full elements. <:-- ko if. ... --><!-- /ko -->作为正确的关闭/结束标签,总是需要环绕整个元素。

Put even differently, you're trying to do the equivalent of this:甚至不同的是,您正在尝试执行与此等效的操作:

<div>
  Some content
  <strong>
    <div>
  </strong>

      CONTENT

  <strong>
    </div>
  </strong>
</p>

Perhaps Knockout should've given you an error, but (I guess in the spirit of HTML) it tries to make the best of it.也许 Knockout 应该给你一个错误,但是(我猜本着 HTML 的精神)它试图充分利用它。

So instead, you should do the "grouping" logic in your view model.因此,您应该在视图 model 中执行“分组”逻辑。 Added benefit is that you could potentially unit test it too.额外的好处是您也可以对其进行单元测试。 Here's an example:这是一个例子:

 const chunkSize = 3; class RootVm { displaySel = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]; displaySelGroups = ko.computed(() => // Chunk in groups of 3 based on: // https://stackoverflow.com/a/44687374/419956 [...Array(Math.ceil(this.displaySel.length / chunkSize))].map(_ => this.displaySel.splice(0,chunkSize)) ); } ko.applyBindings(new RootVm());
 .col-2 { background: silver; border: 1px solid black; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css" integrity="sha512-P5MgMn1jBN01asBgU0z60Qk4QxiXo86+wlFahKrsQf37c9cro517WzVSPPV1tDKzhku2iJ2FVgL67wG03SGnNA==" crossorigin="anonymous" /> <div class="row" data-bind="foreach: displaySelGroups"> <div class="col-2" data-bind="foreach: $data"> <div data-bind="attr:{id: 'div_'+$index()}"> <div data-bind="attr:{id: 'g_'+$data.hId}" style="position:relative;"> <div data-bind="text: $data"></div> </div> </div> </div> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM