【问题标题】:knockoutjs extender observable unknown via with binding通过绑定可观察到的 knockoutjs 扩展器未知
【发布时间】:2013-10-26 09:18:49
【问题描述】:

您好,我在扩展 observableArray 的扩展器“分页”中有一个 KnockoutJs 计算的 observable ItemCountText。 observableArray 是 Products。

这按预期工作,给了我“32 个产品”(32、48,无论数字是多少,加上“产品”或我传递到扩展器设置中的任何文本)

<span data-bind="text:Products.ItemCountText"></span> 

.. 但是这个

<!-- ko with: Products -->
<span data-bind="text:ItemCountText"></span>
<!-- /ko -->

... 因 错误而损坏:无法解析绑定。消息:ReferenceError:ItemCountText 未定义;绑定值:文本:ItemCountText

尽管定义了“Products.ItemCountText”绑定,但导致扩展器计算出的可观察 ItemCountText 未在“with: Products”中定义的问题可能是什么?感觉好像“ko with:”的绑定机制无法“进入”扩展程序。

这是一个演示问题的小提琴。为了避免分心,分页扩展器已将与问题无关的所有内容都剪掉了。

http://jsfiddle.net/J4Nd2/1/

要遇到上述问题,请取消注释小提琴的 HTML 第 14 行并运行

淘汰赛是 2.2.1 版

这是 JsFiddle 的 HTML

    <div id="bindMe">
    <span data-bind='text: Yay()'></span>
    <div data-bind="text: Products.ItemCountText"></div>
    <div><span data-bind="text: Products().length"></span> on this page</div>
    <!-- ko with: Products -->
        <ul>
            <!-- ko foreach: $data -->
                <li data-bind="text: $data"></li>
            <!-- /ko -->
        </ul>
    <!-- /ko -->
<span data-bind='text: Boo'></span>
    <!-- ko with: Products -->
<!--    <div data-bind="text: ItemCountText"></div>  -->
        <div><span data-bind="text: length"></span> on this page</div>
        <ul>
            <!-- ko foreach: $data -->
                <li data-bind="text: $data"></li>
            <!-- /ko -->
        </ul>
    <!-- /ko -->   
</div>

这是 JsFiddle 的 Javascript

ko.extenders.paged = function (target, options) {
    // Settings
    var settings = $.extend({
        "itemcounttext": 'Counted Items'
    }, options);

    target.TotalRecords = ko.observable();
    target.ItemCountText =  ko.computed(function () {
        return target.TotalRecords() + " " + settings.itemcounttext;
    });

    return target;
};
/// -- End paging extender -- \\\

var ViewModel = function()  {
    var self = this;
    self.Yay = ko.observable("Hello World... Products.ItemCountText.. it works great");
self.Boo = ko.observable("But if HTML line 14 is uncommented, why does ItemCountText from extender broke using ko with?");
    self.Products = ko.observableArray([]).extend(
    {
        paged:
        {
            "itemcounttext": 'Products in total'
        }
    });
};

var myViewModel = new ViewModel();
ko.applyBindings(myViewModel, document.getElementById("bindMe"));

myViewModel.Products.push('prod a');
myViewModel.Products.push('prod b');
myViewModel.Products.push('prod c');
myViewModel.Products.TotalRecords(5);

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    问题在于,在您的数据实际位于该 ItemCountText 中之前,您的 observable 已创建并绑定到视图 -

    http://jsfiddle.net/J4Nd2/2/

    <div data-bind="text: $data.ItemCountText"></div>
    

    通过附加 $data。在前面,它告诉 Knockout 只有在它有值时才绑定它,基本上是推迟绑定直到 ItemCountText 有值。

    编辑更新

    您的 with: 绑定忽略了扩展属性,因为您将上下文绑定到数组的值,而数组的值不包括那些扩展属性。

    <!-- ko with: Products -->
    <span data-bind="text: $data"></span>
    

    当您绑定:产品时,它几乎与绑定可观察值的值相同 - 该对象的任何其他不属于可观察值的属性都将被忽略。

    如果您必须使用绑定在无容器中绑定,请使用 $parent.Products 将其重新放入 - http://jsfiddle.net/J4Nd2/4/

    【讨论】:

    • 添加任何上下文标记将隐藏问题,使其不会在 javascript 控制台中显示为错误,但绑定仍然不成功。您的小提琴也没有在下半部分显示“总共 5 个产品”
    • 已更新。您将上下文绑定到 observableArray 的值,而不是您正在扩展的父对象
    • 看到整个事情就是它是一个分页扩展器。我试图做的是重用它和绑定到它的分页视图。因此,“with: ChangeLog”将无法重用其中包含“$parent.Products”的视图。如果“ko with”不能做到这一点,有什么方法可以访问扩展器的属性〜一般地,以便可以在不同的分页数组上重用视图?
    • 如果您希望每个对象都具有该属性,而不是设置一个具有 observableArray 属性的父 observable 并在那里设置该属性,那么您将它绑定在一个可观察数组的顶部/跨度>
    • "...设置一个父 observable,它的属性是 observableArray 并在那里设置属性.." 谢谢你,我认为应该可以,但我仍然想知道为什么 text:Products .ItemCountText 用作绑定,但“With: Products, text:ItemCountText”失败。两种方式应该是一样的,不是吗?
    【解决方案2】:

    在我仍然无法访问扩展器属性的自定义绑定实验失败后,我发现了一个相当简单的解决方案,即声明一种指向“分页”扩展器的指针

    Products 和 Changes 都是 observableArrays 扩展了一个名为“paged”的扩展

    self.Products.Paged = ko.computed(function() {
        return self.Products['extend']('paged');
    });
    
    self.Changes.Paged = ko.computed(function() {
        return self.Changes['extend']('paged');
    });
    

    现在我可以使用无容器的“with”绑定来包含我的 _Pager 视图,该视图使用名为“paged”的扩展器的属性,现在任何由“paged”扩展的内容都可以绑定到我的 _Pager 视图

    <!-- ko with: Products.Paged -->
        @Html.Partial("_Pager",Model)
    <!-- /ko -->
    

    <!-- ko with: Changes.Paged -->
        @Html.Partial("_Pager",Model)
    <!-- /ko -->
    

    既然我已经发现了这一点,我敢打赌,可以编写一个自定义绑定来进行指向,这样就不需要将指针添加到扩展的所有内容中。相反,名为“withExtension”的自定义绑定可能会接受扩展名,从而允许

    【讨论】:

      猜你喜欢
      • 2012-11-02
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-22
      • 2014-10-01
      • 2013-07-01
      相关资源
      最近更新 更多