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

我在调试KnockoutJS模板中的问题时一直遇到麻烦。

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

使用Chrome调试器只告诉我:

"item" is not defined.

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

69604 次浏览

我经常做的一件事是,当在某个范围内存在数据可用的问题时,将模板/节替换为如下内容:

<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

我找到了另一个有用的方法。我正在调试一些绑定,并尝试使用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>

但是,使用这种方法a将数据绑定值替换为以下内容:

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

现在如果我点击PRE元素,同时有chrome调试窗口打开,我得到一个很好的填充范围变量窗口。

找到了一个更好的方法:

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

看看我使用的很简单的东西:

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>

享受:)

更新

另一个恼人的事情是当你试图绑定到一个未定义的值。在上面的例子中,假设数据对象只是{}not {value: 'some text'}。在这种情况下,你会遇到麻烦,但通过以下调整,你会没事的:

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

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

https://github.com/JonKragh/knockthrough

它突出显示绑定错误,并提供该节点上的数据上下文的转储。

你可以在这里使用一个示例:http://htmlpreview.github.io/?https://github.com/JonKragh/knockthrough/blob/master/default.htm

enter image description here

感谢RP Niemeyer,他在SO上出色的Knockout代码示例让我走到这一步。

定义一次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">

优势

  • 使用Chrome调试器的全部功能,如在元素面板中显示
  • 您不必向DOM添加自定义元素,只是为了调试

enter image description here

如果你正在使用Chrome进行开发,有一个非常棒的扩展(我没有加入)称为Knockoutjs上下文调试器,它直接在开发人员工具的元素面板中向你显示绑定上下文。

< a href = " http://devillers。nl/quick-debug -knockoutjs-in-chrome/" rel="noreferrer">Step by Step guide .

    在本指南中,我们将使用官方KnockoutJS之一 李示例< / >。< / >
  1. 说你想看第二个联系人背后的数据(老师 李宫城)。< / >
  2. 右键单击第二个联系人的第一个输入框 文本'Sensei')。
  3. 选择“Inspect element”。Chrome开发工具栏将打开。
  4. 打开JavaScript控制台窗口。您可以通过 点击Chrome开发器左下角的>=图标 工具栏,或者打开“控制台”;选项卡在Chrome开发人员 工具栏,或按Ctrl+转变+J
  5. 输入以下命令,按“Enter”
  6. 您现在应该看到绑定到第二行的数据。你可以 通过按对象左边的小三角形来展开数据
  7. 输入以下命令,按“Enter”
  8. 您现在应该看到一个包含整个 敲除上下文包括根和所有父。这很有用 当你在编写复杂的绑定表达式时,你想

Example output when following above guide

这是什么黑魔法?

这个技巧是Chrome的0- 4美元功能KnockoutJS的实用程序方法的组合。简而言之,Chrome会记住你在Chrome开发工具栏中选择了哪些元素,并在别名$0$1$2$3$4下公开这些元素。因此,当你在浏览器中右键单击一个元素并选择“Inspect element”时,该元素自动以别名$0可用。你可以在KnockoutJS, AngularJS, jQuery或任何其他JavaScript框架中使用这个技巧。

诀窍的另一方面是KnockoutJS的实用程序方法ko。dataFor和ko.contextFor:

  • ko.dataFor(element) -返回可供绑定的数据 对应元素
  • ko.contextFor(element) -返回整个绑定上下文
  • . xml

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

调试快乐!

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

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

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

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

所有其他的答案都很好,我只是添加了我喜欢做的事情:

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

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

淘汰赛代码:

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

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

这对我来说很管用:

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

如果你在Magento项目中使用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时,您将在console.log中看到数据。