我在KnockoutJS模板中调试问题时一直感到困扰。
比如,我想绑定一个名为"items
"的属性,但在模板中我打错了字,绑定到了(不存在的)属性"item
"。
使用Chrome调试器只告诉我:
"item"未定义。
是否有工具、技巧或编码风格可以帮助我获得有关绑定问题更多信息?
我在KnockoutJS模板中调试问题时一直感到困扰。
比如,我想绑定一个名为"items
"的属性,但在模板中我打错了字,绑定到了(不存在的)属性"item
"。
使用Chrome调试器只告诉我:
"item"未定义。
是否有工具、技巧或编码风格可以帮助我获得有关绑定问题更多信息?
当特定范围内可用数据存在问题时,我经常使用替换模板/部分的方式来解决,例如:
<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
函数。
如果您在进行开发时使用 Chrome 浏览器,有一个非常好的扩展(我与之无关)称为Knockoutjs上下文调试,它可以直接在开发者工具的元素面板中显示绑定上下文。
在你的 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">
优点
我发现另一个可能有用的解决方法。我正在调试某些绑定,尝试使用Ryan的示例。结果我收到了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>
但是,使用这种方法,我将data-bind的值替换为以下内容:
<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>
>=
图标或打开 Chrome 开发者工具栏中的“控制台”选项卡或按下 Ctrl+Shift+J 来访问控制台。ko.dataFor($0)
ko.contextFor($0)
这个技巧是Chrome的$0-$4功能和KnockoutJS的实用方法的组合。简而言之,Chrome会记住你在Chrome开发者工具栏中选择的元素,并将这些元素暴露在别名$0
、$1
、$2
、$3
、$4
下。因此,当您右键单击浏览器中的元素并选择“检查元素”时,该元素自动成为别名$0
下可用的元素。您可以将此技巧与KnockoutJS、AngularJS、jQuery或任何其他JavaScript框架一起使用。
这个技巧的另一面是KnockoutJS的实用方法ko.dataFor和ko.contextFor:
ko.dataFor(element)
- 返回可用于绑定元素的数据ko.contextFor(element)
- 返回可用于DOM元素的整个绑定上下文。ko.contextFor
的输出并直接从控制台操作视图模型。尝试var root = ko.contextFor($0).$root; root.addContact();
,看看会发生什么:-)看看我使用的一个非常简单的东西:
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>
最简单的方法是将数据放到控制台中以查看传递给绑定的数据:
<div data-bind="text: console.log($data)"></div>
其他答案都很好,我只是想分享一下我的做法:
在你的视图中(假设你已经绑定了一个ViewModel):
<div data-bind="debugger: $data"></div>
ko.bindingHandlers.debugger = {
init: function (element, valueAccessor) {
debugger;
}
}
执行此操作将暂停调试器中的代码,element
和 valueAccessor()
将包含有价值的信息。
data-bind="somebinding:(function(){debugger; return bindvalue; })()"
。我比较喜欢它而不是echo函数,因为它会将所有绑定传递到脚本中,而不是eval文件,您可以查看$context $data(我在Chrome中也使用它)。
name
是一个可观察的对象,可以执行name.subscribe(function(newValue) { console.log("name", newValue); });
。 - RP Niemeyerforeach
场景中,我发现在相关的渲染标记中更容易看到它,而不是在控制台中查找。这取决于情况。这里有一些我的想法:http://www.knockmeout.net/2013/06/knockout-debugging-strategies-plugin.html。此外,您可能还想在绑定中记录“干净”的版本,例如`console.log(ko.toJS(valueAccessor())`。 - RP Niemeyerdata-bind="text: console.log($data)"
来浏览绑定的对象,从而实现此操作。 - Grirg