【问题标题】:How to debug template binding errors for KnockoutJS?如何调试 KnockoutJS 的模板绑定错误?
【发布时间】:2012-03-04 21:36:57
【问题描述】:

我一直在调试 KnockoutJS 模板中的问题。

假设我想绑定到一个名为“items”的属性,但在模板中我打错字并绑定到(不存在的)属性“item”。

使用 Chrome 调试器只会告诉我:

"item" is not defined.

是否有工具、技术或编码风格可以帮助我获得有关绑定问题的更多信息?

【问题讨论】:

    标签: javascript debugging knockout.js


    【解决方案1】:

    当某个范围内的可用数据存在问题时,我经常做的一件事是将模板/部分替换为以下内容:

    <div data-bind="text: ko.toJSON($data)"></div>
    

    或者,如果您想要一个更易读的版本:

    <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>
    

    这将吐出在该范围内绑定的数据,并让您确保您正在适当地嵌套事物。

    更新:从 KO 2.1 开始,您可以将其简化为:

    <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
    

    现在参数被传递给JSON.stringify

    【讨论】:

    • 哦。我也需要问这个问题。使用复杂的代码来控制台记录数据。现在容易多了。
    • 我必须更多地考虑调试技巧,并且可能会发表一篇博文。另一个想到的是手动订阅 observables 或计算 observables 以观察值的变化。就像name 是一个可观察到的行为name.subscribe(function(newValue) { console.log("name", newValue); });
    • 可能是因为这个答案比较陈旧,但为什么不使用 console.log 并利用调试器的全部功能来查看对象属性呢?见即:stackoverflow.com/a/16242988/647845
    • @DirkBoer - 使用 console.log 也是一个好方法。很多时候,我想在我的元素旁边看到数据,就像在foreach 场景中一样,但我发现在相关渲染标记中的页面上查看比在控制台中筛选更容易。只是视情况而定。我的更多想法在这里:knockmeout.net/2013/06/…。此外,您可能希望在绑定中记录一个“干净”版本,例如 console.log(ko.toJS(valueAccessor())
    • @RuneJeppesen - 我不确定您要序列化什么样的数据,但这样的事情可以提供帮助:knockmeout.net/2011/04/…
    【解决方案2】:

    如果您使用 Chrome 进行开发,有一个名为 Knockoutjs context debugger 的非常棒的扩展程序(我不隶属于它),它直接在开发者工具的元素面板中向您显示绑定上下文。

    【讨论】:

    • 我希望 Firefox 或 Firebug 有这个。有人知道这样的事情吗?
    • 似乎已放弃支持。如果您使用复杂的数据绑定结构,则会导致 chrome 崩溃。大约一年来我的任何项目都没有工作过。
    • 很抱歉听到这个消息,虽然我早就从 KO 转到 Ember。
    • 它(大部分)对我来说很好,而且我有一些非常复杂的结构。我还没有尝试过,但在它建议的扩展选项中,“如果您遇到崩溃,您可能有一个不可序列化的视图模型。您可以关闭序列化。”消息下方有一个复选框,用于禁用此功能。
    • 非常有用,你。
    【解决方案3】:

    在 JavaScript 库文件中的某处定义一次 bindingHandler

    ko.bindingHandlers.debug = 
    {
        init: function(element, valueAccessor) 
        {
            console.log( 'Knockoutbinding:' );
            console.log( element );
            console.log( ko.toJS(valueAccessor()) );
        }
    };
    

    而不是像这样简单地使用它:

    <ul data-bind="debug: $data">
    

    优势

    • 使用 Chrome 调试器的全部功能,例如 在元素面板中显示
    • 您不必将自定义元素添加到 DOM,仅用于调试

    【讨论】:

      【解决方案4】:

      我找到了另一个有用的。我正在调试一些绑定并尝试使用 Ryans 示例。我收到 JSON 发现循环的错误。

      <ul class="list list-fix" data-bind="foreach: detailsView().tabs">
       <li>
         <pre data-bind="text: JSON.stringify(ko.toJS($parent), null, 2)"></pre>
         <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
       </li>
      </ul>
      

      但是,使用这种方法,将数据绑定值替换为以下内容:

        <ul class="list list-fix" data-bind="foreach: detailsView().tabs">
          <li>
            <pre data-bind="text: 'click me', click: function() {debugger}"></pre>
            <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
          </li>
        </ul>
      

      现在,如果我在打开 chrome 调试窗口的同时单击 PRE 元素,我会得到一个填充良好的范围变量窗口。

      找到了一个更好的方法:

      <pre data-bind="text: ko.computed(function() { debugger; })"></pre>
      

      【讨论】:

      • 真的很有用。使用
         时遇到了淘汰循环和 Razor 标记问题。  是一个完美的解决方法。出于某种原因,像 @Html.CheckBox 这样的 RAZOR 输入破坏了 ko.toJSON。
      【解决方案5】:

      Step by step guide

      1. 对于本指南,我们将使用official KnockoutJS examples 之一。
      2. 说要查看第二个联系人背后的数据(Sensei 宫城)。
      3. 右键单击第二个联系人的第一个输入框(带有 文字“老师”)。
      4. 选择“检查元素”。 Chrome 开发者工具栏将打开。
      5. 打开 JavaScript 控制台窗口。您可以通过以下方式访问控制台 单击 Chrome 开发人员左下角的 &gt;= 图标 工具栏,或通过在 Chrome 开发人员中打开“控制台”选项卡 工具栏,或按 Ctrl+Shift+J
      6. 键入以下命令并按 Enter:ko.dataFor($0)
      7. 您现在应该看到绑定到第二行的数据。你可以 通过按对象左侧的小三角形来扩展数据 导航对象树。
      8. 键入以下命令并按 Enter:ko.contextFor($0)
      9. 您现在应该看到一个包含整个 淘汰赛上下文包括根和所有父母。这很有用 当您编写复杂的绑定表达式并且想要 尝试不同的结构。

      这是什么黑魔法?

      这个技巧是Chrome's $0-$4 featureKnockoutJS's utility methods 的组合。简而言之,Chrome 会记住您在 Chrome 开发者工具栏中选择了哪些元素,并在别名 $0$1$2$3$4 下公开这些元素。因此,当您在浏览器中右键单击一个元素并选择“检查元素”时,该元素会自动在别名 $0 下可用。您可以将此技巧与 KnockoutJS、AngularJS、jQuery 或任何其他 JavaScript 框架一起使用。

      诀窍的另一面是 KnockoutJS 的实用方法 ko.dataFor 和 ko.contextFor:

      • ko.dataFor(element) - 返回可用于绑定的数据 反对元素
      • ko.contextFor(element) - 返回整个绑定上下文 可用于 DOM 元素。

      请记住,Chrome 的 JavaScript 控制台是一个功能齐全的 JavaScript 运行时环境。这意味着您不仅限于查看变量。您可以存储ko.contextFor 的输出并直接从控制台操作视图模型。试试var root = ko.contextFor($0).$root; root.addContact(); 看看会发生什么:-)

      调试愉快!

      【讨论】:

        【解决方案6】:

        看看我使用的一个非常简单的东西:

        function echo(whatever) { debugger; return whatever; }
        

        或者

        function echo(whatever) { console.log(whatever); return whatever; }
        

        然后在 html 中,你有:

        <div data-bind="text: value"></div>
        

        替换为

        <div data-bind="text: echo(value)"></div>
        

        更高级:

        function echo(vars, member) { console.log(vars); debugger; return vars[0][member]; }
        
        <div data-bind="text: echo([$data, $root, $parents, $parentContext], 'value')"></div>
        

        享受:)

        更新

        另一个烦人的事情是当你试图绑定到一个未定义的值时。想象在上面的示例中,数据对象只是 {} 而不是 { value: 'some text' }。在这种情况下,你会遇到麻烦,但通过以下调整你会没事的:

        <div data-bind="text: $data['value']"></div> 
        

        【讨论】:

          【解决方案7】:

          我创建了一个名为 knockthrough.js 的 github 项目来帮助可视化这些错误。

          https://github.com/JonKragh/knockthrough

          它突出显示绑定错误并提供该节点上数据上下文的转储。

          你可以在这里玩一个示例:http://htmlpreview.github.io/?https://github.com/JonKragh/knockthrough/blob/master/default.htm

          感谢 RP Niemeyer,他在 SO 上出色的 Knockout 代码示例让我走到了这一步。

          【讨论】:

            【解决方案8】:

            查看传递给绑定的数据的最简单方法是将数据拖放到控制台:

            <div data-bind="text: console.log($data)"></div>
            

            Knockout 将评估文本绑定的值(实际上可以在此处使用任何绑定)并将 $data 刷新到控制台浏览器面板。

            【讨论】:

              【解决方案9】:

              所有其他答案都很好,我只是添加我喜欢做的事情:

              在您的视图中(假设您已经绑定了一个 ViewModel):

              <div data-bind="debugger: $data"></div>
              

              淘汰码:

              ko.bindingHandlers.debugger = {
                  init: function (element, valueAccessor) {
                      debugger;
                  }
              }
              

              这将暂停调试器中的代码,elementvalueAccessor() 将包含有价值的信息。

              【讨论】:

              【解决方案10】:

              如果你在 Visual Studio 和 IE 中开发,我更喜欢 data-bind="somebinding:(function(){debugger; return bindvalue; })()" 我更喜欢 echo 函数,因为它会转到带有所有绑定的脚本而不是 eval 文件,你可以只看 $上下文 $data(我也在 Chrome 中使用它);

              【讨论】:

              • 我敢打赌这与 Visual Studio 或 IE 无关。
              • @Serhiy 与 chrome 相同,但在 chrome 中我认为您可以在没有它的情况下访问该文件我认为您无法在 VS 中访问该文件。
              【解决方案11】:

              这对我有用:

              <div data-bind="text: function(){ debugger; }()"></div>
              

              【讨论】:

                【解决方案12】:

                如果您在 Magento2 项目中使用 KnockoutJS,您可以使用 Magento 的自定义 afterRender 绑定:

                <div afterRender="function (target, viewModel) {
                    console.log('Rendered element:', target);
                    console.log('Associated view model:', viewModel);
                    console.log(this === viewModel);
                }"></div> 
                

                【讨论】:

                  【解决方案13】:

                  此答案基于 Dirk Boer 的答案。我添加到他的处理程序,以便它在更新时也显示数据:

                  ko.bindingHandlers.debug = 
                  {
                      init: function(element, valueAccessor) 
                      {
                          console.log( 'Knockoutbinding (init):', element, ko.toJS(valueAccessor()));
                      },
                      update: function(element, valueAccessor)
                      {
                          console.log( 'Knockoutbinding (update):', element, ko.toJS(valueAccessor()));
                      }
                  };
                  

                  然后,您所要做的就是在您的 HTML 代码中添加这样的绑定:

                  <div data-bind="debug: $data">
                  

                  当console.log初始化或更新时,你会在它看到数据。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-10-18
                    • 1970-01-01
                    • 2011-02-28
                    • 2012-03-07
                    • 2011-07-12
                    相关资源
                    最近更新 更多