ko.applyBindings를 호출 할 때“Cannot read property 'nodeType'of null”발생


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에 다음 메시지가 반환됩니다.

포착되지 않은 TypeError : null의 'nodeType'속성을 읽을 수 없습니다.

이것은 녹아웃 파일과 내 스크립트의 다음 줄과 관련이 있습니다.

ko.applyBindings(new TaskListViewModel());

그리고이 오류는 녹아웃에서이 줄 (1766)을 가리 킵니다.

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

내가 뭘 잘못하고 있죠?


그 오타로 인해 SyntaxError가 발생합니다. 오타를 수정하면 문제가 해결 되나요?
James Allardice 2012

예 ... 다른 오류가 발생하여 질문을 업데이트했습니다.
Gerep

답변:


176

이 문제는 HTML요소가 생성되기 전에 바인딩을 시도했기 때문에 발생 했습니다.

내 스크립트는 맨 위에로드 HTML되었지만 내 HTML코드 맨 아래 (닫는 body 태그 바로 앞)에 로드되어야했습니다 .

관심을 가져 주셔서 감사합니다 . James Allardice .

가능한 해결 방법은 다음을 사용하는 것입니다. defer="defer"

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

스크립트가 문서 내용을 생성하지 않을 경우이를 사용하십시오. 이렇게하면 스크립트를로드하기 전에 콘텐츠가로드 될 때까지 기다릴 수 있음을 브라우저에 알립니다.

추가 읽기 .

도움이되기를 바랍니다.


4
강조하기 : <script ...>태그는 페이지 하단, 닫기 </body>태그 바로 앞에 있어야합니다 .
aliteralmind

1
감사합니다! 방금 스크립트를 본문 끝으로 옮겼는데 완벽하게 작동했습니다. 많은 gratitudes
엘레 짐머만

33

이를 위해 jquery 준비 핸들러 사용을 고려할 수 있습니다.

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

그런 다음 두 가지를 달성합니다.

  1. 글로벌 네임 스페이스 오염 방지
  2. 녹아웃 바인딩은 DOM이 생성 된 후에 발생합니다. 조직에 적합한 곳에 자바 스크립트를 배치 할 수 있습니다.

참조 http://api.jquery.com/ready/를


1
RTM하지 않았다 사람들을 위해 스포일러 경고 : $(handler)에 해당합니다$(document).ready(handler)
브록 헨슬리

21

onloadDOM이 준비되었을 때 녹아웃이 DOM을 찾도록 jQuery가 적용 바인딩을 내부에 넣은 경우 .

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

그것을 못 박았다, btw 문서 블록에 다른 바인딩을 포함 할 수 있습니까?
Allan Jikamu 2013 년

1
정보 감사합니다 !!
karthik

5

간단한 맞춤법 오류가 있습니다.

self.addTask = fuction() {

해야한다:

self.addTask = function() { //Notice the added 'n' in 'function'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.