首页 文章

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

提问于
浏览
193

我一直在调试KnockoutJS模板中的问题 .

假设我想绑定到名为“ items " but in the template I make a typo and bind to the (non existing) property " item ”的属性 .

使用Chrome调试器只会告诉我:

“item”未定义 .

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

10 回答

  • 7

    当某个范围内的数据存在问题时,我常常做的一件事是用以下内容替换模板/部分:

    <div data-bind="text: ko.toJSON($data)"></div>
    

    或者,如果您想要更易读的版本:

    <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>
    

    这将吐出在该范围内绑定的数据,并确保您正确地嵌套事物 .

    Update: as of KO 2.1 ,您可以将其简化为:

    <pre data-bind="text: ko.toJSON($data, null, 2)"></pre>
    

    现在参数传递给 JSON.stringify .

  • 60

    分步指南

    • 对于本指南,我们将使用official KnockoutJS examples之一 .

    • 假设您想查看第二个联系人(Sensei Miyagi)背后的数据 .

    • 右键单击第二个联系人的第一个输入框(文本为'Sensei'的那个) .

    • 选择'Inspect element' . Chrome开发者工具栏将会打开 .

    • 打开JavaScript控制台窗口 . 您可以通过点击Chrome开发者工具栏左下角的 >= 图标,或打开Chrome开发者工具栏中的"Console"标签,或按Ctrl Shift J来访问控制台

    • 输入以下命令并按Enter键: ko.dataFor($0)

    • 您现在应该看到绑定到第二行的数据 . 您可以通过按对象左侧的小三角形来展开数据以导航对象树 .

    • 输入以下命令并按Enter键: ko.contextFor($0)

    • 您现在应该看到一个包含整个Knockout上下文的复杂对象,包括root和所有父项 . 当您编写复杂的绑定表达式并且想要尝试不同的构造时,这非常有用 .

    Example output when following above guide

    这是什么黑魔法?

    这个技巧是Chrome's $0-$4 featureKnockoutJS's utility methods的组合 . 简而言之,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 的输出并直接从控制台操作viewmodel . 试试 var root = ko.contextFor($0).$root; root.addContact(); ,看看会发生什么:-)

    快乐的调试!

  • 335

    如果您正在使用Chrome进行开发,那么有一个名为Knockoutjs context debugger的非常棒的扩展(我不隶属于它),可直接在开发人员工具的“元素”面板中显示绑定上下文 .

  • 1

    我找到了另一个可以帮助的人 . 我正在调试一些绑定并尝试使用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>
    

    但是,使用此方法,将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>
    
  • 5

    看看我用的 really simple

    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>
    

    More advanced:

    function echo(vars, member) { console.log(vars); debugger; return vars[0][member]; }
    
    <div data-bind="text: echo([$data, $root, $parents, $parentContext], 'value')"></div>
    

    请享用 :)

    UPDATE

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

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

    The easiest way 查看传递给绑定的数据是将数据丢弃到控制台:

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

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

  • 1

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

    https://github.com/JonKragh/knockthrough

    它突出显示绑定错误,并在该节点上转储datacontext .

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

    enter image description here

    感谢RP Niemeyer在SO上提供了出色的Knockout代码示例,让我了解到这一点 .

  • 35

    Define a bindingHandler once ,JavaScript库文件中的某个位置 .

    ko.bindingHandlers.debug = 
    {
        init: function(element, valueAccessor) 
        {
            console.log( 'Knockoutbinding:' );
            console.log( element );
            console.log( ko.toJS(valueAccessor()) );
        }
    };
    

    而不是简单地使用它喜欢这样:

    <ul data-bind="debug: $data">
    

    Advantages

    • 使用Chrome调试器的全部功能,例如“元素面板中的显示”

    • 你不必将自定义元素添加到DOM中,仅用于调试

    enter image description here

  • 31

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

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

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

    淘汰赛代码:

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

    这将暂停调试器中的代码, elementvalueAccessor() 将包含有 Value 的信息 .

  • 2

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

相关问题