KnockoutJS:模板未在可观察数组更改时更新(仅在添加时,在删除时有效)

Posted

技术标签:

【中文标题】KnockoutJS:模板未在可观察数组更改时更新(仅在添加时,在删除时有效)【英文标题】:KnockoutJS: template is not updated on observable array change (only on add, works on remove) 【发布时间】:2011-11-16 08:51:48 【问题描述】:

所以,我有带有站点的可观察数组,它通过模板显示。如果我将站点添加到此阵列,则模板不会更新,但如果我将从阵列中删除站点 - 瞧!模板已更新,所有以前添加的网站也都显示出来了。

如果我将使用漂亮的 hack(在代码中注释)将整个数组替换为新数组,那么一切正常。

顺便说一句,我通过 AJAX 加载模板并在之后使用“ko.applyBindings(viewModel)”。我认为这可以正常工作,因为初始站点显示正确。

$(function()

//site entry in user's sites list
var siteObject = function(url, lastChecked, status)
    this.url = url;
    this.lastChecked = (lastChecked == 'undefined') ? '' : lastChecked;
    this.status = (status == 'undefined') ? 'not_checked_yet' : status;
    this.toDelete = false;
    this.remove = function() viewModel.sites.remove(this);
;

viewModel = 
    //=========== sites list managment ==========================
    sites: ko.observableArray(),
    //on "add" click in "add site" form
    addSite: function()
        var $form = $('#add_site_form');
        var siteUrl = $form.find('input[name="site"]').val();

        /*nifty hack  <----
        var sites = this.sites();
        sites.push(new siteObject(siteUrl));
        this.sites(sites);*/

        this.sites.push(new siteObject(siteUrl));
    ,
    //on "remove sites" button click
    removeSites: function() 
        var sitesToRemove = [];
        $.each(this.sites(), function()
            if (this.toDelete) sitesToRemove.push(this);
        );
        if (sitesToRemove.length == 0)
            alert("Ни одного сайта не было выбрано для удаления.");
        else 
            var message = "Вы точно хотите перестать отслеживать";
            for (var i in sitesToRemove) 
                message += "\n\"" +  sitesToRemove[i].url + "\"";
            
            message += "?";
            if (confirm(message)) 
                $.each(sitesToRemove, function()this.remove());
                //save new sites list to db
                this.saveSitesListToDb();
            
           
        //hide form
        $('#remove_sites_form').slideToggle();
        //toggle checkboxes
        $('#content_sites_list .site_info input[type="checkbox"]').slideToggle();
    ;

还有模板:

<!-- end of menu -->
<div id="content_sites_list" 
     class="grid_12" 
     data-bind="template: name: 'sites_list_template', foreach: sites"></div>

  <!-- Templates -->

  <script id="sites_list_template" type="text/x-jquery-tmpl">
    <div class="site">
        <div class="site_panel grid_12">
            <div class="site_info">
                &ndash;
                <input type="checkbox" value="$url" 
                       class="delete_checkbox" data-bind="checked: toDelete" /> 
                <a href="$url" class="show_site_stat">$url.substr(7)</a>
                if status == "200"
                    <img src="img/green_light.png" />
                /if             
            </div>
            <div class="site_stat">
                <div class="site_last_check">Последняя проверка: $dateTimestamp</div>
            </div>
        </div>
    </div>
  </script>

我已经在最新的 knockoutjs 测试版和稳定版上尝试过这个。

【问题讨论】:

如果您将this.sites.push(new siteObject(siteUrl)); 更改为sites.push(new siteObject(siteUrl)); 有什么不同吗? 是的,它不起作用)this.sites() - 是淘汰赛的可观察数组。站点 - 是从可观察数组 + 新对象创建的本地数组。 您的示例经过小幅编辑后对我来说效果很好,包括正确关闭 $(function() ) 中的花括号和圆括号。顺便说一句,我认为最好让 siteUrl 成为视图模型的成员,然后将其绑定到某个复选框,而不是使用 jQuery 选择器搜索它。 @STO 谢谢,我一定会试试的。这是我的第一个 MVVM 项目。) 【参考方案1】:

我制作了一个jsFiddle,效果很好。

JSLint 抱怨 viewModel 的 removeSites 函数中存在一些问题。我修复了这些问题并添加了一个按钮和输入字段,以便能够提供一些输入,一切顺利。

所以您可以尝试更新您的 removeSites 函数,看看它是否对您有帮助,

【讨论】:

哇,谢谢!似乎问题出在 AJAXed 模板中,因为您的代码与我的非常相似。我会尝试将它包含在索引页面中。另外我会尝试在 1.3.0 中使用 knockout 的新模板引擎

以上是关于KnockoutJS:模板未在可观察数组更改时更新(仅在添加时,在删除时有效)的主要内容,如果未能解决你的问题,请参考以下文章

KnockoutJS Observable 未在模板中更新

KnockoutJS observable 未在屏幕上更新

KnockoutJS 3.X API 第八章 映射(mapping)插件

点亮的 Web 组件未在属性更改时更新

knockoutjs 可观察对象绑定的可观察数组

Knockoutjs 单击并编辑字段不更新可观察的