Knockout.js - 简单的“Hello World”失败

时间:2013-11-26 18:58:57

标签: javascript knockout.js

我正在为淘汰js(来自http://goo.gl/lddLl)做一个非常简单的hello世界:但是我的代码产生了一个我不理解的错误。

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>AJAX Example</title>
    <script src="../Scripts/jquery-2.0.3.js"></script>
    <script src="../Scripts/knockout-3.0.0.debug.js"></script>

    <script>

        // Here's my data model
        var ViewModel = function (first, last) {
            this.firstName = ko.observable(first);
            this.lastName = ko.observable(last);

            this.fullName = ko.computed(function () {
                // Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
                return this.firstName() + " " + this.lastName();
            }, this);
        };

        ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work

    </script>
</head>
<body>

    <p>First name: <input data-bind="value: firstName" /></p>
    <p>Last name: <input data-bind="value: lastName" /></p>
    <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>

</body>
</html>

ko.applyBindings调用会引发错误:

未捕获的TypeError:无法读取null knockout-3.0.0.debug.js的属性'nodeType':2439

来自knockout-3.0.0.debug.js代码的

// Perf optimisation: Apply bindings only if...
// (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
//     Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
// (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
var isElement = (nodeVerified.nodeType === 1);

我太无知了,不知道我做错了什么......

2 个答案:

答案 0 :(得分:13)

我猜想有两种解决方法。

最简单的方法:将脚本包装在

$(document).ready(function() {
    your script goes here
});

使用jQuery的ready()函数来延迟初始化,直到页面加载完毕。

2将您的脚本移动到:

<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>

HTML从上到下进行解析。如果你把脚本放在html元素之前,它们可以在一些或所有页面元素准备好与之交互之前运行。

答案 1 :(得分:2)

在将正文添加到DOM之前,您的脚本正在执行,正文是绑定的默认根节点。将脚本放在底部,如下所示:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>AJAX Example</title>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.0.0.debug.js"></script>


</head>
<body>

<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>

<script>

    // Here's my data model
    var ViewModel = function (first, last) {
        this.firstName = ko.observable(first);
        this.lastName = ko.observable(last);

        this.fullName = ko.computed(function () {
            // Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
            return this.firstName() + " " + this.lastName();
        }, this);
    };

    ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work

</script>