如何debuggingKnockoutJS的模板绑定错误?

在KnockoutJS模板中,我一直遇到debugging问题。

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

使用Chromedebugging器只告诉我:

"item" is not defined.

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

在某个范围内有什么数据可用时,我经常做的一件事就是用类似下面的代替模板/部分:

 <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> 

现在parameter passing给JSON.stringify

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

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

但是,使用这种方法,将数据绑定值replace为以下值:

  <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> 

现在,如果在打开Chromedebugging窗口的同时点击PRE元素,我会得到一个很好的范围variables窗口。

find一个更好的方法:

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

定义一个bindingHandler ,在你的JavaScript库文件的某个地方。

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

比简单地使用它喜欢这个:

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

优点

  • 使用Chromedebugging器的全部function,如“ 元素面板”中的“显示”
  • 您不必将自定义元素添加到您的DOM,只是为了debugging

在这里输入图像说明

一步一步的指导

  1. 对于本指南,我们将使用官方的KnockoutJS示例之一 。
  2. 假设您想查看第二个联系人(Sensei Miyagi)背后的数据。
  3. 右键单击第二个联系人的第一个input框(使用文本“Sensei”)。
  4. select“检查元素”。 Chrome开发者工具栏将打开。
  5. 打开JavaScript控制台窗口。 您可以通过点击Chrome开发者工具栏左下angular的>=图标,或者打开Chrome开发者工具栏中的“控制台”标签,或按Ctrl + Shift + J来访问控制台
  6. input以下命令并按Enter键: ko.dataFor($0)
  7. 您现在应该看到绑定到第二行的数据。 您可以通过按下对象左侧的小三angular来浏览对象树来展开数据。
  8. input以下命令并按Enter键: ko.contextFor($0)
  9. 您现在应该看到一个复杂的对象,其中包含整个Knockout上下文,包括根和所有父项。 当你正在编写复杂的绑定expression式,并且你想用不同的结构进行实验时,这是非常有用的。

遵循以上指南时的示例输出

这是什么黑魔法?

这个技巧结合了Chrome的$ 0- $ 4特性和KnockoutJS的实用方法 。 简而言之,Chrome会记住您在Chrome开发人员工具栏中select的元素,并在别名$0$1$2$3$4下公开这些元素。 所以当你在浏览器中右键点击一个元素并select“检查元素”时,这个元素自动地在别名$0下变得可用。 您可以使用KnockoutJS,AngularJS,jQuery或任何其他JavaScript框架的这个技巧。

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

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

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

快乐debugging!

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

 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> 

请享用 :)

UPDATE

另一个恼人的事情是当你试图绑定到一个未定义的值。 想象一下,在上面的例子中,数据对象只是不是{值:'一些文本'}。 在这种情况下,你会遇到麻烦,但通过下面的调整,你会好起来的:

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

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

https://github.com/JonKragh/knockthrough

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

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

在这里输入图像说明

感谢RP Niemeyer在SO上的出色的Knockout代码示例,以帮助我理解这一点。

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

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

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

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

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

在你看来(假设你已经绑定了ViewModel):

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

挖掘代码:

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

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