如何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
一步一步的指导
- 对于本指南,我们将使用官方的KnockoutJS示例之一 。
- 假设您想查看第二个联系人(Sensei Miyagi)背后的数据。
- 右键单击第二个联系人的第一个input框(使用文本“Sensei”)。
- select“检查元素”。 Chrome开发者工具栏将打开。
- 打开JavaScript控制台窗口。 您可以通过点击Chrome开发者工具栏左下angular的
>=
图标,或者打开Chrome开发者工具栏中的“控制台”标签,或按Ctrl + Shift + J来访问控制台 - input以下命令并按Enter键:
ko.dataFor($0)
- 您现在应该看到绑定到第二行的数据。 您可以通过按下对象左侧的小三angular来浏览对象树来展开数据。
- input以下命令并按Enter键:
ko.contextFor($0)
- 您现在应该看到一个复杂的对象,其中包含整个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器中的代码,而element
和valueAccessor()
将包含有价值的信息。