在 TypeScript 中定义自定义 jQuery UI 小部件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14578651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 02:47:38  来源:igfitidea点击:

Define a custom jQuery UI widget in TypeScript

jquery-uitypescript

提问by thomaux

We're currently looking at translating our JavaScript project to TypeScript. Our application relies heavily on custom developed jQuery UI widgets.

我们目前正在考虑将我们的 JavaScript 项目翻译成 TypeScript。我们的应用程序严重依赖于自定义开发的 jQuery UI 小部件。

In our current code base, we're using a deep copy mechanism to inherit from widget definitions allowing us, for example, to declare a generic TableWidgetas well as an OrdersTableWidgetwhich defines more specific functions.

在我们当前的代码库中,我们使用深层复制机制来继承小部件定义,例如,允许我们声明泛型TableWidget以及OrdersTableWidget定义更具体功能的an 。

Therefore, I'd like to define my widget definitions as TypeScript classes and then bind an instance of these classes to jQuery.

因此,我想将我的小部件定义定义为 TypeScript 类,然后将这些类的实例绑定到 jQuery。

For example

例如

class MyWidget {
    options: WidgetOptions;
    _init(){
        // general initialization
    }
}

class MySecondWidget extends MyWidget {
    _init(){
        super._init();
        // specific initialization
    }
}

And then

接着

$.widget("MyNameSpace.MyWidget", new MyWidget());
$.widget("MyNameSpace.MySeWidget", new MyWidget());

Furthermore, I'd like to denote my custom widgets as implementations of jQuery UI's Widgetdefinition

此外,我想将我的自定义小部件表示为 jQuery UIWidget定义的实现

class MyWidget implements Widget {
    options: WidgetOptions;
    _init(){
        // general initialization
    }
}

so I'm able to use the following syntax in TypeScript:

所以我可以在 TypeScript 中使用以下语法:

$(selector).MyWidget(options);

I know I have to work with the definition file (from DefinitelyTyped), however I have not yet found a reliable source explaining me how I should write custom jQuery UI Widgets in TypeScript. Has anyone got experience with this?

我知道我必须使用定义文件(来自绝对类型),但是我还没有找到一个可靠的来源来解释我应该如何在 TypeScript 中编写自定义 jQuery UI 小部件。有没有人有这方面的经验?

Any help greatly appreciated, as always!

一如既往,非常感谢任何帮助!

采纳答案by Fenton

I'm not sure you can write a class that implements the Widgetinterface, due to the lack of overloaded constructors. You could create a variable that is typed by the Widgetinterface.

Widget由于缺少重载的构造函数,我不确定您是否可以编写一个实现接口的类。您可以创建一个由Widget接口输入的变量。

A standard jQuery plugin would be represent in almost pure JavaScript and wouldn't use modules or classes as it ends up being wrapped up as part of jQuery, which itself isn't a module or class.

标准的 jQuery 插件几乎用纯 JavaScript 表示,并且不会使用模块或类,因为它最终被包装为 jQuery 的一部分,而 jQuery 本身不是模块或类。

Here is an empty plugin called pluginthat looks like any standard jQuery plugin, but you can see it takes advantage of the TypeScript type system and extends the JQueryinterface to allow it to be called.

这是一个名为的空插件plugin,它看起来像任何标准的 jQuery 插件,但您可以看到它利用了 TypeScript 类型系统并扩展了JQuery接口以允许调用它。

/// <reference path="jquery.d.ts" />

interface JQuery {
    plugin(): JQuery;
    plugin(settings: Object): JQuery;
}

(function ($) {

    function DoSomething(someParamater: string) : void {

    }

    $.fn.plugin = function (settings) {

        var config = {
            settingA: "Example",
            settingB: 5
        };

        if (settings) {
            $.extend(config, settings);
        }

        return this.each(function () {

        });
    };

})(jQuery);

This would be called in the normal way.

这将以正常方式调用。

$('#id').plugin();

So really, my answer is - you can't really do what you want because you are adding to the declared interfaces for jQuery rather than exposing them as modules. You could wrap the usage in a module, like an adaptor that abstracts the jQuery aspect away from the use in your TypeScript, or you can call your classes from inside the plugin, but the plugin or widget doesn't really fit into a module or class.

所以真的,我的答案是 - 你不能真正做你想做的,因为你是添加到 jQuery 的声明接口而不是将它们作为模块公开。您可以将用法包装在模块中,例如将 jQuery 方面从 TypeScript 中的使用中抽象出来的适配器,或者您可以从插件内部调用您的类,但插件或小部件并不真正适合模块或班级。

回答by Benjamin

It might help to have a base class in typescript from which other widget classes may derive. Its only purpose is to provide the base class semantic so you can access the base class'es members without having to resort to weak typing.

在打字稿中拥有一个基类可能会有所帮助,其他小部件类可以从中派生。它的唯一目的是提供基类语义,以便您可以访问基类的成员而不必求助于弱类型。

The trick is to remove all the members at runtime (in the constructor) -- otherwise you run into problems with the inheritance provided by the widget factory. For example, the optionmethod would override the widget's original method which is not desired: we just want to be able to call it (in a statically typed way).

诀窍是在运行时(在构造函数中)删除所有成员——否则你会遇到小部件工厂提供的继承问题。例如,该option方法将覆盖小部件的原始方法,这是不希望的:我们只是希望能够调用它(以静态类型的方式)。

class WidgetBase {

    public element:JQuery;

    constructor() {
        // remove all members, they are only needed at compile time.
        var myPrototype =  (<Function>WidgetBase).prototype;
        $.each(myPrototype, (propertyName, value)=>{
           delete myPrototype[propertyName];
        });
    }

    /**
     * Calles the base implementation of a method when called from a derived method.
     * @private
     */
    public _super(arg1?:any, arg2?:any, arg3?:any, arg4?:any) {

    }

    /**
     * @private
     */
    public _superApply(arguments) {

    }

    /**
     * Gets or sets the value of the widget option associated with the specified optionName.
     */
    public option(optionName:string, value?:any):any {

    }

    // ... further methods from http://api.jqueryui.com/jQuery.widget/
}

Then you can implement your own widget like this:

然后你可以像这样实现你自己的小部件:

class SmartWidget extends WidgetBase {

    constructor(){
        super();
    }

    public _create() {
        var mySmartOption = this.option('smart'); // compiles because of base class
        this.beSmart(mySmartOption);
    }

    public _setOption(key:string, value:any) {
        if (key === 'smart') {
           this.beSmart(value);
        }

        this._super(key, value); // compiles because of base class
    }

    private beSmart(smartOne:any){
        // ...
    }

}

// register
jQuery.widget("myLib.smartWidget", new SmartWidget());

// assuming you are using https://github.com/borisyankov/DefinitelyTyped
declare interface JQuery{
    smartWidget();
    smartWidget(options:any);
    smartWidget(methodName:string, param1?:any, param2?:any, param3?:any, param4?:any);
}

And finally, you can use your widget:

最后,您可以使用您的小部件:

$(".selector").smartWidget({smart:"you"});