如何调试KnockoutJS的模板绑定错误?

时间:2012-02-13 13:23:42

标签: debugging knockout.js

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

假设我想要绑定到名为“items”的属性,但在模板中我输入拼写错误并绑定到(不存在的)属性“item”。

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

  

"item" is not defined.

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

13 个答案:

答案 0 :(得分:338)

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

<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

答案 1 :(得分:60)

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

答案 2 :(得分:35)

在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添加自定义元素,仅用于调试

enter image description here

答案 3 :(得分:32)

我找到了另一个可以帮助的人。我正在调试一些绑定并尝试使用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>

答案 4 :(得分:17)

Step by step guide

  1. 对于本指南,我们将使用其中一个official KnockoutJS examples
  2. 假设您想查看第二个联系人背后的数据(Sensei 宫城)。
  3. 右键单击第二个联系人的第一个输入框(带有的第一个输入框) 文字'Sensei')。
  4. 选择“检查元素”。 Chrome开发者工具栏将会打开。
  5. 打开JavaScript控制台窗口。您可以通过访问控制台 点击Chrome开发者左下角的>=图标 工具栏,或打开Chrome Developer中的“控制台”标签 工具栏,或按 Ctrl + Shift + J
  6. 键入以下命令,然后按Enter:ko.dataFor($0)
  7. 您现在应该看到绑定到第二行的数据。您可以 按对象左侧的小三角形展开数据 导航对象树。
  8. 键入以下命令,然后按Enter:ko.contextFor($0)
  9. 您现在应该看到一个包含整个对象的复杂对象 敲除上下文,包括根和所有父母。这很有用 当你编写复杂的绑定表达式时,你想要 尝试不同的结构。
  10. Example output when following above guide

    这是什么黑魔法?

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

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

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

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

    快乐的调试!

答案 5 :(得分:7)

查看我使用的非常简单的内容:

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> 

答案 6 :(得分:5)

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

https://github.com/JonKragh/knockthrough

它突出显示绑定错误,并在该节点上转储datacontext。

您可以在此处播放示例:http://htmlpreview.github.io/?https://github.com/JonKragh/knockthrough/blob/master/default.htm

enter image description here

感谢RP Niemeyer在SO上提供了出色的Knockout代码示例,以帮助我达到这一点。

答案 7 :(得分:3)

查看将哪些数据传递给绑定的最简单方法是将数据删除到控制台:

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

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

答案 8 :(得分:2)

所有其他答案都会很有效,我只想添加我喜欢的内容:

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

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

淘汰赛代码:

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

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

答案 9 :(得分:1)

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

答案 10 :(得分:0)

这对我有用:

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

答案 11 :(得分:0)

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

     await AsyncStorage.clear();
     //props.navigation.navigate('Auth');
     dispatch(setToken(null));

答案 12 :(得分:0)

此答案基于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中看到数据。