Knockout.js使每个嵌套对象成为Observable

fra*_*llo 34 javascript mvvm knockout-mapping-plugin knockout-2.0 knockout.js

我使用Knockout.js作为MVVM库将我的数据绑定到某些页面.我目前正在构建一个库来对Web服务进行REST调用.我的RESTful Web服务返回一个简单的结构:

{
    id : 1,
    details: {
        name: "Johnny",
        surname: "Boy"
    }
}
Run Code Online (Sandbox Code Playgroud)

我有一个可观察的主要父母,myObject.当我做

myObject(ko.mapping.fromJS(data))
Run Code Online (Sandbox Code Playgroud)

可观测量myObject是:

  • id
  • name
  • surname

我怎样才能details(理论上结构中的任何对象都是可观察的)?我需要这种行为,这样我就可以在细节上设置一个计算的observable,并在任何内部数据发生变化时立即注意到.

我已经设置了一个基本的递归函数,应该可以解决这个问题.当然,myObject.details它不会成为可观察的.

// Makes every object in the tree an observable.
var makeAllObservables = function () {
    makeChildrenObservables(myObject);
};
var makeChildrenObservables = function (object) {
    // Make the parent an observable if it's not already
    if (!ko.isObservable(object)) {
        if ($.isArray(object))
            object = ko.observableArray(object);
        else
            object = ko.observable(object);
    }
    // Loop through its children
    for (var child in object()) {
        makeChildrenObservables(object()[child]);
    }
};
Run Code Online (Sandbox Code Playgroud)

我很确定它是关于错误引用的东西,但我该如何解决这个问题呢?谢谢.

Pao*_*ndo 23

我会使用淘汰映射插件.

var jsonData = {
    id : 1,
    details: {
        name: "Johnny",
        surname: "Boy"
    }
}

var yourMapping = {
    'details': {
        create: function(options) {
            return Details(options.data);
        }
    }
}

function Details(data) {
    ko.mapping.fromJS(data, {}, this);
}

function YourObjectName() {
    ko.mapping.fromJS(jsonData, yourMapping, this);
}
Run Code Online (Sandbox Code Playgroud)

这将创建您的对象层次结构,其中所有子项都是可观察对象.

  • 是的,我已经考虑过这个解决方案,对于许多比这个例子中的on更大的结构,我需要这样做,而且我正在寻找一种自动完成的方法. (5认同)
  • 我同意,这可能是繁琐的工作,因为这意味着你需要为你想要映射/具有可观察性的每种类型的对象预先定义模型.但是想想......必须有一种方式可以说淘汰如何映射属性.你知道这不是魔术.:)我认为长期建模有利于可维护性的原因.还想象一下你使用TypeScript.在TypeScript中,对象必须是强类型的,因此在前面预先定义.因此,建模在客户端也是必须的. (2认同)

Jas*_*aat 14

我不认为淘汰赛有一种内置的方式来观察子元素的变化.如果我理解了您的问题,当有人更改名称时,您需要将细节更改为要注意的实体.你能给出一个如何使用它的具体例子吗?您是否会使用可观察的详细信息订阅来执行某些操作?

你的代码没有使细节成为可观察对象的原因是因为javascript是按值传递的,所以更改函数中'object'参数的值不会改变你传递的实际值,只改变你内部参数的值功能.

编辑

如果更改自动传播给父母,这应该让所有孩子都能观察到,但是你第一次传递的根应该已经是一个可观察的.

// object should already be observable
var makeChildrenObservables = function (object) {
    if(!ko.isObservable(object)) return;

    // Loop through its children
    for (var child in object()) {
        if (!ko.isObservable(object()[child])) {
            object()[child] = ko.observable(object()[child]);
        }
        makeChildrenObservables(object()[child]);
    }
};
Run Code Online (Sandbox Code Playgroud)