【发布时间】:2012-03-04 21:36:57
【问题描述】:
我一直在调试 KnockoutJS 模板中的问题。
假设我想绑定到一个名为“items”的属性,但在模板中我打错字并绑定到(不存在的)属性“item”。
使用 Chrome 调试器只会告诉我:
"item" is not defined.
是否有工具、技术或编码风格可以帮助我获得有关绑定问题的更多信息?
【问题讨论】:
标签: javascript debugging knockout.js
我一直在调试 KnockoutJS 模板中的问题。
假设我想绑定到一个名为“items”的属性,但在模板中我打错字并绑定到(不存在的)属性“item”。
使用 Chrome 调试器只会告诉我:
"item" is not defined.
是否有工具、技术或编码风格可以帮助我获得有关绑定问题的更多信息?
【问题讨论】:
标签: javascript debugging knockout.js
当某个范围内的可用数据存在问题时,我经常做的一件事是将模板/部分替换为以下内容:
<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。
【讨论】:
name 是一个可观察到的行为name.subscribe(function(newValue) { console.log("name", newValue); });
foreach 场景中一样,但我发现在相关渲染标记中的页面上查看比在控制台中筛选更容易。只是视情况而定。我的更多想法在这里:knockmeout.net/2013/06/…。此外,您可能希望在绑定中记录一个“干净”版本,例如 console.log(ko.toJS(valueAccessor())。
如果您使用 Chrome 进行开发,有一个名为 Knockoutjs context debugger 的非常棒的扩展程序(我不隶属于它),它直接在开发者工具的元素面板中向您显示绑定上下文。
【讨论】:
在 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">
优势
【讨论】:
我找到了另一个有用的。我正在调试一些绑定并尝试使用 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>
【讨论】:
>= 图标
工具栏,或通过在 Chrome 开发人员中打开“控制台”选项卡
工具栏,或按 Ctrl+Shift+J
ko.dataFor($0)
ko.contextFor($0)
这个技巧是Chrome's $0-$4 feature 和KnockoutJS'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(); 看看会发生什么:-)
调试愉快!
【讨论】:
看看我使用的一个非常简单的东西:
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>
【讨论】:
我创建了一个名为 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 代码示例让我走到了这一步。
【讨论】:
查看传递给绑定的数据的最简单方法是将数据拖放到控制台:
<div data-bind="text: console.log($data)"></div>
Knockout 将评估文本绑定的值(实际上可以在此处使用任何绑定)并将 $data 刷新到控制台浏览器面板。
【讨论】:
所有其他答案都很好,我只是添加我喜欢做的事情:
在您的视图中(假设您已经绑定了一个 ViewModel):
<div data-bind="debugger: $data"></div>
淘汰码:
ko.bindingHandlers.debugger = {
init: function (element, valueAccessor) {
debugger;
}
}
这将暂停调试器中的代码,element 和 valueAccessor() 将包含有价值的信息。
【讨论】:
如果你在 Visual Studio 和 IE 中开发,我更喜欢 data-bind="somebinding:(function(){debugger; return bindvalue; })()" 我更喜欢 echo 函数,因为它会转到带有所有绑定的脚本而不是 eval 文件,你可以只看 $上下文 $data(我也在 Chrome 中使用它);
【讨论】:
这对我有用:
<div data-bind="text: function(){ debugger; }()"></div>
【讨论】:
如果您在 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>
【讨论】:
此答案基于 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初始化或更新时,你会在它看到数据。
【讨论】: