将KnockoutJS与TypeScript和RequireJS一起使用时,ko未定义

时间:2014-08-17 06:01:54

标签: knockout.js requirejs typescript

我正在学习,并且在定义视图模型时遇到了一些问题,并且绑定工作正常。

以下是观看模式:

module MyApp {
    export class MyViewModel {
        public clicked: KnockoutObservable<boolean>;

        constructor() {
            this.clicked = ko.observable(false);
        }

        myClickEvent() {
            this.clicked(true);
        }
    }
}

(可能不需要构造函数。)

以下是我使用requirejs加载模块的方法:

require.config({
baseUrl: "../../Scripts",
    paths: {
        knockout: "knockout-3.1.0",
        jquery: "jquery-2.1.1.min"
    }
});

require(['knockout', 'jquery', 'myviewmodel'], (ko, $, myViewModel) => {
    $(document).ready(() => {
        var vm = new MyApp.MyViewModel();
        ko.applyBindings(vm, document.getElementById("profile-bar"));
    });
});

问题在于以下行:

this.clicked = ko.observable(false);

当click事件触发时(似乎绑定到HTML元素OK),浏览器中出现以下错误:

  

未捕获的ReferenceError:未定义ko

在之前的尝试中我使用了

define('myviewmodel', ['ko'], (ko) => {

等确保满足要求但使用该方法我无法看到如何使用该模块并导出一个类用作视图模型。

你对我做错了什么有任何建议吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

我认为问题最终是由于我应该根据文档http://knockoutjs.com/documentation/amd-loading.html返回函数时尝试使用类。

现在运作良好。以下方法允许上的多个视图模型,同时具有主应用程序视图模型,该模型为整个范围提供一般功能。

我想知道是否有更好/首选的方法。

init.ts

 require.config({
    baseUrl: "../Scripts",
    paths: {
        jquery: "jquery-2.1.1.min",
        knockout: "knockout-3.1.0"
    }
});

require(["jquery", "knockout", "appViewModel"], ($, ko, appViewModel) => {
    $(document).ready(() => {
        ko.bindingHandlers.stopBinding = {
            init: () => {
                return { controlsDescendantBindings: true };
            }
        };
        ko.virtualElements.allowedBindings.stopBinding = true;

        ko.applyBindings(new appViewModel());
    });
});

appViewModel.ts

define(["knockout", "firstnameViewModel", "lastnameViewModel"], (ko, firstNameViewModel, lastnameViewModel) => {
    return () => {
        this.fnvm = new firstNameViewModel();
        ko.applyBindings(this.fnvm, document.getElementById("fn"));

        this.lnvm = new lastnameViewModel();
        ko.applyBindings(this.lnvm, document.getElementById("ln"));

        this.fullName = ko.computed((): string => {
            return this.fnvm.firstName() + " " + this.lnvm.lastName();
        }, this);

        this.clearNameFields = (): void => {
            this.lnvm.clear();
        };;
    };
});

firstnameViewModel.ts

define(["knockout"], (ko) => {
    return function () {
        this.firstName = ko.observable("Bert");
        this.firstNameCaps = ko.computed((): string => {
            return this.firstName().toUpperCase();
        }, this);
    };
});

lastnameViewModel.ts

define(["knockout"], (ko) => {
    return function () {
        this.lastName = ko.observable("Muppet");

        this.clear = (): void => {
            this.lastName("");
        };
    };
});

htmlpage1.html

<html>
<head>
    <script type="text/javascript" data-main="Scripts/init.js" src="Scripts/require.js"></script>
</head>
<body>
    <!-- ko stopBinding: true -->
    <div id="fn">
        <p>First name: <input data-bind="value: firstName" /></p>
        <p>First name capitalized: <strong data-bind="text: firstNameCaps"></strong></p>
    </div>
    <!--/ko-->
    <!-- ko stopBinding: true -->
    <div id="ln">
        <p>Last name: <input data-bind="value: lastName" /></p>
    </div>
    <!--/ko-->
    <p>Full name: <strong data-bind="text: fullName"></strong></p>
    <button data-bind="click:clearNameFields">Clear</button>
</body>
</html>

跳过绑定技术来自http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html