带有 KnockoutJS 的 TypeScript

Posted

技术标签:

【中文标题】带有 KnockoutJS 的 TypeScript【英文标题】:TypeScript with KnockoutJS 【发布时间】:2012-09-23 06:32:39 【问题描述】:

有没有使用 TypeScript 和 KnockoutJS 的示例?我只是好奇他们将如何合作?

编辑

这是我所拥有的,似乎可以工作

declare var ko: any;
declare var $: any;
class ViewModel 
    x = ko.observable(10);
    y = ko.observable(10);



$(() => 
    ko.applyBindings(new ViewModel());
);

这会生成以下 javascript

var ViewModel = (function () 
    function ViewModel() 
        this.x = ko.observable(10);
        this.y = ko.observable(10);
    
    return ViewModel;
)();
$(function () 
    ko.applyBindings(new ViewModel());
);

【问题讨论】:

我对与“var”结合使用的“declare”关键字感到有些困惑,直到我在规范中找到关于环境声明的部分。现在很有意义:typescriptlang.org/Content/…. 在 Typescript 0.9 中,我们有泛型,它为您提供输入的 observables:ko.observable<number>(10)。我写了一篇博文,提供了一些更详细的信息:ideasof.andersaberg.com/idea/12/… 【参考方案1】:

看看DefinitelyTyped。

“流行 JavaScript 库的 TypeScript 类型定义存储库”

【讨论】:

这可能是一个愚蠢的问题,但你能解释一下 TypeScript 类型定义到底是什么/做什么吗?纯粹是为了让您可以在 TypeScript 编译的文件中使用库函数而编译器不会抱怨吗?如果是这种情况,您不需要在应用程序中引用定义,只需在编译 ts 文件时,对吗? 正是如此。如果您在记事本中编写打字稿代码,则只需要在编译时定义。另一方面,打字稿的一个优点是它更容易让视觉工作室(和其他通过插件的编辑器)智能理解你的代码,它可以帮助你自动完成和执行类型和错误检查(更多比 JavaScript)。这就是为什么我们使用 JavaScript 编写的代码的定义文件来提供 typescript 类型检查。当然,您可以将库声明为“任何”,但这并不好。希望我有所帮助! 请注意,关键是将/// <reference path="knockout-2.2.d.ts" /> 添加到 .ts 文件的顶部,以便它获取定义。 我在列表中的任何地方都看不到淘汰赛....已删除??搬家了??沮丧【参考方案2】:

我制作了这个小接口来获取 Knockout 的静态类型:

interface ObservableNumber 
        (newValue: number): void;               
        (): number;                             
        subscribe: (callback: (newValue: number) => void) => void;

interface ObservableString 
        (newValue: string): void;               
        (): string;                             
        subscribe: (callback: (newValue: string) => void) => void;

interface ObservableBool 
    (newValue: bool): void;             
    (): bool;                               
    subscribe: (callback: (newValue: bool) => void) => void;


interface ObservableAny 
    (newValue: any): void;              
    (): any;                                
    subscribe: (callback: (newValue: any) => void) => void;


interface ObservableStringArray 
    (newValue: string[]): void;
    (): string[];
    remove: (value: String) => void;
    removeAll: () => void;
    push: (value: string) => void;
    indexOf: (value: string) => number;


interface ObservableAnyArray 
    (newValue: any[]): void;
    (): any[];
    remove: (value: any) => void;
    removeAll: () => void;
    push: (value: any) => void;


interface Computed 
    (): any;


interface Knockout 
    observable: 
        (value: number): ObservableNumber;
        (value: string): ObservableString;
        (value: bool): ObservableBool;
        (value: any): ObservableAny;
    ;
    observableArray: 
        (value: string[]): ObservableStringArray;
        (value: any[]): ObservableAnyArray;
    ;
    computed: 
        (func: () => any): Computed;
    ;

将其放入“Knockout.d.ts”中,然后从您自己的文件中引用它。如您所见,它将从泛型(根据规范提供)中受益匪浅。

我只为 ko.observable() 做了几个接口,但是 ko.computed() 和 ko.observableArray() 可以很容易地添加到相同的模式中。 更新:我修复了 subscribe() 的签名并添加了 computed() 和 observableArray() 的示例。

要从您自己的文件中使用,请在顶部添加:

/// <reference path="./Knockout.d.ts" />
declare var ko: Knockout;

【讨论】:

@JcFx:Anders 提到的可能是采用 TypeScript .ts 文件并输出接口声明文件 .d.ts 的选项。没有办法使用常规的无类型 JavaScript 并神奇地发现类型。 JS 的问题(TypeScripts 试图解决的)是程序员无法声明她的意图,即变量应该符合特定类型。当您在 JS 中说 x = 'hello' 时,我们不知道您是否打算稍后在代码中的某个地方说 x = 34。我们无法推断出 x 的类型。 @JcFx:实际上,您可能是对的,一些有限的类型信息可以从纯 JS 派生。尝试时告诉我结果如何! typescript 正在添加泛型。【参考方案3】:

试试我的TypeScript接口声明的实现(附简单例子)https://github.com/sv01a/TypeScript-Knockoutjs

【讨论】:

【参考方案4】:

在标记中声明淘汰绑定的方式方面没有任何改变,但是一旦为淘汰库编写接口,我们就会获得智能感知优势。在这方面,它就像jquery Sample 一样工作,它有一个typescript file containing interfaces for most of the jQuery api。

我认为如果你去掉 ko 和 $ 的两个变量声明,你的代码就可以工作了。这些隐藏了在敲除和 jquery 脚本加载时创建的实际 ko 和 $ 变量。

我必须这样做才能将 Visual Studio 模板项目移植到淘汰赛:

app.ts:

class GreeterViewModel 
    timerToken: number;
    utcTime: any;

    constructor (ko: any)  
        this.utcTime = ko.observable(new Date().toUTCString());
        this.start();
    

    start() 
        this.timerToken = setInterval(() => this.utcTime(new Date().toUTCString()), 500);
    


window.onload = () => 
    // get a ref to the ko global
    var w: any;
    w = window;
    var myKO: any;
    myKO = w.ko;

    var el = document.getElementById('content');
    myKO.applyBindings(new GreeterViewModel(myKO), el);
;

default.htm:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="Scripts/knockout-2.1.0.debug.js" type="text/javascript"></script>
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>

    <div id="content" data-bind="text: utcTime" />
</body>
</html>

【讨论】:

不是在 ko 中发布给每个构造函数的那种矫枉过正【参考方案5】:

好的,只需使用以下命令导入敲除类型或 tds。

npm install @types/knockout

这将在您的项目 node_modules 目录中创建一个@types 目录,并且索引敲除类型定义文件将位于名为敲除的目录中。 接下来,通过对类型文件的三斜杠引用。这将提供出色的 IDE 和 TypeScript 功能。

/// <reference path="../node_modules/@types/knockout/index.d.ts" />

最后,只需使用声明语句将 ko 变量带入作用域。这是强类型的,所以你好智能感知。

declare var ko: KnockoutStatic;

所以现在您可以像在您的 javascript 文件中一样使用 KO。

希望这会有所帮助。

【讨论】:

这对 2021 年的我来说是完美的。在利用 npm 的同时将 Typescript 与现有的旧 Javascript 混合。谢谢。【参考方案6】:

我正在使用https://www.nuget.org/packages/knockout.editables.TypeScript.DefinitelyTyped/ 并且它具有用于 Knockout 的所有接口。

【讨论】:

以上是关于带有 KnockoutJS 的 TypeScript的主要内容,如果未能解决你的问题,请参考以下文章

带有 jQ​​uery UI 可排序的 Knockoutjs

带有模板和 foreach 的 KnockoutJS observableArray

有人愤怒地使用带有 asp.net-mvc 的 Knockoutjs 吗? [关闭]

knockoutjs 读源码

knockoutjs 从一个函数中保存多个视图模型?

如何更改knockoutjs中的onClick按钮