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

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

使用Chrome调试器只告诉我:

“item”没有定义。

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


当前回答

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

function echo(whatever) { debugger; return whatever; }

Or

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> 

其他回答

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

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

如果你在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> 

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

function echo(whatever) { debugger; return whatever; }

Or

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> 

循序渐进指南

For this guide, we will be using one of the official KnockoutJS examples. Say you want to see the data behind the second contact (Sensei Miyagi). Right-click the first input box of the second contact (the one with the text 'Sensei'). Select 'Inspect element'. The Chrome Developer Toolbar will open. Open the JavaScript Console window. You can access the console by clicking the >= icon in the bottom-left of the Chrome Developer Toolbar, or by opening the "Console" tab in the Chrome Developer Toolbar, or by pressing Ctrl+Shift+J Type the following command and press Enter: ko.dataFor($0) You should now see the data that is bound to the second row. You can expand the data by pressing the little triangle left of the Object to navigate the object tree. Type the following command and press Enter: ko.contextFor($0) You should now see a complex object that contains the entire Knockout context including the root and all parents. This is useful when you are writing complex binding expressions and you want to experiment with different constructs.

这是什么黑魔法?

这个技巧是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) -返回被绑定的整个绑定上下文 DOM元素可用。

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

调试快乐!