Cara membuat plugin jQuery dapat dimuat dengan requirejs

88

Saya bekerja dengan requirejs + jquery dan saya bertanya-tanya apakah ada cara cerdas untuk membuat plugin jQuery berfungsi dengan baik dengan Requirement.

Misalnya saya menggunakan jQuery-cookie. Jika saya mengerti dengan benar, saya dapat membuat file bernama jquery-cookie.js dan di dalamnya lakukan

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});
requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

saya bertanya-tanya apakah saya bisa melakukan hal-hal seperti yang dilakukan jQuery, seperti ini:

if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
    define( "jquery", [], function () { return jQuery; } );
}

atau jika ini adalah satu-satunya cara untuk membuat plugin jQuery kompatibel dengan requirejs atau amd apa pun

Nicola Peluchetti
sumber

Jawaban:

67

Anda hanya perlu melakukan BAIK

define(["jquery"], // Require jquery
       function($){
// Put here the plugin code. 
// No need to return anything as we are augmenting the jQuery object
});

di akhir jquery-cookie.js, OR

requirejs.config( {
    "shim": {
        "jquery-cookie"  : ["jquery"]
    }
} );

di mana saja sebelum Anda memasukkan jquery-cookie (seperti di mana pun titik utama data, misalnya).

Blok kode terakhir yang Anda posting bagus untuk hal-hal seperti jQuery yang dapat didistribusikan ulang dan mungkin atau mungkin tidak ada di lingkungan AMD. Idealnya setiap plugin jQuery sudah menyiapkannya.

Saya lebih suka menyimpan pustaka yang disertakan sebisa mungkin, sehingga konfigurasi shim global sekali per halaman sepertinya solusi terbersih bagi saya . Dengan begitu, peningkatan versi lebih aman dan CDN menjadi kemungkinan.

Hans
sumber
1
Jika saya tidak melakukan baik yang didefinisikan maupun yang shim tidak berfungsi, saya mendapatkan $ .cookie bukanlah pesan kesalahan fungsi
Nicola Peluchetti
Menurut pengalaman saya, tidak mengembalikan apa pun dari fungsi pendefinisian tidak cukup, requirejs tidak akan mengenali bahwa modul dimuat. Ini dapat diubah oleh shim: {plugins: {tergantung: ['jquery'], ekspor: 'plugins'}
honzajde
Anda harus mencatat bahwa skrip plugin jQuery harus benar-benar dijalankan. Saya bukan ahli tetapi saya menemukan solusi langsung di mana Anda memiliki satu require(['plugin1', 'plugin2']);dll. Tidak ada panggilan balik yang diteruskan sehingga tidak ada yang akan berjalan kecuali skrip plugin itu sendiri. Ini berarti bahwa mereka kemudian akan menambahkan dirinya sendiri jQuery.fnsehingga di mana pun Anda dapat mencantumkan 'jquery' sebagai dependensi dan mereka akan disertakan. Seperti yang saya katakan, saya cukup baru dalam hal ini dan mungkin ada pendekatan yang lebih baik (seperti hanya menggunakan scripttag) tetapi ini berhasil.
Joshua Bambrick
3
Josh: Anda bertaruh bahwa semuanya akan dimuat dengan urutan yang benar. Beberapa pengguna di situs Anda mungkin melihat barang rusak. Masalahnya adalah tidak sebanyak yang beban Plugin, itu saat beban Plugin dan apa lagi mengeksekusi pada saat itu. Alasan utama untuk menggunakan Requirement adalah untuk memastikan urutan operasi yang masuk akal berdasarkan dependensi, bukan tebakan.
Hans
104

Ada beberapa peringatan dengan menggunakan konfigurasi shim di RequireJS, yang ditunjukkan di http://requirejs.org/docs/api.html#config-shim . Yaitu, "Jangan mencampur pemuatan CDN dengan konfigurasi shim dalam sebuah build" saat Anda menggunakan pengoptimal.

Saya sedang mencari cara untuk menggunakan kode plugin jQuery yang sama di situs dengan dan tanpa RequireJS. Saya menemukan cuplikan untuk plugin jQuery ini di https://github.com/umdjs/umd/blob/master/jqueryPlugin.js . Anda membungkus plugin Anda dengan kode ini, dan itu akan berfungsi dengan baik.

(function (factory) {
if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module depending on jQuery.
    define(['jquery'], factory);
} else {
    // No AMD. Register plugin with global jQuery object.
    factory(jQuery);
}
}(function ($) {

    $.fn.yourjQueryPlugin = function () {
        // Put your plugin code here
    };  

}));

Kredit diberikan kepada jrburke; seperti banyak javascript, itu fungsi di dalam fungsi yang bekerja pada fungsi lain. Tapi saya pikir saya telah membongkar apa yang dilakukannya.

Argumen fungsi factorydi baris pertama itu sendiri adalah fungsi yang dipanggil untuk mendefinisikan plugin pada $argumen tersebut. Jika tidak ada loader yang kompatibel dengan AMD, itu dipanggil secara langsung untuk menentukan plugin pada jQueryobjek global . Itu seperti idiom definisi plugin yang umum:

function($)
{
  $.fn.yourjQueryPlugin = function() {
    // Plugin code here
  };
}(jQuery);

Jika ada modul pemuat, maka factoryterdaftar sebagai panggilan balik untuk pemuat yang akan dipanggil setelah memuat jQuery. Salinan jQuery yang dimuat adalah argumennya. Itu setara dengan

define(['jquery'], function($) {
  $.fn.yourjQueryPlugin = function() {
     // Plugin code here
  };
})
Carl Raymond
sumber
3
Saya suka jawaban ini karena meskipun pertanyaannya tentang plugin jQuery, ini berfungsi untuk semua jenis modul atau pustaka, bukan hanya jQuery. Saya butuh waktu satu menit untuk memahami kode Anda, tapi begitu saya melakukannya, itu sangat masuk akal.
Adam Tuttle
1
Ini jelas javascript yang tidak bisa ditembus. Saya menambahkan beberapa penjelasan tentang cara kerjanya.
Carl Raymond
Adakah tips tentang cara melakukan ini dan membuat plugin yang berfungsi dengan jQuery atau Zepto? Anda dapat dengan mudah mengganti kode non-AMD dengan factory(jQuery || Zepto);, tetapi saya tidak tahu bagaimana Anda akan melakukan bagian AMD. Saya pikir Anda harus mengatur jQuery "path" ke zepto ?? paths: { jquery: 'vendor/zepto/zepto.min' }
Ryan Wheale
wow saya sudah lama ingin memahami potongan kode ini. Terima kasih banyak, Bukankah pada shimdasarnya hanya melakukan itu? Saya kira tidak .. karena Anda mengatakan Anda mengkodekannya secara manual seperti di atas.
eugene
Protip untuk orang bodoh seperti saya: di mana dikatakan $.fn.jqueryPlugindi cuplikan, ubah jqueryPluginke nama plugin !!
Matt Lacey
2

Sama seperti FYI untuk semua beberapa plugin jquery sudah menggunakan amd / require sehingga Anda tidak perlu mendeklarasikan apa pun di shim. Faktanya, melakukan hal itu dapat menimbulkan masalah bagi Anda dalam beberapa kasus.

Jika Anda melihat di jquery cookie JS Anda akan melihat panggilan define dan require (["jquery"]).

dan di jquery.js Anda akan melihat panggilan untuk mendefinisikan ("jquery", [], function () ...

TPEACHES
sumber