Bắt "Không thể đọc thuộc tính 'nodeType' của null" khi gọi ko.applyBindings


99

Tôi có mã loại trực tiếp này:

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());

Html này:

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

Ví dụ này giống với ví dụ được tìm thấy trên trang web Knockout, nhưng khi tôi chạy nó, nó trả về thông báo này trên Chrome Fire Bug:

Uncaught TypeError: Không thể đọc thuộc tính 'nodeType' của null

Cái này liên quan đến tệp loại trực tiếp và dòng này trong tập lệnh của tôi:

ko.applyBindings(new TaskListViewModel());

Và lỗi này chỉ đến dòng này (1766) trên loại trực tiếp:

var isElement = (nodeVerified.nodeType == 1);

Tôi đang làm gì sai?


Lỗi đánh máy đó sẽ gây ra lỗi SyntaxError. Việc sửa lỗi chính tả có khắc phục được sự cố không?
James Allardice

Rất tiếc ... Tôi đã cập nhật câu hỏi vì một lỗi khác đến.
Gerep

Câu trả lời:


176

Sự cố này đã xảy ra vì tôi đang cố gắng liên kết một HTMLphần tử trước khi nó được tạo.

Tập lệnh của tôi đã được tải trên đầu HTML(trong đầu) nhưng nó cần được tải ở cuối HTMLmã của tôi (ngay trước thẻ nội dung đóng).

Cảm ơn sự quan tâm của bạn James Allardice .

Một giải pháp khả thi đang sử dụng defer="defer"

<script src="script.js" type="text/javascript" defer="defer"></script>

Sử dụng điều này nếu tập lệnh sẽ không tạo ra bất kỳ nội dung tài liệu nào. Điều này sẽ cho trình duyệt biết rằng nó có thể đợi nội dung được tải trước khi tải tập lệnh.

Đọc thêm .

Hy vọng nó giúp.


4
Để nhấn mạnh: <script ...>Thẻ cần phải ở cuối trang, ngay trước </body>thẻ đóng .
aliteralmind

1
tuyệt vời, cảm ơn! Tôi vừa chuyển kịch bản của mình đến cuối nội dung và nó hoạt động hoàn hảo. nhiều độ cao
Eleanor Zimmermann

33

Bạn có thể muốn xem xét sử dụng trình xử lý sẵn sàng jquery cho việc này

$(function() {
   function TaskListViewModel() {
   ...
   ko.applyBindings(new TaskListViewModel());
});

Sau đó, bạn đạt được hai điều:

  1. Tránh làm ô nhiễm không gian tên chung
  2. Liên kết Knockout xảy ra SAU KHI DOM được tạo. Bạn có thể đặt javascript của mình bất cứ nơi nào nó phù hợp với tổ chức.

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


1
Spoiler cảnh báo cho những người không RTM: $(handler)tương đương với$(document).ready(handler)
Brock Hensley

21

nếu bạn có jQuery đặt áp dụng ràng buộc bên trong onload để loại bỏ tìm kiếm DOM khi DOM đã sẵn sàng.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});

đóng đinh nó, btw tôi có thể bao gồm các ràng buộc khác trên khối tài liệu không?
Allan Jikamu

1
Cảm ơn thông tin của bạn!!
karthik

5

Bạn có một lỗi chính tả đơn giản:

self.addTask = fuction() {

Nên là:

self.addTask = function() { //Notice the added 'n' in 'function'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.