【问题标题】:Knockoutjs treeview lazy loading: child nodes not showingKnockoutjs treeview 延迟加载:子节点不显示
【发布时间】:2012-02-28 01:36:40
【问题描述】:

我刚开始使用 knockoutjs,并且正在尝试构建动态树视图。为了简化,我删除了与问题无关的所有内容。树视图将包含嵌套的 UL 标记。

html:

<div id="pnlDestinations">
    <ul data-bind="template: { name: 'GroupTemplate', foreach: Groups }"></ul>
</div>

<script type="text/html" id="GroupTemplate">
    <li>
        <a href="#" data-bind="text: GroupName, click: function() { RetrieveDestinations($data); }"></a>
        <ul data-bind="template: { name: 'DestinationTemplate', foreach: Destinations }"></ul>
    </li>
</script>

<script type="text/html" id="DestinationTemplate">
    <li>
        <a href="#" data-bind="text: DestinationName"></a>
    </li>
</script>

代码:

function ViewModel(groups) {
    Groups = ko.mapping.fromJS(groups);
    RetrieveDestinations = function (group) {
        $.getJSON('GetDestinations?id=' + group.GroupId(), function (data) {
            group.Destinations(ko.mapping.fromJS(data));
        });
    }
}

$(function () {
    $.getJSON("GetGroups", function (data) {
        ko.applyBindings(new ViewModel(data));
    });
});

所以我将树视图绑定在两个级别(使用 2 个模板),但我只在“GetGroups”中检索一个级别(目标存在,但是是一个空数组)。

单击组时,将在 RetrieveDestinations() 方法中检索目标,并且应该替换组中的空数组。但是,它们不会出现在我的树形视图中。

树视图的绑定应该是正确的,因为如果我在“GetGroups”中包含目的地,一切都会正确呈现。

【问题讨论】:

    标签: jquery knockout.js knockout-mapping-plugin


    【解决方案1】:

    ko.mapping.fromJS 当给定一个数组时,它将把它变成一个 observableArray。

    因此,当您执行group.Destinations(ko.mapping.fromJS(data)) 时,您将Destinations observableArray 的值设置为等于observableArray。基本上,这只是意味着它被包裹了两次。

    你可以做类似group.Destinations(ko.mapping.fromJS(data)())

    jsFiddle 目前不允许保存,但这里是您的代码简化为使用映射插件更新目的地(setTimeouts 来模拟 AJAX):

    <div id="pnlDestinations">
        <ul data-bind="foreach: Groups">
            <li>
                <a href="#" data-bind="text: GroupName, click: $root.RetrieveDestinations"></a>
                <ul data-bind="foreach: Destinations">
                    <li>
                        <a href="#" data-bind="text: DestinationName"></a>
                    </li>        
                </ul>
            </li>
        </ul>
    </div>
    

    视图模型:

    function ViewModel(groups) {
        this.Groups = ko.mapping.fromJS(groups);
        this.RetrieveDestinations = function (group) {
            setTimeout(function() {
                //fake data
                var name = group.GroupName(),
                    data = [ 
                        { DestinationName: name + "-1" }, 
                        { DestinationName: name + "-2" },
                        { DestinationName: name + "-3" }
                    ];
                ko.mapping.fromJS(data, {}, group.Destinations);
                group.Destinations.push({ DestinationName: "new" });
            }, 100);
        };
    }
    
    $(function () {
        setTimeout(function() {
            var data = [
                { GroupName: "Group1", Destinations: [] },
                { GroupName: "Group2", Destinations: [] },
                { GroupName: "Group3", Destinations: [] }
                ];
            ko.applyBindings(new ViewModel(data));
        }, 100);     
    });
    

    【讨论】:

    • 是的,这两个 () 成功了,我现在有一个工作树视图!非常感谢。很好的解释!
    • 我注意到一个奇怪的副作用,RP Niemeyer... 代码 group.Destinations.push({ DestinationId: 0, DestinationName: "New" }); 不起作用。消息是:对象不支持属性或方法“推送”。当我立即检索目的地时它确实有效。
    • 也许你可以在 jsFiddle 中放一些东西?
    • 你能在jsFiddle中模拟ajax请求吗?在上面的示例中:如果group.Destinations(ko.mapping.fromJS(data)()); 后跟group.Destinations.push({ DestinationId: 0, DestinationName: "New" });(立即将额外的项目添加到检索到的列表中),则在“推送”时引发异常。如果我不替换 Destinations 的值(将其注释掉),使其保持原来的空数组,它就可以工作。
    • 上面的更新代码(作为答案)使用映射插件使用ko.mapping.fromJS(data, {}, group.Destinations) 更新数组。试试这个代码。我不确定你在哪里推动,但看看这是否有帮助。当 jsFiddle 允许再次保存时,我们可以轻而易举地做到这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2019-02-04
    • 1970-01-01
    相关资源
    最近更新 更多