【问题标题】:Can I do branching/decisions with knockout.js我可以使用 knockout.js 进行分支/决策吗
【发布时间】:2012-10-07 21:10:25
【问题描述】:

我有一些旧代码,我想看看是否可以使用 knockout.js。

    var secs = 960 + Math.floor(data.length / 6) * 1060 + 10;
    $("#metro-scrollbar").css("width", secs.toString() + 'px');
    var group_count = 0;
    section = ""
    for (i = 0; i < data.length; i++) {
        if (i % 6 == 0)
            section += "<section class=\"" + (data.length - i <= 6 ? "last" : "") + "\"><h2 class=\"section-title\">Group " + ++group_count  + "</h2>";

        section += "<a href=\"/TheoryTests/Test/" + data[i].Id + "/" + data[i].Title.replace(/ /g,'-') + "\">";
        section += "<div class=\"metro-tile double" + (i % 3 == 2 ? " last" : "") + "\"><div class=\"a1x2\"></div><div class=\"live-tile metrogreen\">";

        section += "<span class=\"tile-title\">" + data[i].Title + "</span>";
        section += "<div class=\"dark\"><div class=\"TheoryTestTile\"><p>Helo</p></div></div>";

        section += "</div></div></a>";
        if (i % 6 == 5)
          section += "</section>";
    }

javascript 生成了一组带有一些嵌套 div 的部分。每 6 个 div 它创建一个新部分。我了解如何使用 knockout.js 进行数据绑定

data-bind="foreach: test, visible: tests().length > 0" 但是如果(i%6 == 0)我该如何做决策

更新

<div id="metro-grid">
    <div id="metro-scrollbar" data-bind="foreach: tests, visible: tests().length > 0">
        <!-- ko if: $index() % 6 == 0 -->
        <section data-bind ="css: { 'last' : $parent.isLastSection($index)}," >
        <!-- /ko -->
            <div class="metro-tile double " data-bind ="css: { 'last' : $parent.isLastTile($index)}">
            <div class="a1x2"></div><div class="live-tile metrogreen">
                <div ></div>
             </div>
                </div>
        <!-- ko if: $index() % 6 == 0 -->
        </section>
        <!-- /ko -->

    </div>
</div>

上面的问题是我仍然想在 section 中生成 div。 tests 是一个包含 12 个元素的列表。我想每第 6 个元素创建一个新部分。

更新 2

function TaskListViewModel() {
    // Data
    var self = this;
    self.tests = ko.observableArray([]);
    this.sections = [];

    self.isLastTile = function (i) {
           return i() % 3 == 2;
    };
    self.isLastSection = function (i) {

        return i() >= Math.floor(self.tests().length / 6);
    };

    this.createSections = ko.computed(function () {
        var tests = self.tests();
        current = [];
        sections.push(current);
        for (var i = 0; i < tests.length; i++) {
            current.push(tests[i]);
            if (((i+1) % 6) == 0) {
                current = [];
                sections.push(current);
            }
        }
    });


    $.getJSON(url, function (allData) {
        var mappedTasks = $.map(allData, function (item) { return new Task(item) });
        self.tests(mappedTasks);
        //var secs1 = self.tests().length / 6 * 960 + 960 + 10;
        var secs = 960 + Math.floor(self.tests().length / 6) * 1060 + 10;
        $("#metro-scrollbar").css("width", secs.toString() + 'px');

    });

}
ko.applyBindings(new TaskListViewModel());

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    您可以在foreach 上下文中使用$index 对象:

    <div data-bind="foreach: items">
        <span data-bind="visible: $index() % 6 == 0"></span>
    </div>
    

    阅读更多关于foreach绑定的信息:http://knockoutjs.com/documentation/foreach-binding.html

    编辑: 为了避免渲染:

      <div data-bind="foreach: items">
            <!-- ko if: $index() % 6 == 0-->
                <span data-bind="text: $data"></span>
            <!-- /ko -->
        </div>
    

    【讨论】:

    • 我的问题是这些部分不应该被隐藏,它们不需要被生成。
    • 我可以计算出有多少个部分并做两个循环。但是我该如何做一个 for n 循环,其中 n 是节数。
    【解决方案2】:

    我建议您将 2 个 ko.observables 添加到您的 viewModel。第一个是“sections”数组,第二个是 ko.computed,每次更新测试时都会重新填充“sections”,然后使用绑定循环遍历“sections”。

    这是一个小提琴示例:

    http://jsfiddle.net/Zholen/q57RX/

    var vm = function() {
      var self = this;
      this.tests = ko.observableArray([1,2,3,4,5,6,7,8,9,
                                     10,11,12,13,14,15,16]);
      this.sections = [];
    
      this.createSections = ko.computed(function(){
        var tests = self.tests();
        console.log(tests.length);
        for(var i = 0; i < tests.length; i++)
        {
            if(i%6 == 0)
                self.sections.push([]);
            self.sections[self.sections.length - 1].push(tests[i]);
        }
      });
    };
    
    <div>
        <div data-bind="foreach: sections">
            <section data-bind="foreach: $data">
                <div data-bind="text:$data">
                </div>
            </section>
        </div>
    </div>​
    

    【讨论】:

    • 当你回答时我刚刚完成了。猜猜这是唯一的方法。 ko.computed() 表示每次使用 createSections() 时都会创建?
    • ko.computed 将在函数中使用的任何 ko.observable 发生变化时被调用。请注意,在小提琴中,我实际上并没有在任何地方调用 createSections(),那是因为一旦我将值设置为“测试”,KO 就为我调用了 createSections。
    • 啊,没注意到。我做了绑定 foreach: createdSections 并在 createdSections 中有一个返回部分。我会改用你的方法
    • 我让它工作了,但是每次调用 createsections 时请注意,你添加到列表中。所以如果使用 ajax 获取数据,从初始化会有一个空白部分。
    【解决方案3】:

    Knockout.js 有一个“if”绑定:http://knockoutjs.com/documentation/if-binding.html

    【讨论】:

    • 并没有真正涵盖 OP 的问题,即如何根据序数位置有条件地显示某些内容。
    • 我添加了更多信息。我现在的问题是我的分组中的 div 没有生成。
    • 您可以将您的视图模型添加到问题中吗?
    猜你喜欢
    • 1970-01-01
    • 2023-04-10
    • 2015-09-04
    • 2020-04-07
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 2019-07-21
    • 2014-06-12
    相关资源
    最近更新 更多