【问题标题】:knockout.js 3.3 - rerendering component in foreach bindingknockout.js 3.3 - 在 foreach 绑定中重新渲染组件
【发布时间】:2015-10-05 23:33:24
【问题描述】:

我的 viewModel 由带有可观察元素的可观察数组组成。

// viewmodel
var viewModel = function () {
    this.o = ko.observableArray();
    for (var i = 0; i < 3; i++)
    this.o.push(ko.observable(0));
};

我需要更改这些元素的值。为此,我创建了组件。简单的例子如下:

//custom element <component>
ko.components.register("component", {
    viewModel: function (params) {
        var self = this;
        this.value = params.value;
        console.log("init component");
        this.i = 1;
        this.change = function () {
            self.value(self.i++);
            console.log("change to " + self.value());
        }
    },
    template: "<span data-bind='text: value'></span>  <button data-bind='click:change'>Change</button>"
});

这个组件可以改变 params.value 中的 observable 元素的值。

我的看法很简单:

<!--ko foreach:o-->
       <component params="value: $rawData"></component>
<!--/ko-->

完整示例:http://jsfiddle.net/tselofan/xg16u5cg/7/ 问题是当可观察数组中可观察元素的值发生变化时,组件会再次呈现,因为它位于 foreach 绑定内部。您可以在日志中看到这一点。在这种情况下我可以使用什么最佳实践?谢谢

【问题讨论】:

    标签: javascript knockout.js custom-component knockout-3.0


    【解决方案1】:

    Knockout-Repeat (https://github.com/mbest/knockout-repeat) 是一种迭代绑定,它不会创建新的绑定上下文,并且具有 foreach 模式,因此它应该可以与您的组件一样工作。

    【讨论】:

    • 小心这种狂欢。 1.它提供了伪可观察的$item上下文变量,它不是ko.subscribable。 2. 当您从可观察数组中删除元素时,它使用重新生成标记的奇怪算法:据我了解,首先它删除第一个 DOM 节点(不管已删除元素的索引),然后更新剩余 DOM 节点的 ko 上下文。由于某些原因(可能是因为伪可订阅上下文),我的组件无法处理此算法。谢谢你的回答。
    【解决方案2】:

    每次数字更改时都会重新创建组件,因为组件的上下文数字。

    http://jsfiddle.net/Crimson/xg16u5cg/8/

    <!-- ko foreach: o -->
        <component params="value: $data.myNumber"></component>
    <!-- /ko -->
    
    //Test how components work in foreach binding
    //custom element <component>
    ko.components.register("component", {
        viewModel: function (params) {
            var self = this;
            this.value = params.value;
            console.log("init component");
            this.i = 1;
            this.change = function () {
                self.value(self.i++);
                console.log("change to " + self.value());
            }
        },
        template: "<span data-bind='text: value'></span>  <button data-bind='click:change'>Change</button>"
    });
    
    
    // viewmodel
    var viewModel = function () {
        this.o = ko.observableArray();
        for (var i = 0; i < 3; i++)
            this.o.push({myNumber: ko.observable(0)});
    };
    
    ko.applyBindings(new viewModel());
    

    【讨论】:

    • 作为替代方案,您仍然可以传入简单值,但在 init 中创建一个新的组件视图模型值作为可观察的值。 jsfiddle.net/xg16u5cg/9
    • 任何避免直接改变组件上下文的解决方案都可以。
    • 感谢您的回复! CrimsonChris,您的解决方案迫使我更改域模型。我想避免它。 @Roy J,更改组件内部的 observable 不会强制更改数组中的 observable 元素。见jsfiddle.net/tselofan/xg16u5cg/10。尽管上下文发生了变化,但我的代码适用于 foreach 绑定之外的可观察元素。见jsfiddle.net/tselofan/xg16u5cg/12。这是因为 foreach 绑定聚合了模板绑定,它会在上下文更改时重新呈现内容。可能我可以停止重新渲染 foreach 模板的内容吗?谢谢。
    • @Tselofan 可能敲除重复 (github.com/mbest/knockout-repeat) 会为您工作。
    • 您可以从组件中删除状态。那么你就不必关心 Knockout 是否重拍它。 jsfiddle.net/Crimson/xg16u5cg/16
    猜你喜欢
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-08-25
    • 2019-06-01
    • 2021-06-07
    • 2018-08-12
    • 2021-04-07
    相关资源
    最近更新 更多