RequireJS / Durandal 字段始终为空

RequireJS / Durandal fields always null

问题

Durandal 或者 RequireJS 似乎使我的属性无效。我的主视图模型有 3 个子模型(PostModelCategoryModelTagModel),所有这些都结束成为空对象。

代码

主文件:blog.js

var viewModel;

define(['jquery', 'knockout', 'datajs', 'OData', 'Q', 'breeze', 'blog-posts', 'blog-categories', 'blog-tags'],
    function ($, ko, datajs, odata, Q, breeze, posts, categories, tags) {
        'use strict'

        var ViewModel = function () {
            var self = this;

            self.postModel = false;
            self.categoryModel = false;
            self.tagModel = false;

            self.activate = function () {
                self.postModel = new posts();
                self.categoryModel = new categories();
                self.tagModel = new tags();
            };
            self.attached = function () {
                breeze.config.initializeAdapterInstances({ dataService: "OData" });
                self.postModel.init();
                self.categoryModel.init();
                self.tagModel.init();
            };
            self.showCategories = function () {
                //.....
            };
            self.showPosts = function () {
                //.....
            };
            self.showTags = function () {
                //.....
            };
        };

        viewModel = new ViewModel();
        return viewModel;
    });

post.js

define(['jquery', 'jqueryval', 'knockout', 'kendo', 'kendo-knockout', 'notify'],
    function ($, jqueryval, ko, kendo, ko_kendo, notify) {
        'use strict'

        var PostModel = function () {
            var self = this;

            self.id = ko.observable(0);
            self.categoryId = ko.observable(0);
            self.headline = ko.observable(null);
            self.slug = ko.observable(null);
            self.teaserImageUrl = ko.observable(null);
            self.shortDescription = ko.observable(null);
            self.fullDescription = ko.observable(null);
            self.useExternalLink = ko.observable(false);
            self.externalLink = ko.observable(null);
            self.metaKeywords = ko.observable(null);
            self.metaDescription = ko.observable(null);

            self.availableTags = ko.observableArray([]);
            self.chosenTags = ko.observableArray([]);

            self.init = function () {
                //..... this code runs fine (initializes a Kendo Grid)
            };
            self.create = function () {
                //.....
            };
            self.edit = function (id) {
                //.....
            };
            self.remove = function (id) {
                //.....
            };
            self.save = function () {
                //.....
            };
            self.cancel = function () {
                //.....
            };
            self.validator = $("#post-form").validate({
                rules: {
                    // JQuery Validation Rules
                }
            });
        };
        return PostModel

tag.js

define(['jquery', 'jqueryval', 'knockout', 'kendo', 'kendo-knockout', 'notify'],
    function ($, jqueryval, ko, kendo, ko_kendo, notify) {
        'use strict'

        var TagModel = function () {
            var self = this;

            self.id = ko.observable(0);
            self.name = ko.observable(null);
            self.urlSlug = ko.observable(null);

            self.init = function () {
                //..... this code runs fine (initializes a Kendo Grid)
            };
            self.create = function () {
                //.....
            };
            self.edit = function (id) {
                //.....
            };
            self.remove = function (id) {
                //.....
            };
            self.save = function () {
                //.....
            };
            self.cancel = function () {
                //.....
            };
            self.validator = $("#tag-form").validate({
                rules: {
                    // JQuery Validation Rules
                }
            });
        };
        return TagModel;
    });

category.js

define(['jquery', 'jqueryval', 'knockout', 'kendo', 'kendo-knockout', 'notify'],
    function ($, jqueryval, ko, kendo, ko_kendo, notify) {
        'use strict'

        var CategoryModel = function () {
            var self = this;

            self.id = ko.observable(0);
            self.name = ko.observable(null);
            self.urlSlug = ko.observable(null);

            self.init = function () {
                //..... this code runs fine (initializes a Kendo Grid)
            };
            self.create = function () {
                //.....
            };
            self.edit = function (id) {
                //.....
            };
            self.remove = function (id) {
                //.....
            };
            self.save = function () {
                //.....
            };
            self.cancel = function () {
                //.....
            };
            self.validator = $("#category-form").validate({
                rules: {
                    // JQuery Validation Rules
                }
            });
        };
        return CategoryModel;
    });

注释

我尝试了什么

var CategoryModel = {}

而不是:

var CategoryModel = function () {};

这似乎可以防止 viewModel.postModel 和其他人为空,但它导致了其他问题。主要是 this 关键字的范围问题,我无法在任何地方成功设置 var self = this; - 即使我在 activate() 中设置它,它仍然不起作用 - 我会得到主视图模型或访问 this 时的其他内容。所以我认为我现在设置它的方式对于范围界定是最安全的,但由于某些原因,这 3 个字段始终为 NULL。

为了这个,我已经焦头烂额好几天了。谁能帮帮我?

编辑

当我在控制台中运行以下内容时:

alert(JSON.stringify(viewModel))

我得到:

{"postModel":{},"categoryModel":{},"tagModel":{},"__moduleId__":"viewmodels/admin/blog"}

如您所见,这 3 个子模型是空对象,并且出于某种原因,还缺少以下函数:

self.showCategories = function () { }
self.showPosts = function () { }
self.showTags = function () { }

我对这个完全运行没有想法...

好吧,由于某种原因 self.validator 始终为 NULL。我的 guess 是在将 HTML 注入 Durandal 占位符之前评估模块。因此,在计算 self.validator = $("#post-form").validate({ 时,页面上不存在 ID 为 #post-form 的表单,因此 self.validator 未定义。

所以我的解决方案是只在 init() 函数中分配 self.validator,该函数在 Durandal 生命周期的 attached 回调期间调用.