1

当我的视图和模型被使用 durandal 的 compose 绑定语句绑定时,我从微风和 q.js 收到以下错误。我单独编写了有问题的视图,它工作得很好,直到我尝试用它进行组合绑定,它抛出了这个错误。我尝试将所有自定义属性从我的实体构造函数移动到初始化程序,并推迟对我的计算属性的评估,但这并没有阻止错误。我不确定是哪个框架导致了这个问题,或者我自己的代码是否是。我在我的数据上下文中使用了延迟的 Q 承诺,但我评论它以排除它并返回使用标准回调函数。

错误:

[Q] Unhandled rejection reasons (should be empty): [TypeError]
Object [object Object] has no method 'isExpanded'
TypeError: Object [object Object] has no method 'isExpanded'?    at domainModel.<anonymous> (http://myApp/App/viewmodels/categoryTreeView.js?v=1.0.0.0:31:59)?    at evaluateImmediate (http://myApp/Scripts/knockout-2.2.1.debug.js:1241:41)?    at Object.ko.dependentObservable (http://myApp/Scripts/knockout-2.2.1.debug.js:1318:9)?    at dmInitializer (http://myApp/App/viewmodels/categoryTreeView.js?v=1.0.0.0:30:29)?    at proto._postInitialize (http://myApp/scripts/breeze.debug.js:2975:13)?    at mergeEntity (http://myApp/scripts/breeze.debug.js:12768:39)?    at processMeta (http://myApp/scripts/breeze.debug.js:12685:24)?    at visitAndMerge (http://myApp/scripts/breeze.debug.js:12665:16)?    at http://myApp/scripts/breeze.debug.js:12972:20?    at Array.map (native)?From previous event:?    at executeQueryCore (http://myApp/scripts/breeze.debug.js:12593:77)?    at proto.executeQuery (http://myApp/scripts/breeze.debug.js:11461:23)?    at Object.getCategories (http://myApp/App/services/datacontext.js?v=1.0.0.0:51:17)?    at viewModel.self.getCategories (http://myApp/App/viewmodels/categoryTreeView.js?v=1.0.0.0:204:17)?    at init (http://myApp/App/viewmodels/categoryTreeView.js?v=1.0.0.0:223:18)?    at new viewModel (http://myApp/App/viewmodels/categoryTreeView.js?v=1.0.0.0:225:9)?    at Object.<anonymous> (http://myApp/App/durandal/composition.js?v=1.0.0.0:317:42)

类别树视图.js:

define(["services/datacontext"], function (ctx) {
    function domainModel() {
        var self = this;
        self.isSelected = ko.observable(false);
        self.isExpanded = ko.observable(false);

        self.toggleIsExpanded = function () {
            self.isExpanded(!self.isExpanded());
        };
        self.toggleIsSelected = function () {
            self.isSelected(!self.isSelected());
        };
    }
    var dmInitializer = function (item) {
        item.isBranch = ko.computed(function () {
            return item.Children().length > 0 || item.ParentCategory() == null;
        });
        item.isRoot = ko.computed(function () {
            return item.ParentCategory() == null;
        });
        item.isVisible = ko.computed(function() {
            return item.isRoot() || item.ParentCategory().isExpanded();
        }, item);
    };

    ctx.metadataStore.registerEntityTypeCtor("Category", domainModel, dmInitializer);

    function viewModel() {
        var self = this;
        self.categories = ko.observableArray();

        self.getCategoriesCallback = function (data) {
            console.log("callback for getCategories");
            self.categories(data.results);
        };
        self.getCategories = function () {
            ctx.getCategories(self.getCategoriesCallback);
        };
        init = function () {
            self.getCategories();
        };
        init();
    }
    return viewModel;
}

categorytreeview.html

<div id="categoryTreeView">
    <script id="recursiveTemplate" type="text/html">
    <ul data-bind="visible: isVisible">
        <li data-bind="css: { branch: isBranch, leaf: !isBranch(), expanded: isExpanded }">
            <div data-bind="click: toggleIsExpanded"></div>
            <div>
                <input type="checkbox" data-bind="attr: { id: 'c-' + CategoryId() }, value: CategoryId" />
                <label data-bind="text: Name, attr: { for: 'c-' + CategoryId() }"></label>
            </div>
        </li>
        <!-- ko template: { name: 'recursiveTemplate', foreach: Children } --><!-- /ko -->
    </ul>
    </script>
    <div class="css-treeview">
        <!-- ko template: { name: 'recursiveTemplate', foreach: categories } --><!-- /ko --> 
        <div id="dialog-buttons">
            <input type="button"
                value="Cancel" class="btn-cancel">
            <input type="button" value="Save" class="btn-primary pull-right">
        </div>
    </div>
</div>

这是我正在撰写失败视图的主视图中的 html:

<div data-bind="compose: { model: categoryMapModel, activate: true, cacheViews: false }">
</div>

数据上下文.js

function getCategories(afterGetCategories) {
    //var deferred = Q.defer();

    var query = breeze.EntityQuery.from("Category")
        .orderBy("ParentCategoryId, Name")
        .expand("Children");

    manager.executeQuery(query)
        .then(function (data) {
            console.log("callback for getCategories");
            //deferred.resolve(data);
            afterGetCategories(data);
        })
        .fail(function (error) { console.log("Error: " + error); });

    //return deferred.promise;
};

更新1:

我已经排除 Q.js 是一个问题,它只是堆栈中的最后一个人。如果我为 my 分配categoryMapModel()一个如下所示的初始值,则一切正常。如果我然后单击删除并重新显示此视图的 UI 按钮,则一切正常。activate()如果我也等待并在durandal 再次调用的方法中设置此变量,那么一切正常。

self.categoryMapModel = ko.observable("viewmodels/categoryTreeView");

然而,这个变量是在运行时设置的,当用户点击一个按钮时,我得到了错误。我看到的是,brief.js 没有将自定义属性从我的初始化函数附加到特定实体。正如您从下面的日志中看到的那样,当它击中名为“DVD”的类别实体时,它会被炸毁。由于未知原因,此实体不包含任何自定义属性,例如在初始化函数中定义的isExpanded()或定义的。在所有实体中,这是唯一没有自定义属性的实体。列表中还有其他实体,它们很好。我看不出任何逻辑为什么微风在这种情况下会对特定实体产生问题,但确实如此。isRoot()

我到底做错了什么/什么会导致微风.js 忽略初始化函数?

name: Apparel categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Art categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Books categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Electronics categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Movies categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: root node categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Blu-ray categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
*name: DVD categoryTreeView.js:269
*properties: entityAspect, IsDeleted, CategoryId, PictureId, Name, Description, IsPublished, ParentCategoryId, CreatedOn, ParentCategory, Picture, Children, AdvertiserCategories, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: reddisc categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Animation categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: Accessories categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: test categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: test2 categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: test23 categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
name: test categoryTreeView.js:269
properties: isSelected, isExpanded, toggleIsExpanded, toggleIsSelected, entityAspect, CreatedOn, CategoryId, PictureId, Name, Description, IsPublished, IsDeleted, ParentCategoryId, Children, Picture, ParentCategory, AdvertiserCategories, isBranch, isRoot, isVisible, path, _$typeName, entityType, _$interceptor, getProperty, setProperty,  categoryTreeView.js:270
rootCategories needed 
[Q] Unhandled rejection reasons (should be empty): [TypeError]
4

1 回答 1

0

我终于明白怎么回事了!在主视图中,我有一个向下扩展到Category表的轻量查询,然后我正在加载另一个也需要查询Category表的视图(categoryTreeView)。registerEntityTypeCtor由于首先加载了主视图,并且在该视图中没有调用Category实体微风,因此本质上是按原样缓存来自第一个查询的任何实体。当我的第二个视图出现时,即使我确实registerEntityTypeCtor在那里调用,它也不会触发已经从主视图的查询中加载的实体。

于 2013-06-13T16:58:28.807 回答