1

通过我的 knockout.js 映射,我在 IE 上进行了无休止的递归。更熟悉 KO 的人可以发现我做错了什么吗?

我有以下 knockout.js 映射:


        var mapping = {
            create: function(options) {
                return new MyViewModel(options.data);
            },
            'ChildItems': {
                create: function(options) {
                    return new ChildVM(options.data);
                }
            }
        }

当我渲染页面时。5 次 IE 中有 1 次以以下无限递归堆栈结束(导致“SCRIPT28:堆栈空间不足”)。IE 的调用栈:


    fromJS
    MyViewModel
    create
    Anonymous Function
    withProxyDependentObservable
    createCallback
    updateViewModel
    fromJS
    MyViewModel
    create
    Anonymous Function
    withProxyDependentObservable
    createCallback
    updateViewModel
        ...

我的视图模型构造函数:

 function MyViewModel(data) {
            var self = this;
            this.$type = 'MyViewModel';

            [some observables]         
            ...

            ko.mapping.fromJS(data, mapping, this);
        }

视图模型的初始化是通过调用 json 端点来完成的:


            $.ajax({
                url: 'http://my.end/point',
                type: 'POST',
                data: JSON.stringify(payload),
                contentType: 'application/json; charset=utf-8',
                success: function(data) {
                    window.vm = ko.mapping.fromJS(data, mapping);
                    ko.applyBindings(window.vm)
                    }
            });

4

1 回答 1

2

您应该将映射对象划分为 2 个对象。第一个用于映射视图模型,第二个用于子视图。

var mapping = {
            create: function(options) {
                return new MyViewModel(options.data);
            }
        }

var childrenMapping = {
                'ChildItems': {
                    create: function(options) {
                        return new ChildVM(options.data);
                    }
                }
}

您的 ajax 请求保持不变。更新 MyViewModel 函数以使用 childrenMapping :

 function MyViewModel(data) {
            var self = this;
            this.$type = 'MyViewModel';

            [some observables]         
            ...

            ko.mapping.fromJS(data, childrenMapping, this);
        }

问题的根本原因是映射的递归调用。当您调用ko.mapping.fromJS(data, mapping);淘汰赛调用创建规则时,将创建 MyViewModel 对象。在 MyViewModel 的构造函数中,ko.mapping.fromJS由于使用相同的映射选项,您调用了相同的创建规则,该规则创建了使用相同选项调用的 MyViewModel 对象ko.mapping.fromJS

于 2012-08-17T13:24:23.847 回答