Получение «Невозможно прочитать свойство 'nodeType' of null» при вызове ko.applyBindings

99

У меня есть этот нокаут-код:

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:

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

Пример такой же, как и на веб-сайте Knockout, но когда я его запускаю, он возвращает это сообщение в Chrome Fire Bug:

Uncaught TypeError: невозможно прочитать свойство nodeType, равное null

Это связано с файлом нокаута и этой строкой моего скрипта:

ko.applyBindings(new TaskListViewModel());

И эта ошибка указывает на эту строку (1766) на нокауте:

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

Что я делаю не так?

Гереп
источник
Эта опечатка приведет к ошибке SyntaxError. Устраняет ли проблему исправление опечатки?
Джеймс Аллардис,
Да ... Я обновил вопрос, потому что пришла другая ошибка.
Гереп

Ответы:

176

Эта проблема возникла из-за того, что я пытался привязать HTMLэлемент до его создания.

Мой скрипт был загружен поверх HTML(в голове), но его нужно было загрузить в нижней части моего HTMLкода (непосредственно перед закрывающим тегом тела).

Спасибо за внимание Джеймс Аллардис .

Возможный обходной путь - использование defer="defer"

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

Используйте это, если скрипт не собирается генерировать какое-либо содержимое документа. Это сообщит браузеру, что он может дождаться загрузки содержимого перед загрузкой скрипта.

Дальнейшее чтение .

Надеюсь, поможет.

Гереп
источник
4
Подчеркнем: <script ...>тег должен находиться внизу страницы, непосредственно перед закрывающим </body>тегом.
aliteralmind
1
замечательно, спасибо! Я просто переместил свой сценарий в конец тела, и он отлично сработал. много благодарностей
Элеонора Циммерманн
33

Возможно, вы захотите использовать для этого обработчик jquery ready

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

Тогда вы добьетесь двух вещей:

  1. Избегайте загрязнения глобального пространства имен
  2. Нокаут-привязка происходит ПОСЛЕ создания DOM. Вы можете разместить свой javascript везде, где это удобно для организации.

См. Http://api.jquery.com/ready/

Джеймс Кесслер
источник
1
Спойлер для тех, кто не делал RTM: $(handler)эквивалент$(document).ready(handler)
Brock Hensley
21

если у вас есть jQuery, установите привязку внутри, onloadчтобы нокаут искал DOM, когда DOM готов.

$(document).ready(function(){
    ko.applyBindings(new TaskListViewModel());
});
Джанкар Махбуб
источник
прибил его, кстати, могу ли я включить другие привязки в блок документа?
Аллан Джикаму 06
1
Спасибо за информацию !!
karthik
5

У вас простая орфографическая ошибка:

self.addTask = fuction() {

Должно быть:

self.addTask = function() { //Notice the added 'n' in 'function'
Джеймс Аллардис
источник