1

HTMLフォームでPersonオブジェクトを編集するために使用される次のビューモデルがあります。

function PersonModel(person) {
    var self = this;
    self.id = ko.observable(person.Id);
    self.firstName = ko.observable(person.FirstName);
    self.surname = ko.observable(person.Surname);
    self.email = ko.observable(person.Email);
    self.cell = ko.observable(person.Cell);

    self.save = function (data) {
        savePerson(data);
    };
}

ユーザーが Person を編集したい場合、次のように、この新しいインスタンスを編集フォームにバインドします。

function editPerson(person) {
    var url = "@Url.Action("EditJson", "Person")";
    $.getJSON(url, function (data) {
        $("#person-detail").css("display", "block");
        ko.applyBindings(new PersonModel(data), $("#person-detail")[0]);
    });
}

そして、フォームでは、クリック イベントをビュー モデルの save メソッドにバインドします。

<a href="#" data-bind="click: save">Update</a>

1 人の個人レコードを編集するときに複数の DB 更新が実行されるという問題が発生しました。これはapplyBindings、同じ要素である編集ポップアップで複数回呼び出したためだと思います。これは、ApplyBindings を呼び出した回数と同じ数の DB 編集が実行されるため、ある程度確認できます。

ここで、 によって適用されたバインディングを削除するapplyBindings方法、またはバインディングを 1 回だけ適用し、編集ごとに再作成するのではなくビュー モデルを更新する方法を知る必要があります。私は最初のアプローチをはるかに好みます。ビュー モデルは、シングルトンの特性を示すべきではありません。

4

2 に答える 2

3

with一般に、現在選択されているレコードを保持するオブザーバブルを作成し、またはバインディングを使用してそれに対してバインドするようなことをしたいと思うでしょうtemplate

したがって、次のようなエディタがあります。

<div data-bind="with: currentItem">
  ...
</div>

次に、現在のデータを入力します。

this.currentItem(new PersonModel(data));

この方法では、バインディングを 1 回だけ適用し、複数のイベント ハンドラーなどで問題が発生することはありません。また、バインディングは、オブジェクトが設定されたときにのみコンテンツをレンダリングするため、空のwith場合はコンテンツが表示されません。currentItem

于 2012-10-14T21:52:45.317 に答える
0

Ryan のソリューションは、ほとんどの状況に最適です。ページ上で複数回インスタンス化できる JS および HTML コードのモジュールを本当に扱っている場合は、ko.cleanNode()またはを調べることをお勧めしますko.removeNode()

これらのメソッドは両方とも、メモリ リークとバインディングのクリーンアップを処理するために KO によって内部的に使用されます。最近のプロジェクトでは、製品の行が動的に追加されたテーブルがあります。これらの製品はそれぞれ、インラインで編集できる必要があります。各行のフォーム html を複製する代わりに、HTML がテーブルの行に動的にロードされ、バインディングが適用され、編集が完了するとバインディングが削除される、一種の KO モジュール パターンをセットアップすることにしました。

以下は、私が継承した基本的な AMD モジュールです。

/**
Prototype object for creating individual KnockoutJS modules

@module Shared
@class ko-module-prototype
@namespace
@static
**/
define(["knockout", 'jquery', 'Shared/js/helpers'], function (ko, $, helpers) {
    var exports = {};
    /**
    KO viewModel
    @property vm
    @static
    **/
    exports.vm = {};
    /**
    KO bindings
    @property bindings
    @static
    **/
    exports.bindings = {};
    /**
    Optional binding namespace for avoiding bindings getting overwritten
    @property bindingNamespace
    @static
    **/
    exports.bindingNamespace = null;
    /**
    Whether bindings are registered with KO or not
    @property bindingsRegistered
    @static
    **/
    exports.bindingsRegistered = false;
    /**
    The HTML node wrapping the area we wish to apply KO bindings
    @property $wrapperNode
    @static
    **/
    exports.$wrapperNode = $("body");
    /**
    Optional html string to be loaded in as a template
    @property template
    @static
    **/
    exports.template = null;
    /**
    Injects html, registers bindings, and applies bindings
    @method start
    @static
    **/
    exports.start = function ($wrapperNode) {
        // Update wrapper node
        if ($wrapperNode) this.$wrapperNode = $wrapperNode;

        this._openNodeId = "mod_" + helpers.uniqueId();
        var $targetNode = $wrapperNode;

        // Insert template html
        // Wrap in a div
        if (this.template) {
            this.$wrapperNode.html($("<div></div>").attr("id", this._openNodeId).html(this.template));
            $targetNode = $wrapperNode.find("#" + this._openNodeId);
        }

        // Register bindings
        // Class binding provider has to be setup first...
        if (!this.bindingsRegistered) {
            this.bindingsRegistered = true;
            var register = this.bindings;
            if (this.bindingNamespace !== null) {
                register = { };
                register[this.bindingNamespace] = this.bindings;
            }
            ko.bindingProvider.instance.registerBindings(register);
        }

        ko.applyBindings(this.vm, $targetNode[0]);
    };
    /**
    Removes html, and un-applies bindings
    @method end
    @static
    **/
    exports.end = function () {
        var $openNode = $("#" + this._openNodeId)[0];

        if (this.template !== null) {
            ko.removeNode($openNode);
        } else {
            ko.cleanNode($openNode);
        }
    };
    return exports;
});

ここで見つけることができる Ryan の KO classBindingProvider を使用します。

https://github.com/rniemeyer/knockout-classBindingProvider

于 2012-10-15T17:42:49.433 に答える