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 时,我将 this 的新实例绑定到编辑表单,如下所示:

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]);
    });
}

在表单中,我将单击事件绑定到视图模型中的保存方法:

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

我现在在编辑单个人员记录时遇到了多个数据库更新运行的问题,我认为这是因为我applyBindings在同一个元素上多次调用了编辑弹出窗口。我可以确认这一点,因为我执行的数据库编辑次数与调用 ApplyBindings 的次数一样多。

现在我要么需要知道如何删除由 应用的applyBindings绑定,或者如何只应用一次绑定,然后更新我的视图模型,而不是为每次编辑重新创建它。我更喜欢第一种方法。视图模型不应表现出单例特征。

4

2 回答 2

3

通常你会想做一些事情,比如创建一个 observable 来保存当前选择的记录,然后使用withortemplate绑定来绑定它。

所以,你会有一个像这样的编辑器:

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

然后,您将使用当前数据填充它:

this.currentItem(new PersonModel(data));

这样,您只需应用一次绑定,并且不会遇到多个事件处理程序等问题。绑定也只会在填充对象时呈现其内容,因此当它为空with时不会显示任何内容。currentItem

于 2012-10-14T21:52:45.317 回答
0

Ryan 的解决方案是大多数情况下的最佳解决方案。如果您真正处理的是可以在页面上多次实例化的 JS 和 HTML 代码模块,您可能需要查看ko.cleanNode()ko.removeNode().

KO 在内部使用这两种方法来处理内存泄漏和绑定清理。在最近的一个项目中,我有一个表格,其中包含几行动态添加的产品。这些产品中的每一个都必须是可在线编辑的。我没有为每一行复制表单 html,而是选择设置一种 KO 模块模式,其中 html 动态加载到表行中,应用绑定,一旦完成编辑,绑定就会被删除。

这是我继承自的基本 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 回答