【问题标题】:Converting a jQuery plugin to TypeScript将 jQuery 插件转换为 TypeScript
【发布时间】:2019-12-15 12:19:52
【问题描述】:

好的,首先这里是我非常基本的 jQuery 插件

(function ($){
    $.fn.greenify = function (options) {
        var settings = $.extend({
            // These are the defaults
            color: '#556b2f',
            backgroundColor: 'white'
        }, options);
}(jQuery));

$('a').greenify({
    color: 'orange'
}).showLinkLocation();

基本上所有这些都是使用提供的元素更改文本颜色和背景颜色。现在我要做的就是将这个简单的插件转换成 TypeScript

我已经尝试了一些东西,我得到的最接近的是这个。

打字稿

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

module Coloring
{
    interface IGreenifyOptions
    {
        color: string;
        backgroundColor: string;
    }

    export class GreenifyOptions implements IGreenifyOptions
    {
        // Fields
        color: string;
        backgroundColor: string;

        constructor(color: string, backgroundColor: string)
        {
            this.color = color;
            this.backgroundColor = backgroundColor;
        }
    }

    export class Greenify
    {
        // Fields
        element: JQuery;
        options: GreenifyOptions;

        constructor(element: JQuery, options: GreenifyOptions)
        {
            this.element = element;
            this.options = options;

            this.OnCreate();
        }

        OnCreate()
        {
            this.element.css('color', this.options.color).css('background-color', this.options.backgroundColor);
        }
    }
}

调用它的JQuery

$(function ()
{
    var options: Coloring.GreenifyOptions = new Coloring.GreenifyOptions('#0F0', '#000');

    var $elems = $('a');
    $elems.each(function()
    {
        var result = new Coloring.Greenify($(this), options)
    });
});

但是我不想提供像上面new Coloring.Greenify($(this), options)这样的元素,我基本上想做这样的事情

$('a').Coloring.Greenify(options);

$('a').Coloring.Greenify(Coloring.GreenifyOptions()
{
    color: '#F0F',
    backgroundColor: '#FFF'
});

但我似乎不知道如何告诉 TypeScript 它附加到的元素已经是 Jquery 元素。任何人都可以对此有所帮助。

附:上面我已经正常工作了,我只是想更改调用代码。


更新

这是我目前所拥有的,并且有效

打字稿

interface JQuery
{
    Greenify();
    Greenify(options: Coloring.GreenifyOptions);
}

(function ($)
{
    $.fn.Greenify = function (options)
    {
        return new Coloring.Greenify(this, options);
    }
})(jQuery);

jQuery

var $elems = $('a').Greenify(options);

但这意味着我必须提供选项,如果我在没有选项的情况下执行构造函数,我得到的选项是未定义的。我勾选正确的答案对于我提出的问题是正确的。但是请记住,提供的答案要求您在 typescript 构造函数中提供选项,我将了解如何使用默认选项,然后在构造函数中覆盖它们,但这是一个不同的问题 :)


更新 2

只是为了让大家知道我找到了一种方法来为您的插件提供选项。

你能做的就是这个

TypeScript 类

export class Greenify
    {
        // Default Options
        static defaultOptions: IGreenifyOptions =
        {
            color: '#F00',
            backgroundColor: '#00F'
        };

        // Fields
        element: JQuery;
        options: GreenifyOptions;

        constructor(element: JQuery, options: GreenifyOptions)
        {
            // Merge options
            var mergedOptions: GreenifyOptions = $.extend(Greenify.defaultOptions, options);
            this.options = mergedOptions;
            this.element = element;

            this.OnCreate();
        }

        OnCreate()
        {
            this.element.css('color', this.options.color).css('background-color', this.options.backgroundColor);
        }

    }

TypeScript 接口

interface JQuery
{
    Greenofy();
    Greenify(obj?: any);
    Greenify(options?: Coloring.GreenifyOptions);
}

(function ($)
{
    $.fn.Greenify = function (options)
    {
        return new Coloring.Greenify(this, options);
    }
})(jQuery);

使用一个可选选项调用插件的 jQuery 代码

$(function ()
{
    var $elems = $('a').Greenify(<Coloring.GreenifyOptions>{
        color: '#00F'
    });
});

因此,输出不会使锚点背景颜色为“#00F”,这是默认值,而我提供的选项将使锚点文本颜色为“#00F”。

我希望这可以帮助其他和我有同样问题的人:)

【问题讨论】:

    标签: javascript jquery html typescript


    【解决方案1】:

    与 TypeScript 一起创建 jQuery 插件可能会有点混乱。我个人更喜欢保留 jQuery 插件链接语法,主要是为了一致性和可维护性。

    因此,在模块声明之后,您基本上可以将 jQuery 原型扩展为:

    module Coloring {
      interface IGreenifyOptions {
        color: string;
        backgroundColor: string;
      }
    
      export class GreenifyOptions implements IGreenifyOptions {
        // Fields
        color: string;
        backgroundColor: string;
    
        constructor(color: string, backgroundColor: string) {
          this.color = color;
          this.backgroundColor = backgroundColor;
        }
      }
    
      export class Greenify {
        // Fields
        element: JQuery;
        options: GreenifyOptions;
    
        constructor(element: JQuery, options: GreenifyOptions) {
          this.element = element;
          this.options = options;
    
          this.OnCreate();
        }
    
        OnCreate() {
          this.element.css('color', this.options.color).css('background-color', this.options.backgroundColor);
        }
      }
    }
    
    
    //jquery plugin wrapper.
    ;
    (function(w, $) {
        //no jQuery around
      if (!$) return false;
    
      $.fn.extend({
        Coloring: function(opts) {
          //defaults
          var defaults: Coloring.GreenifyOptions = new Coloring.GreenifyOptions('#0F0', '#000');
    
          //extend the defaults!
          var opts = $.extend({}, defaults, opts)
    
          return this.each(function() {
            var o = opts;
            var obj = $(this);
            new Coloring.Greenify(obj, o);
    
          });
        }
      });
    })(window, jQuery);
    

    获取插件为:

    $(function() {
    
      var $a = $('a').Coloring();
      var $div = $('div').Coloring({
        color: '#F0F',
        backgroundColor: '#FFF'
      });
      var $div = $('strong').Coloring({
        color: '#gold',
        backgroundColor: 'pink'
      });
    });
    

    Demo

    【讨论】:

    • 这个答案看起来很有希望,但是我必须使用扩展吗?我可以不只为选项提供一个默认构造函数,然后如果我传入选项覆盖选项吗?
    • @Canvas 当然,您可以四处玩耍并操作此示例以满足您的需求。请记住,您需要将对象传递给构造函数。这是有关映射对象的相关任务:stackoverflow.com/questions/16793503/…
    • 这个答案的一部分可以改进。默认选项可以是静态的(因此也是可修改的)。 $.extend 将修改第一个参数,因此您只需使用一个空对象作为目标,例如:var opts = $.extend({}, defaults, opts);。另请注意,原始问题不需要为选项提供class 的开销。一个简单的对象就可以了,因为没有方法。
    • @TrueBlueAussie 没错,我正在更新我的答案。非常感谢。
    • 你误会了。您只需要更正if 您移动到静态默认选项。每次(此刻)都在更新一个新鲜的对象,所以没有区别:)
    【解决方案2】:

    您可以创建和引用您自己的定义文件greenify.d.ts 并添加如下函数:

    interface Jquery {
         greenify: (options: Coloring.IGreenifyOptions) => void
    }
    

    然后你可以简单地这样称呼它:

    $('a').greenify(new GreenifyOptions(...));
    

    $('a').greenify({color:'', backgroundColor:''});
    

    说明:

    在编译时 typescript 实际上会合并所有接口定义。

    旁注:

    如果你坚持要和$('a').Coloring.Greenify(..) 完全一样,那么你将不得不做出更多改变:

    • 着色不再是您模块的名称,因为您必须在上面的接口定义中使用它
    • 您可能必须创建一个将 .Greenify 作为静态方法的类
    • 可能更多...

    总而言之,坚持我最初的解决方案可能更容易,因为它不那么冗长,但这取决于你。

    希望对你有帮助

    更新:

    要考虑默认选项,您可以修改接口定义以进行覆盖:

    interface Jquery {
         greenify: () => void;
         greenify: (options: Coloring.IGreenifyOptions) => void;
    }
    
    interface IGreenifyOptions
    {
        color?: string;
        backgroundColor?: string;
    }
    

    【讨论】:

    • 这是我目前拥有的,但这意味着我必须提供选项,但如果我想使用默认选项怎么办?
    • 您问题顶部的 jquery 插件是否已经处理默认值?如果这些是您的意思的默认值,那么向界面添加另一个定义应该足够简单。查看我的更新
    • 确实如此,但例如我们想改变背景颜色而不是颜色,我将如何在构造函数中做到这一点?
    • 哦,我明白了...然后只需在名称末尾添加? 将选项设置为可选。更新了我的“更新”
    • 我已经这样做了color?: string; backgroundColor?: string;,但是当我打电话给var $elems = $('a').Greenify(); 时,它指出color 是未定义的
    猜你喜欢
    • 1970-01-01
    • 2013-12-16
    • 2011-07-28
    • 2016-11-05
    • 2022-10-18
    • 2018-05-26
    • 2012-07-08
    • 2016-05-05
    • 1970-01-01
    相关资源
    最近更新 更多