我在调试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。


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

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> 

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

https://github.com/JonKragh/knockthrough

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

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

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


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

优势

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


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


循序渐进指南

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 ();看看会发生什么:-)

调试快乐!


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

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

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


如果你是在Visual studio和IE中开发,我更喜欢这样data-bind="somebinding:(函数(){调试器;返回bindvalue;}) ()我喜欢它比echo函数,因为它会去脚本与所有的绑定,而不是eval文件,你可以只看$context $data(我在Chrome中也使用这个);


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

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

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

淘汰赛代码:

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

这将暂停调试器中的代码,element和valueAccessor()将包含有价值的信息。


这对我来说很管用:

<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中看到数据。