javascript - KnockoutJS 正在更新数组中的所有对象,而不仅仅是一个

标签 javascript knockout.js

所以这有点复杂。我会尽我所能在这里解释它,但是已经设置了一个 Fiddle 来演示这个问题......你可以找到它 here

我首先创建了一个 Javascript 数据传输对象,它不仅仅是一个简单的 DTO,因为它试图合并 KO 映射功能,以便可以使用“GetKnockout()”方法将 DTO 的内容作为 KO 对象检索.它存储 KO 对象以及用于在私有(private)属性(_lotKO、_origData)中内部初始化属性的对象。

var LotDTO = function (data) {

    //#region Public Properties
    var name            = (data != null) ? data.Name : null;
    var desc            = (data != null) ? data.Description : null;
    var model           = (data != null) ? data.Model : null;
    var buildStage      = (data != null) ? data.BuildStage : null;
    var softwareVersion = (data != null) ? data.SoftwareVersion : null;
    var config          = (data != null) ? data.Configuration : new Array();
    var serialNumbers   = (data != null) ? data.SerialNumbers : new Array();
    //#endregion 

    //#region Private Properties
    var _lotKO = null;
    var _origData = data;
    //#endregion

    //#region Public Methods
    var GetKnockout = function () {
        /// <summary>
        /// Returns a knockout object that can be used to bind to UI elements. It is important to remeber that the values in the knockout object do NOT sync up with the LotDTO values.
        /// </summary>
        /// 
        var self = this;
        if (_lotKO == null) {
            SetKnockout(self);
        }

        return _lotKO;
    }

    var Reset = function () {
        /// <summary>Reverts all the object properties back to their original values</summary>
        /// 
        var self = this;
        name            = (_origData != null) ? _origData.Name : null;
        desc            = (_origData != null) ? _origData.Description : null;
        model           = (_origData != null) ? _origData.Model : null;
        buildStage      = (_origData != null) ? _origData.BuildStage : null;
        softwareVersion = (_origData != null) ? _origData.SoftwareVersion : null;
        config          = (_origData != null) ? _origData.Configuration : new Array();
        serialNumbers   = (_origData != null) ? _origData.BrewerSerialNumbers : new Array();
        //
        // If the KO object has already been defined the reset it's definitions
        if (_lotKO != null) {
              //alert("resetting knockout");
            SetKnockout(self);
        }
    }
    //#endregion

    //#region Private Methods
    function SetKnockout(self) {

        _lotKO = {
            Name            : ko.observable(self.Name),
            Description     : ko.observable(self.Description),
            Model           : ko.observable(self.Model),
            BuildStage      : ko.observable(self.BuildStage),
            SoftwareVersion : ko.observable(self.SoftwareVersion),
            Configuration   : ko.observableArray(self.Configuration),
            SerialNumbers   : ko.observableArray(self.SerialNumbers)
        };
    }

    //#endregion

    return {
        Name            : name,
        Description     : desc,
        Model           : model,
        BuildStage      : buildStage,
        SoftwareVersion : softwareVersion,
        Configuration   : config,
        SerialNumbers   : serialNumbers,
        GetKnockout     : GetKnockout,
        Reset: Reset
    };
}

在我的JSFiddle example我还创建了一个函数,该函数在调用时将实例化 DTO 对象的多个实例并将它们返回到一个数组中。

到目前为止一切顺利......

现在,当我运行 Fiddle 时,表单会正确填写,“名称”属性值显示在标签和文本框中。 “序列号”已正确绑定(bind)到下拉列表框。

当您单击“Next”/“Prev”按钮时,数组中下一个 DTO 的“GetKnockout()”函数将被调用并绑定(bind)到表单。 “GetKnockout()”将 DTO 映射到新的 KO ViewModel,除非已经创建了 KO ViewModel,然后它将返回现有的 KO ViewModel。 (重要:请记住示例中只有 3 个 DTO,我没有为错误处理而烦恼,所以不要“下一个/上一个”太远!)

function BtnNext_OnClick(event) {

    APPScreen.SelectedLotIDX = APPScreen.SelectedLotIDX + 1;
    ko.applyBindings(APPScreen.SelectedLot().GetKnockout(), $("#dvContainer")[0]);

}

到目前为止,一切都按预期工作:您可以看到标签、文本框和下拉列表的内容在您通过 DTO 时发生适当的变化。

这里是问题开始的地方......在文本框中,修改名称,然后通过单击“下一步”/“上一步”按钮之一转到下一个/上一个 DTO。您会注意到,当您更改一个名称时,您会更改所有实例的名称!所以这让我开始审视我对“this”的使用,并让我做出了一些改变。然而,我仍然对为什么更改绑定(bind)文本框的值应该更新所有实例感到困惑。当您点击“Reset()”按钮时,它会正确地重置 仅显示的实例 的值。

最佳答案

您的问题是您绑定(bind)到模型,然后当您单击按钮时,您更改了基础模型的值。你应该做什么。是有一个模型数组,然后在单击下一个/上一个时只需切换您正在显示/编辑的对象。

检查简化的 fiddle :http://jsfiddle.net/tkirda/BAXsS/1/

<div id="dvContainer">
    <div data-bind="with: CurrentItem">
         <h2 data-bind="text:Name"></h2>

        <input type="text" data-bind="value:Name" />
        <br />
        <select data-bind="options: $root.SerialNumbers"></select>
        <br />
    </div>
    <button id="btnPrev" data-bind="click: Prev">Prev</button>
    <button id="btnNext" data-bind="click: Next">Next</button>
    <button id="btnReset">Reset</button>
</div>

JavaScript:

function Item(name) {
    this.Name = ko.observable(name);
}

var model = {
    items: ko.observableArray([new Item('A'), new Item('B'), new Item('C')]),
    SerialNumbers: ['1', '2', '3'],
    index: ko.observable(0)
};

model.CurrentItem = ko.observable(model.items()[0]);

model.Next = function () {
    model.index(model.index() + 1);
    model.CurrentItem(model.items()[model.index()]);
};

model.Prev = function () {
    model.index(model.index() - 1);
    model.CurrentItem(model.items()[model.index()]);
};

ko.applyBindings(model, $("#dvContainer")[0]);

关于javascript - KnockoutJS 正在更新数组中的所有对象,而不仅仅是一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16905648/

相关文章:

使用 Chrome + XHR 时未定义 PHP POST 变量

javascript - UI日期选择器代码格式

javascript - 如何在 jQuery 中将预加载的图像转换为 Base64 数据

javascript - 如何使用 javascript 或 JQuery 绕过打印对话框..?

javascript - 通过原型(prototype)将计算的可观察对象添加到构造函数

javascript - Knockout - 设置 json 生成的列表中仅一项可见

javascript - 如何将动态复选框值绑定(bind)到对象上的 Knockout observableArray?

javascript - Node.js 桌面应用程序的源代码是否受到保护?

javascript - CoffeeScript 错误

javascript - knockout 选项绑定(bind)不起作用