【问题标题】:JSViews observable array not refreshingJSViews 可观察数组不刷新
【发布时间】:2017-07-24 15:00:23
【问题描述】:

对于关于 JSViews 的另一个问题,我们深表歉意。我真的很喜欢这个系统,但我偶尔会遇到困难。

我有一个简单的模板,它只需要更新数组中的哪些项目以在选择框更改时显示:

但是,当我更改数据“isSelected”时,模板并未使用以下内容进行更新:

即:

function someClickFunction(sel) {
    value = sel.value;
    ....
    la_configure_list[0].isSelected = false;
    $.observable(la_configure_list).refresh(
            la_configure_list.slice(0)
        );
}

如果我把它改成

$.observable(la_configure_list).refresh(
        JSON.parse(JSON.stringify(la_configure_list))
                       );

它更新得很好。

谁能告诉我我做错了什么:

<script id="la-config-overview-list-template" type="text/x-jsrender">
    {^{if isSelected}}
    <div class="col s12 la_review_list_item" data-index="{{:#index}}">
        <div class="card">
            <div class="card-content" style="padding: 10px;">
                <div class="col s12 m6 l5 xl5">
                    <h6 style="font-weight: 700;" class="">{{:title}}</h6>
                        <div>Categories:</div>
                        <div>
                            {{for categories}}
                            <span class="chip">{{:#data}}</span>
                            {{/for}}
                        </div>
                    </div>
                    <div class="clearfix"></div>
                </div>
            </div>
        </div>
    </div>
    {{/if}}

我的html是

<div id="teacher_la_review_overview_main_wrapper" class="container body-content">
    <div class="row" style="margin-bottom: 0;"></div>
</div>

数组是:

la_configure_list = [
{
    isSelected:true,
    title: "Title",
    categories: ["1", "2"....]
},
....
]

我设置了模板:

$.templates("#la-config-overview-list-template").link("#la_review_list_overview_list_wrapper .row", la_configure_list);

我尝试使用 $.view(elem).refresh(),但由于我更新 isSelected 的点击操作在模板之外,我找不到要使用的正确“elem”。

编辑 - 添加实际更新代码:

function CategoryUpdate(sel) {

        var catSelected = sel.value;
        var catText = sel.options[sel.selectedIndex].text;

        if (catSelected !== "-1") {
            for (var cs = 0; cs < la_configure_list.length; cs++) {
                if (la_configure_list[cs].categories == null) {
                    la_configure_list[cs].isSelected = false;
                    continue;
                }
                var categories = la_configure_list[cs].categories;
                var isFound = false;
                for (var c = 0; c < categories.length; c++) {
                    var category = categories[c];
                    if (category === catText) {

                        la_configure_list[cs].isSelected = true;
                        isFound = true;
                    }
                }
                if (!isFound) {
                    la_configure_list[cs].isSelected = false;
                }
            }
        } else {
            for (var x = 0; x < la_configure_list.length; x++) {
                la_configure_list[x].isSelected = true;
            }
        }

        $.observable(la_configure_list).refresh(
            JSON.parse(JSON.stringify(la_configure_list))
        );
    }

【问题讨论】:

    标签: jsrender jsviews


    【解决方案1】:

    您的数组la_configure_list.slice(0) 是la_configure_list 的浅表副本。可观察数组refresh() 方法用于数组更新——排序、删除或添加项目。它经过优化以避免不必要的更新。事实上,它会分析数组并针对它检测到的任何更改触发移动、插入和删除事件。

    在您的情况下,虽然您复制了数组,但它是浅拷贝,因此数组项相同,顺序不变。因此不会触发可观察到的数组更改事件。当您使用 JSON.parse 等时,您正在用克隆副本替换对象,所以现在 refresh() 认为所有项目都已删除,然后添加了新项目。

    但是你为什么不对 isSelected 可观察的属性进行任何更改,如下所示:

    function someClickFunction(sel) {
        value = sel.value;
        ...
        $.observable(la_configure_list[index]).propertyChange("isSelected", false);
        ...
    }
    

    由于您有可观察的数据链接{^{if isSelected}},因此您不需要对数组或视图进行任何额外的刷新……

    【讨论】:

    • 谢谢你,我明白了。我没有将其作为属性更改的原因是我实际上是在遍历类别数组并查看所选类别是否在列表中并更新每个数组项的 isSelected。因此,arrat 中的每个项目都根据搜索条件将 isSelected 设置为 true 或 false。可观察地单独更新每一个而不是最后一次更新会不会很慢?您说刷新用于排序,但这就是我想要做的。有没有更好的办法?
    • 我用更新/排序的完整代码编辑了我的问题
    • 您可以在每个项目上使用 observable().propertyChange(),只要您不重复地前后切换相同的项目。因此,只需使用 propertyChange() 击中每个项目一次。如果 value 已经为 false 则设置 propertyChange(..., false) 不会触发事件,如果已经为 true 也不会设置为 true ,这样就可以了。所以应该是每一项都访问一次是合理的做法……
    猜你喜欢
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2018-09-05
    • 1970-01-01
    • 2014-01-22
    • 2015-03-08
    相关资源
    最近更新 更多