调用ko.applyBindings时,"无法读取属性'nodeType'为null"

Ger*_*rep 99 javascript knockout.js

我有这个淘汰代码:

function Task(data) {
    this.title = ko.observable(data.title);
    this.isDone = ko.observable(data.isDone);
}

function TaskListViewModel() {
    // Data
    var self = this;
    self.tasks = ko.observableArray([]);
    self.newTaskText = ko.observable();
    self.incompleteTasks = ko.computed(function() {
        return ko.utils.arrayFilter(self.tasks(), function(task) { return !task.isDone() });
    });

    // Operations
    self.addTask = function() {
        self.tasks.push(new Task({ title: this.newTaskText() }));
        self.newTaskText("");
    };
    self.removeTask = function(task) { self.tasks.remove(task) };
}

ko.applyBindings(new TaskListViewModel());
Run Code Online (Sandbox Code Playgroud)

这个html:

<head>
    <script type="text/javascript" src="jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="knockout-2.0.0.js"></script>
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
    <h3>Tasks</h3>

    <form data-bind="submit: addTask">
        Add task: <input data-bind="value: newTaskText" placeholder="What needs to be done?" />
        <button type="submit">Add</button>
    </form>

    <ul data-bind="foreach: tasks, visible: tasks().length > 0">
        <li>
            <input type="checkbox" data-bind="checked: isDone" />
            <input data-bind="value: title, disable: isDone" />
            <a href="#" data-bind="click: $parent.removeTask">Delete</a>
        </li> 
    </ul>

    You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s)
    <span data-bind="visible: incompleteTasks().length == 0"> - it's beer time!</span>
</body>
Run Code Online (Sandbox Code Playgroud)

该示例与Knockout网站上的示例相同,但是当我运行它时,它会在Chrome Fire Bug上返回此消息:

未捕获的TypeError:无法读取null的属性"nodeType"

这个与淘汰文件和我的脚本的这一行有关:

ko.applyBindings(new TaskListViewModel());
Run Code Online (Sandbox Code Playgroud)

这个错误指向淘汰赛的这一行(1766):

var isElement = (nodeVerified.nodeType == 1);
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Ger*_*rep 175

这个问题发生了,因为我试图HTML在创建元素之前绑定它.

我的脚本被加载到HTML(在头部)的顶部,但它需要加载到我的HTML代码的底部(就在关闭正文标记之前).

感谢您的关注James Allardice.

可能的解决方法是使用 defer="defer"

<script src="script.js" type="text/javascript" defer="defer"></script>
Run Code Online (Sandbox Code Playgroud)

如果脚本不会生成任何文档内容,请使用此选项.这将告诉浏览器它可以在加载脚本之前等待加载内容.

进一步阅读.

希望能帮助到你.

  • 要强调:`<script ...>`标签需要位于页面底部,就在关闭`</ body>`标签之前. (4认同)

Jam*_*ler 33

您可能需要考虑使用jquery ready处理程序

$(function() {
   function TaskListViewModel() {
   ...
   ko.applyBindings(new TaskListViewModel());
});
Run Code Online (Sandbox Code Playgroud)

然后你实现了两件事:

  1. 避免污染全局命名空间
  2. 在创建DOM之后发生敲除绑定.您可以将javascript放在适合组织的任何地方.

http://api.jquery.com/ready/


Jha*_*bub 21

如果你有jQuery把apply绑定放在里面,onload那么当DOM准备好时,knockout会查找DOM.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});
Run Code Online (Sandbox Code Playgroud)


Jam*_*ice 5

你有一个简单的拼写错误:

self.addTask = fuction() {
Run Code Online (Sandbox Code Playgroud)

应该:

self.addTask = function() { //Notice the added 'n' in 'function'
Run Code Online (Sandbox Code Playgroud)