Расширить плагин ES6 до прототипа jQuery

Я хотел бы попросить некоторую помощь, потому что я не могу преобразовать мой классический jQuery (v2) плагин в ES6 с модулем и классом.

В ECMAScript 5 мы можем подключить плагин jQuery в прототипе jQuery следующим образом:

app.js - jQuery, загружаемый через тег <script>

$.fn.myPlugin = function() {};
$('div').myPlugin();

И это работает:). В ES6 я бы написал что-то вроде этого:

myPlugin.es6:

import $ from 'jquery';

export default class myPlugin extends $ {
 // Could i use constructor() method ???
}

app.es6:

import $ from 'jquery';
import myPlugin from 'myPlugin.es6';

$('div').myPlugin();

И, наконец, он не работает...
Я искал, и никто не задавал этот вопрос раньше.
Я использую Babel для перевода ES6 в ES5.

Ответ 1

$.fn - это просто объект. Нет волшебства при добавлении нового свойства в прототип $. Таким образом, код $.fn.myPlugin = function() {} равен $.prototype.myPlugin = function() {}.

$.fn === $.prototype; // true

Чтобы иметь возможность вызывать функцию в объекте $ стандартным образом ($('div').func()), вам нужно добавить эту функцию в объект $.

Вы не добавляете его в свой код es6.

Таким образом,

import $ from 'jquery';

export default class myPlugin extends $ {
 // Could i use constructor() method ???
}

Значит (почти)

var myPlugin = function() {};

myPlugin.prototype = Object.create($.prototype);

return { default: myPlugin };

Я не уверен, что вы должны расширять $.fn, но, возможно, вам это нужно.

И с

import $ from 'jquery';
import myPlugin from 'myPlugin.es6';

это означает

var $ = require('jquery');
var myPlugin = require('myPlugin'); // a reference to the 'export.default' object from 'myPlugin.es6'

Следовательно, нет связи между объектом $.fn и myPlugin.

Вы должны создать соединение где-нибудь. Он может быть в специальном модуле, таком как plugins, где вы будете вводить все необходимые плагины в объект $.fn:

import $ from 'jquery';
import plugin1 from 'plugin1.es6'; // should contain 'name'
import plugin2 from 'plugin2.es6';
...
import plugin10 from 'plugin10.es6';

[plugin1, plugin2, ..., plugin10].forEach(plugin => $.fn[plugin.name] = plugin);

Или вы можете добавить метод "initialize" к экспортированному объекту в "myPlugin.es6" и вызвать его перед первым использованием: init($) { $.fn.myPlugin = myPlugin; }

И так далее.

Ответ 2

Вы устанавливаете новые методы в прототипе jQuery в ES6 так же, как и всегда. Ничто не изменилось для них. Вы не собираетесь подклассифицировать jQuery, поэтому нет смысла использовать class или extends.

// myPlugin.es6:
import $ from 'jquery';

$.fn.myPlugin = function() {
    …
};

// app.es6:
import $ from 'jquery';
import 'myPlugin.es6';

$('div').myPlugin();