0
var modules;

$.when(
    $.get('modules.json', function(data) {
        var mapping = { 'observe' : ['enabled'] };
        modules = ko.mapping.fromJS(data, mapping);
    })
).then(function() {
    ko.applyBindings(new viewModel(modules));
});

function viewModel(modules) {

    var self = this;

    self.modules = modules;

    console.log(self.modules());

    ...

}

enabledjson数组中每个模块对象中的键值不应该在我的控制台中显示为可观察函数,其值设置为json中定义的值(在这种情况下true)?

另外,有什么比我现在尝试的更好的等待绑定接收到的 json 数据的方法(如果有更好的方法)?

我的 json 数组中的一个对象如下所示:

{
    "id" : "spnsrlogo",
    "name" : "Sponsor Logo",
    "code" : "<h3>Sponsor Logo</h3><label for=\"spnsrLogoSrc\" data-bind=\"text: $root.spnsrLogoSrc\">Sponsor Logo Path</label><input type=\"text\" id=\"spnsrLogoSrc\" data-bind=\"value: $root.spnsrLogoSrc, valueUpdate: 'afterkeydown'\">",
    "output" : "assets/img/sponsor-logo.png",
    "enabled" : true
}

另外,我怎样才能利用这个code值,以便在附加它时,可观察对象变得活跃?以这种非工作尝试为例:

<div>
    <div data-bind="foreach: modules">
        <input type="checkbox" data-bind="checked: $parent.modulesEnabled(), value: $data.id, attr: { id: $data.id }">
        <label data-bind="attr: { for: $data.id }, text: $data.name" class="inlineblock"></label>
    </div>
</div>
<div id="modulecontainer" data-bind="foreach: modules">
    <div class="moduleoptions" data-bind="visible: $parent.modulesEnabled(), html: code, attr: { id: 'module-' + $data.id}"></div>
</div>

我尝试使 modulesEnabled 成为一个可观察的数组,但这没有用。

任何帮助将非常感激!

4

2 回答 2

1

对于问题的第一部分,我查看了映射源。在这里的某个地方,正在处理观察设置。它通过将属性的“完整路径”与您在观察数组中传递的字符串完全匹配来工作。

使用您的 json 层次结构,启用的属性应指定为 [0].enabled、[1].enabled、[2].enabled 等等。目前我认为你必须完全像这样在数组中传递它们,也许我们应该询问插件维护者是否可以将其更改为 [i].enabled 之类的东西,以考虑到数组的所有成员。如果任何维护者 / hardcore_users 读到:伙计们,我说得对吗?

因此,您必须生成“观察”配置数组,使其与初始数据中的项目数一样长,如下所示:

var mapping = { 'observe' : ['[0].enabled', '[1].enabled', '[2].enabled',.../*and so on*/ ] };

更改您的 json 结构可能会更好。

对于问题的第二部分,可以使用自定义绑定来完成,如下所示:

ko.bindingHandlers.customHtml = {
    init:function(element, valueAccessor, allBindings, viewModel, bindingContext){  
        $(element).html(valueAccessor());
        ko.applyBindingsToNode($(element).find("div")[0],{with:viewModel}, bindingContext.$root );        
        return { controlsDescendantBindings: true };              
    },
    update:function(element, valueAccessor, allBindings, viewModel, bindingContext){                               
    }
}

请注意,我添加了一些 div 标签来将 html 包装在代码属性中。

页面中的初始html是这样变化的,我只添加了customHtml customBinding:

<div id="modulecontainer" data-bind="foreach: modules">
    <div class="moduleoptions" data-bind="visible: $parent.modulesEnabled(), customHtml: code, attr: { id: 'module-' + $data.id}"></div>
</div>

最后,所有代码的小提琴:http: //jsfiddle.net/cUVN8/3/

于 2013-11-04T22:46:53.303 回答
0

如果有人感兴趣,我终于设法让事情正常进行。我要感谢 pax162 的第二个回答,因为没有它我会迷路。

我最终像这样构建我的 JSON:

{
    "id" : "isi",
    "name" : "ISI",
    "code" : "<h3>ISI</h3><label for=\"isiHeading\">ISI Heading</label><input type=\"text\" id=\"isiHeading\" data-bind=\"value: isiHeading, valueUpdate: 'afterkeydown'\"><label for=\"isiContent\">ISI Content</label><textarea id=\"isiContent\" data-bind=\"value: isiContent, valueUpdate: 'afterkeydown'\"></textarea><label for=\"isiFooter\">ISI Footer HTML</label><textarea id=\"isiFooter\" data-bind=\"value: isiFooter, valueUpdate: 'afterkeydown'\"></textarea>",
    "observables" : ["isiHeading","isiContent","isiFooter"]
}

然后使用一些延迟的 jQuery 魔法并手动添加我的 observables:

$.when(
    $.get(options.paths.modules, function(data) {
        self.modules = data;
        for (var i=0, l=self.modules.length; i<l; i++) {
            if (typeof(data[i].observables) !== "undefined") {
                for (var j=0, ll=data[i].observables.length; j<ll; j++) {
                    self.modules[i][data[i].observables[j]] = ko.observable('');
                }
            }
            self.modules[i].enabled = ko.observable(true);
        }
    })
).then(function() {
    self.successful();
    ko.applyBindings(self);
}, function(o) {
    console.log(o);
});

如果有人好奇,我成功的函数包含 customHtml 绑定处理程序定义和创建我在其他地方使用的其他更通用的可观察对象(不依赖于收到的 JSON):

this.successful = function() {

    ko.bindingHandlers.customHtml = {
        init: function(element,valueAccessor,allBindings,viewModel,bindingContext) {
            $(element).html(valueAccessor());
            ko.applyBindingsToNode($(element)[0],{with:viewModel}, bindingContext.$root);
            return { controlsDescendantBindings: true };
        },
        update: function(element,valueAccessor,allBindings,viewModel,bindingContext) {
            //
        }
    };

    // other functionality not relevant to this problem

};
于 2013-11-05T20:31:57.903 回答