在Durandal中组合单独的模块实例

时间:2014-04-30 12:57:50

标签: knockout.js durandal knockout-2.0

我在同一个模块视图中多次编写相同的表单,但是当我在一个字段中更改数据时,它会反映在每个表单上。

这是一些清理过的代码。正如您所看到的,我确保不要将单例模式用于我想要多次构成的表单...

view.html

<button data-bind="click: append">Append</button>

<div data-bind="foreach: odbcForms">
    <div data-bind="compose: { model: $data, activationData: settings }"></div>
</div>

viewmodel.js

define(['knockout', 'forms/odbc'], function ( ko, odbcForm) {
    var odbcForms = ko.observableArray()

    var append = function () {
        odbcForms.push(new odbcForm({ hostname: 'v1', db: 'v2' }));
    };

    return {
        odbcForms: odbcForms,
        append: append
    }
}

形式/ odbc.html

<div>
    <form class="form-horizontal" role="form">
        <fieldset>
            <div class="form-group" data-bind="validationElement: hostname">
                <label for="hostname" class="col-sm-2 control-label">ODBC Link Name</label>

                <div class="col-xs-4">
                    <input data-bind="value: hostname" type="text" class="form-control" id="hostname">
                </div>
            </div>

            <div class="form-group" data-bind="validationElement: db">
                <label for="db" class="col-sm-2 control-label">Database</label>

                <div class="col-xs-4">
                    <input data-bind="value: db" type="text" class="form-control" id="db">
                </div>
            </div>
        </fieldset>
    </form>
</div>

形式/ odbc.js

define(['knockout'], function(ko) {
    var ctor = function (settings) {
        this.settings = settings;
    };

    ctor.prototype = {
        constructor: ctor,

        activate: function (settings) {
            this.hostname(this.settings.hostname);
            this.db(this.settings.db);
        },

        hostname: ko.observable().extend({
            required: true,
            minLength: 2
        }),

        db: ko.observable().extend({
            required: true,
            minLength: 2
        }),
    };

    return ctor;
}

提前谢谢

2 个答案:

答案 0 :(得分:2)

将您的表单/ odbc.js更改为以下内容:

define(['knockout'], function(ko) {
    var ctor = function () {
        this.settings = settings;
        this.hostname = ko.observable().extend({
            required: true,
            minLength: 2
        };
        this.db = ko.observable().extend({
            required: true,
            minLength: 2
        });
    };        

    ctor.prototype.activate = function (settings) {
        this.hostname(this.settings.hostname);
        this.db(this.settings.db);
    };

    return ctor;
});

可能是杜兰达对你的方法感到困惑。在表单/ odbc模块中的其他问题中,构造函数(ctor函数)应该没有参数。此外,将observable放在原型上并不是一个好主意 - 你会泄漏内存。如果你真的希望将hostnamedb建立为某种全局,请创建一个单独的config模块,使其成为单例,然后使用RequireJS注入它,如下所示:

define('config', ['knockout'], function(ko) {
    var 
        hostname = ko.observable(),
        db = ko.observable();

    return {
        hostname: hostname,
        db: db
    }
});

然后将odbc.js更改为以下内容:

define(['knockout', 'config'], function(ko, config) {
    var ctor = function (settings) {
        this.settings = null;     
        this.config = null;
    };        

    ctor.prototype.activate = function (settings) {
        this.settings = settings;
        this.config = config;
        config.hostname(settings.hostname);
        config.db(settings.db);
    };

    return ctor;
});

您的观点需要稍加更新:例如,您需要更改为value: hostname,而不是value: config.hostname

使用这种方法,您可以在应用程序增长时构建配置模块,而无需重构每个模块。另外,你知道你不必称它为ctor,对吗?为了便于调试,请为模块指定一个明确的名称,例如OdbcForm,以便您拥有:

var OdbcForm = function()
...
return OdbcForm;

它将在调试器中显示为OdbcForm,而不是ctor

答案 1 :(得分:1)

原型是共享的。您不应该在原型上放置属性值。属性值应该在实例上。只放功能。所有属性(可观察的)都应该出现在&#34;这个&#34;对象实例。

相关问题