Bir JavaScript dosyasını başka bir JavaScript dosyasına nasıl eklerim?


5194

JavaScript'te @importCSS'ye benzer başka bir JavaScript dosyasının içine bir JavaScript dosyası eklemenizi sağlayan bir şey var mı ?



82
@Daniel, AJAX çağrısı kullanmak istemiyorum.
Alec Smart

13
İçe aktarılan dosyayı neden diğerlerinden önce, yalnızca sıralı scriptetiketleri kullanarak bildirmiyorsunuz ?
falsarella

6
@Claudiu Bu, hiçbir şeyi içe aktarmaya yardımcı olmaz , ancak aynı zamanda işe yaramalıdır . Başka bir JS dosyasına bağlı bir JS dosyanız varsa, önce bağımlılık dosyalarının komut dosyası etiketlerini bildirmeniz yeterlidir, bu nedenle daha sonra bağımlılıkları zaten yüklü olacaktır. Olası bir yaklaşım olmayan bir durumunuz varsa, buradaki yanıtlar yardımcı olacaktır.
falsarella

1
Bunu yapmanın pratik avantajı nedir? her iki şekilde de javascript dosyasına bağımlı kod tabanı yüklenmez ve yüklü değilse her durumda çalışmaya başlar!
Ciasto piekarz

Yanıtlar:


4472

JavaScript'in eski sürümlerinde herhangi bir içe aktarma, içerme veya gereksinim yoktu, bu soruna birçok farklı yaklaşım geliştirildi.

Ancak 2015'ten beri (ES6), JavaScript, çoğu modern tarayıcı tarafından da desteklenen Node.js'de modülleri içe aktarmak için ES6 modülleri standardına sahiptir .

Eski tarayıcılarla uyumluluk için Webpack gibi araçlar oluşturun ve Toplama ve / veya Babel gibi çeviri araçları oluşturun kullanılabilir.

ES6 Modülleri

ECMAScript (ES6) modülleri, v8.5'ten beri, bayrakla birlikte ve en azından Node.js v13.8.0'da bayraksız olarak desteklenmektedir--experimental-modules . "ESM" (node.js önceki CommonJS tarzı modülü sistemine karşı [ "CJS"]) sizi ya kullanımı etkinleştirmek için "type": "module"depackage.json ya dosyaları uzantısı verin .mjs. (Benzer şekilde, Node.js'nin önceki CJS modülü ile yazılmış modüller adlandırılabilir.cjs varsayılan değer ESM ise .)

kullanma package.json :

{
    "type": "module"
}

Sonra module.js :

export function hello() {
  return "Hello";
}

Sonra main.js :

import { hello } from './module.js';
let val = hello();  // val is "Hello";

Kullanarak .mjs,module.mjs :

export function hello() {
  return "Hello";
}

Sonra main.mjs :

import { hello } from './module.mjs';
let val = hello();  // val is "Hello";

Tarayıcılarda ECMAScript modülleri

Tarayıcılar, Safari 10.1, Chrome 61, Firefox 60 ve Edge 16'dan beri ECMAScript modüllerini doğrudan yükleme (Webpack gibi bir araç gerekmez) desteğine sahipti . Caniuse'daki mevcut desteği kontrol edin . Node.js'nin .mjsuzantısını kullanmaya gerek yoktur ; tarayıcılar modüller / komut dosyalarındaki dosya uzantılarını tamamen yok sayar.

<script type="module">
  import { hello } from './hello.mjs'; // Or it could be simply `hello.js`
  hello('world');
</script>
// hello.mjs -- or it could be simply `hello.js`
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}

Https://jakearchibald.com/2017/es-modules-in-browsers/ adresinde daha fazla bilgi bulabilirsiniz.

Tarayıcılarda dinamik içe aktarma

Dinamik içe aktarmalar komut dosyasının diğer komut dosyalarını gerektiği gibi yüklemesine izin verir:

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

Https://developers.google.com/web/updates/2017/11/dynamic-import adresinden daha fazla bilgi edinin.

Node.js gerektirir

Hala Node.js'de yaygın olarak kullanılan eski CJS modülü stili module.exports/require sistemidir.

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val is "Hello"   

JavaScript'in harici önizleme gerektirmeyen tarayıcılara harici JavaScript içeriği eklemesinin başka yolları da vardır.

AJAX Yükleniyor

AJAX çağrısı ile ek bir komut dosyası yükleyebilir ve daha sonra evalçalıştırmak için kullanabilirsiniz . Bu en basit yoldur, ancak JavaScript korumalı alan güvenlik modeli nedeniyle alan adınızla sınırlıdır. Kullanmak evalda hatalara, korsanlara ve güvenlik sorunlarına kapı açar.

Yükleme Getir

Dinamik İçe Aktarmalar gibi fetch, Getirme Enjeksiyonu kitaplığını kullanarak komut dosyası bağımlılıkları için yürütme sırasını kontrol etme vaatlerini kullanarak bir veya daha fazla komut dosyası yükleyebilirsiniz :

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})

jQuery Yükleniyor

JQuery kütüphanesi yükleme işlevi sağlar tek satırda :

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

Dinamik Betik Yükleme

HTML'ye komut dosyası URL'sini içeren bir komut dosyası etiketi ekleyebilirsiniz. JQuery yükünü önlemek için, bu ideal bir çözümdür.

Komut dosyası farklı bir sunucuda bile bulunabilir. Ayrıca, tarayıcı kodu değerlendirir. <script>Etiketi ya web sayfası içine enjekte edilebilir <head>, ya da sadece kapanış önüne eklenir </body>etiketi.

Bunun nasıl çalışabileceğine ilişkin bir örnek:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL

    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)
}

Bu işlev <script>, sayfanın başlık bölümünün sonuna yeni bir etiket ekler ; burada srcözellik, ilk parametre olarak işleve verilen URL'ye ayarlanır.

Bu çözümlerin her ikisi de JavaScript Çılgınlığı: Dinamik Betik Yükleme bölümünde tartışılmış ve gösterilmiştir .

Komut dosyasının ne zaman yürütüldüğünü algılama

Şimdi bilmeniz gereken büyük bir sorun var. Bunu yapmak , kodu uzaktan yüklediğiniz anlamına gelir . Modern web tarayıcıları dosyayı yükler ve mevcut komut dosyanızı yürütmeye devam eder, çünkü performansı artırmak için her şeyi eşzamansız olarak yüklerler. (Bu hem jQuery yöntemi hem de el ile dinamik komut dosyası yükleme yöntemi için geçerlidir.)

Bu, bu hileleri doğrudan kullanırsanız, yüklenmesini istedikten sonra yeni yüklediğiniz kodu bir sonraki satırda kullanamayacağınız anlamına gelir , çünkü yine de yüklenecektir .

Örneğin: şunları my_lovely_script.jsiçerir MySuperObject:

var js = document.createElement("script");

js.type = "text/javascript";
js.src = jsFilePath;

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

Sonra sayfa isabet yeniden yükleyin F5. Ve çalışıyor! Kafa karıştırıcı...

Peki bu konuda ne yapmalı?

Yazarın size verdiğim linkte önerdiği hack'i kullanabilirsiniz. Özetle, acele eden insanlar için, komut dosyası yüklendiğinde bir geri arama işlevi çalıştırmak için bir olay kullanır. Böylece tüm kodu geri çağrı işlevindeki uzak kitaplığı kullanarak koyabilirsiniz. Örneğin:

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.head;
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

Sonra komut dosyası lambda işlevinde yüklendikten SONRA kullanmak istediğiniz kodu yazarsınız :

var myPrettyCode = function() {
   // Here, do whatever you want
};

Sonra tüm bunları çalıştırın:

loadScript("my_lovely_script.js", myPrettyCode);

Komut dosyasının, DOM yüklendikten sonra veya tarayıcıya ve satırı ekleyip eklemediğinize bağlı olarak daha önce çalıştırılabileceğini unutmayın script.async = false;. Bir var genel JavaScript yükleme büyük makale bu anlatılır.

Kaynak Kodu Birleştirme / Önişleme

Bu cevabın en üstünde belirtildiği gibi, birçok geliştirici projelerinde Parcel, Webpack veya Babel gibi derleme / transpilasyon araçlarını kullanıyor, böylece yaklaşan JavaScript sözdizimini kullanmalarına izin veriyor, eski tarayıcılar için geriye dönük uyumluluk sağlıyor, dosyaları birleştiriyor, küçültüyor, kod bölme vb.


130
Hayır ama Rhino kadar gelişmiş bir şey kullanan ya da başka biri bu soruyu sormazdı.
e-satis

192
Tam olarak söylemek gerekirse, üçüncü bir yol var: Her iki javascript dosyasını da kontrol ederken belirli çözümlerde, her iki dosyanın içeriğini birleştiren 1 dev javascript dosyası oluşturabilirsiniz.
Kurbağa

20
"Document.createElement (" my_lovely_script.js ");" örnekte "document.createElement (" script ")"?
Russell Silva

14
Eval, yürütmekte olduğunuz kodunuzsa bilgisayar korsanlarının kapısını nasıl açar?
Vince Panuccio

6
Cevabınız IE ( onreadystatechangeetkinlik ve readyStateözellik) için bazı değişiklikler gerektiriyor . Ayrıca, dinamik komut dosyası yüklemesi, broswer'in önyükleme tarayıcılarından yararlanamaz. Bu HTML5Rocks makalesini önerin: html5rocks.com/en/tutorials/speed/script-loading
ruhong

570

Birisi daha gelişmiş bir şey arıyorsanız, RequireJS'yi deneyin . Bağımlılık yönetimi, daha iyi eşzamanlılık gibi ek avantajlar elde edersiniz ve çoğaltmayı önlersiniz (yani, bir komut dosyasını bir kereden fazla almak).

JavaScript dosyalarınızı "modüllere" yazabilir ve daha sonra diğer komut dosyalarında bağımlılık olarak başvurabilirsiniz. Veya RequireJS'yi basit bir "bu betiği al" çözümü olarak kullanabilirsiniz.

Misal:

Bağımlılıkları modül olarak tanımlayın:

Bazı-dependency.js

define(['lib/dependency1', 'lib/dependency2'], function (d1, d2) {

     //Your actual script goes here.   
     //The dependent scripts will be fetched if necessary.

     return libraryObject;  //For example, jQuery object
});

implementation.js bağlıdır "ana" JavaScript dosyası olan bazı-dependency.js

require(['some-dependency'], function(dependency) {

    //Your script goes here
    //some-dependency.js is fetched.   
    //Then your script is executed
});

GitHub README'den alıntı :

RequireJS, düz JavaScript dosyalarını ve daha tanımlanmış modülleri yükler. Bir Web Çalışanı dahil olmak üzere tarayıcı içi kullanım için optimize edilmiştir, ancak Rhino ve Node gibi diğer JavaScript ortamlarında kullanılabilir. Asenkron Modül API'sini uygular.

RequireJS, modülleri / dosyaları yüklemek için düz komut dosyası etiketleri kullanır, bu nedenle kolay hata ayıklamaya izin vermelidir. Mevcut JavaScript dosyalarını yüklemek için kullanılabilir. yeniden yazmak zorunda kalmadan mevcut projenize ekleyebilirsiniz.

...


1
@aaaidan: MattDmo'nun sebebi artı kabul edilen cevaba dayanan harici bir kütüphaneye dayanıyor.
David Mulder

1
Requir.js üstesinden gelmek için en son açısal js olacaktır, bu daha bağlayıcı ve zengin HTML özellikleri ile birlikte daha istikrarlı ve kullanımı kolay.
Zeeshan

5
-1: Bu soyutlamalar - "bazı_bağımlılık" - gerçekten zayıftır ve dizinler karışıklığa neden olur. Bir çalışma kodu örneğinin neye benzediğini anlamaya çalışıyorum. Yazar çalışma örneği sağlamış olsaydı, neredeyse herkes bunu kendi ihtiyaçlarına göre uyarlayabilir ve genelleştirebilirdi.
Tegiri Nenashi

1
MVC ve otomatik küçültme ile komut dosyası
gruplaması

1
'JavaScript dosyalarınızı yeniden yazmak zorunda kalmadan ekleyin ..'; havalı, ama tam olarak nasıl? Cur. cevap ana betiğe böyle bir 'zorunlu' ('requirjs' değil mi?) Ama bu yeniden yazılıyor yani yeniden yazılmayan ne? -ReireJS ea dosyası genel olarak normal defs yapmak sağlar izin kod-rest? -yapar? Az önce denedim, + (unuttum?) <Script src = " requirjs.org/docs/release/2.2.0/comments/require.js "> </script>, sonra 'requirjs ([' GoogleDrive.com/host /..',..Red.function(a,b) {mycode}) ': Firebug, yüklenen her bağımlı AMA hatalarının kodumda ve sonrasında tanımlanmadığını söylüyor.
Destiny Architect

195

Orada aslında olan bir JavaScript dosyası yüklemek için bir yol değil bunu yüklenmesinden sonra yeni yüklenen dosya sağ dahil fonksiyonlarını kullanabilir, böylece uyumsuz ve bunu tüm tarayıcılarda çalışır düşünüyorum.

Sen kullanmak gerekir jQuery.append()üzerinde <head>sayfanızın elemanı, yani:

$("head").append('<script type="text/javascript" src="' + script + '"></script>');

Ancak, bu yöntemin de bir sorunu vardır: içe aktarılan JavaScript dosyasında bir hata oluşursa, Firebug (ve ayrıca Firefox Hata Konsolu ve Chrome Geliştirici Araçları da) yerini yanlış bildirir; bu, izlemek için Firebug'u kullanırsanız büyük bir sorundur. JavaScript hataları çok azaldı (yapıyorum). Firebug herhangi bir nedenle yeni yüklenen dosyayı bilmiyor, bu nedenle bu dosyada bir hata oluşursa, bunun ana HTML'nizde oluştuğunu bildiriyor dosyanızda ve hatanın gerçek nedenini bulmakta sorun yaşarsınız.

Ancak bu sizin için bir sorun değilse, bu yöntem işe yaramalıdır.

Aslında bu yöntemi kullanan $ .import_js () adlı bir jQuery eklentisi yazdım :

(function($)
{
    /*
     * $.import_js() helper (for JavaScript importing within JavaScript code).
     */
    var import_js_imported = [];

    $.extend(true,
    {
        import_js : function(script)
        {
            var found = false;
            for (var i = 0; i < import_js_imported.length; i++)
                if (import_js_imported[i] == script) {
                    found = true;
                    break;
                }

            if (found == false) {
                $("head").append('<script type="text/javascript" src="' + script + '"></script>');
                import_js_imported.push(script);
            }
        }
    });

})(jQuery);

Yani JavaScript'i içe aktarmak için yapmanız gereken tek şey:

$.import_js('/path_to_project/scripts/somefunctions.js');

Ben ayrıca bunun için basit bir test yapılmış Örnek .

main.jsAna HTML'de bir dosya ve daha sonra şu işlevi tanımlayan ek bir dosyayı içe aktarmak için main.jskullanılan komut $.import_js()dosyası included.jsiçerir:

function hello()
{
    alert("Hello world!");
}

Ve dahil ettikten hemen sonra included.js, hello()fonksiyon çağrılır ve uyarıyı alırsınız.

(Bu cevap e-satis'in yorumuna yanıt olarak).


Bu yöntemi deniyorum, ama benim için çalışmıyor, öğe sadece kafa etiketinde görünmüyor.
Siteler

16
@juanpastas - kullan jQuery.getScript , bu şekilde eklentiyi yazma konusunda endişelenmenize gerek yok ...
MattDMo

6
Hmm, bu makaleye göre , özel olarak ayarlanmadığı sürece bir scriptöğenin eklenmesi head, eşzamansız olarak çalışmasına neden olacakasyncfalse .
Flimm

1
Komut dosyası değişkeninde html öğeleri kodlanmış olmamalı mı? Bağlantıda ", kod kırılırsa
RedClover

1
@Flimm sevgili efendim, ben ve ekibim yorumunuz için teşekkür ederim ve şahsen tanışırsak kişisel olarak size bile bir bira borçluyum
Alex

155

Başka bir deyişle, bence çok daha temiz, bir <script>etiket kullanmak yerine senkron bir Ajax isteği yapmaktır . Bu, Node.js'nin işleyişini de içerir.

İşte jQuery kullanan bir örnek:

function require(script) {
    $.ajax({
        url: script,
        dataType: "script",
        async: false,           // <-- This is the key
        success: function () {
            // all good...
        },
        error: function () {
            throw new Error("Could not load script " + script);
        }
    });
}

Daha sonra, genellikle bir içerme yöntemini kullandığınız gibi kodunuzda kullanabilirsiniz:

require("/scripts/subscript.js");

Ve sonraki satırda gerekli komut dosyasından bir işlevi çağırabilirsiniz:

subscript.doSomethingCool(); 

1
İyi çözüm, kafa maalesef async, ajax çözümü çalışıyor.
Matteo Conta

17
Başka birinin belirttiği gibi, requirjs.org bunu yapar ve ayrıca daha hızlı yüklenmeleri için js dosyalarını bir araya getiren bir ön derleyiciye sahiptir. Kontrol etmek isteyebilirsiniz.
Ariel

2
Chrome için dosyanın alt kısmına bu yönergeyi ekleyerek hata ayıklayabilirim: // @ sourceURL = view_index.js
Todd Vance

11
talihsiz, zaman uyumsuz: false şimdi jQuery'de kullanımdan kaldırılmıştır. Gelecekte mola verebilir, bu yüzden kaçınırdım.
13'te sqram

3
@katsh Burada jqXHR nesnelerini kullanmıyoruz. async: falseTeklifiniz, kaldırıldığı iddia edilen önceki yorumunuzu desteklemiyor gibi görünüyor . O değil! Alıntı belirttiği gibi, sadece jqXHR ilgili şeyler olduğunu.
Zero3

101

Sizin için iyi bir haber var. Çok yakında JavaScript kodunu kolayca yükleyebileceksiniz. JavaScript kod modüllerini içe aktarmanın standart bir yolu haline gelecek ve temel JavaScript'in kendisinin bir parçası olacaktır.

Bir dosyadan import cond from 'cond.js';adlandırılmış bir makro yüklemek için yazmanız yeterlidir .condcond.js

Dolayısıyla, herhangi bir JavaScript çerçevesine güvenmeniz veya Ajax çağrılarını açıkça yapmanız gerekmez .

Bakınız:


12
jsfile dosyasındaki gereksinim / içe aktarma çok uzun süredir devam ediyor. (IMO).
rwheadon

6
@rwheadon evet bu dilin bir parçası değil gibi görünüyor! İnsanların bir şeyleri nasıl yaptıklarını benden öte! Ben yeni ve bu delilik (birçok) en kötü bit gibi görünüyor
JonnyRaa

@ jonny-leeds Dahili modül yüklemesi olmasa bile tarayıcıdaki JavaScript, modül yönetimimiz için RequireJS gibi bir kitaplık uygulayabileceğimiz kadar esnektir.
Keen

8
2015 ortalarında- Hala herhangi bir tarayıcıda uygulanmadı, developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
scape

Evet haklısın. şimdi bunun için kötü hissetmeye başlıyorum :(. Thouh, bir kez tüm tarayıcılarda uygulandığında bu javascript için yerleşik harika bir özellik olacak.
Imdad

96

Bir JavaScript etiketini dinamik olarak oluşturmak ve diğer JavaScript kodunun içinden HTML belgesine eklemek mümkündür. Bu, hedeflenen JavaScript dosyasını yükleyecektir.

function includeJs(jsFilePath) {
    var js = document.createElement("script");

    js.type = "text/javascript";
    js.src = jsFilePath;

    document.body.appendChild(js);
}

includeJs("/path/to/some/file.js");

8
@ e-satis - Aslında bu bir avantaj, bir senkronizasyon komut dosyası engelliyor olurdu. Kurslar için atlar, ancak 10'da 9 kez engellemeyen seçeneği istiyorsunuz.
annakata

@Svitlana - Bunun gibi oluşturulan komut dosyası öğeleri zaman uyumsuzdur. Şu anda bu bir boşluk açıyor gibi görünebilir, bu yüzden gelecekteki kanıt olmayabilir, herhangi bir standartta bunu açıklayan hiçbir şey görmedim.
annakata

Aslında geri alıyorum, kafa yerine vücuda eklediğinizi fark ettim.
annakata

@annakata: Fark nedir? BTW, yahoo, gövdenin sonuna komut dosyası etiketleri eklemenizi önerir, bu nedenle dinamik olarak eklenirken hiçbir şey yanlış olmamalıdır.
Svitlana Maksymchuk

7
@ e-satis asenkron iyi çünkü sayfanızı dondurmaz. js.onload = callback;
Tamamlandığında

74

Açıklama importECMAScript 6'dadır.

Sözdizimi

import name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import name , { member [ , [...] ] } from "module-name";
import "module-name" as name;

... ancak bağlandığınız sayfadaki uyumluluk tablosuna göre bugüne kadar hiçbir tarayıcı tarafından desteklenmiyor.
Sıfır3

6
Artık ES6 kodunu yazabilir ve tercih ettiğiniz mevcut modül sistemine (CommonJS / AMD / UMD) ne olursa olsun Babel.js ( babeljs.io ) ile derleyebilirsiniz : babeljs.io/docs/usage/modules
Jeremy Harris

@ Zero3 Görünüşe göre yeni IE (Edge) sadece biri
Julian Avar

2019'da IE bunu hiçbir şekilde desteklemiyor. Microsoft neden kullanılabilirliğe karşı bu kadar çok olmalı?
GreySage

61

Belki bu sayfada bulduğum bu işlevi kullanabilirsiniz. JavaScript dosyasına bir JavaScript dosyasını nasıl ekleyebilirim ? :

function include(filename)
{
    var head = document.getElementsByTagName('head')[0];

    var script = document.createElement('script');
    script.src = filename;
    script.type = 'text/javascript';

    head.appendChild(script)
}

5
Eklemek için yararlı olmalıscript.onload = callback;
Vitim.us

@SvitlanaMaksymchuk, eğer kullanmazsam vardeğişken küresel olacak mı?
Francisco Corrales Morales

@FranciscoCorrales evet.
Christopher Chiche

Onunla veya var :) olmaksızın küresel biter
Vedran Maricevic.


54

İşte jQuery olmadan senkron bir sürüm :

function myRequire( url ) {
    var ajax = new XMLHttpRequest();
    ajax.open( 'GET', url, false ); // <-- the 'false' makes it synchronous
    ajax.onreadystatechange = function () {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4) {
            switch( ajax.status) {
                case 200:
                    eval.apply( window, [script] );
                    console.log("script loaded: ", url);
                    break;
                default:
                    console.log("ERROR: script not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

Bu çalışma arası etki alanını elde etmek için sunucunun allow-originyanıtında üstbilgi ayarlaması gerekeceğini unutmayın .


Mükemmel fonksiyon! Gövdeden sonra ek JS yazılmadan önce JavaScript'i yükler. Birden fazla komut dosyası yüklerken çok önemlidir.
tfont

3
@heinob: Web alanları arası için çalışmasını sağlamak için ne yapabilirim? (komut dosyasını yükleme http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570

@ user2284570: Yabancı alan adının sahibiyseniz: sunucu yanıtında `` izin ver '' başlığını ayarlayın. Eğer sahibi değilseniz: hiçbir şey. Afedersiniz! Kökenler arası politika budur.
heinob

2
@ user2284570: Yorumunuzu bu şekilde anlıyorum, betiği yüklemek istediğiniz etki alanının sahibi değilsiniz. Bu durumda, komut dosyasını yalnızca eklenen bir <script>etiketle yükleyebilirsiniz , üzerinden değil XMLHttpRequest.
heinob

2
Bunu Firefox'ta kullanmayı planlayanlar için (örneğin, imacros komut dosyası için), bu satırı dosyanın üstüne ekleyin:const XMLHttpRequest = Components.Constructor("@mozilla.org/xmlextras/xmlhttprequest;1");
Kwestion

49

Sadece (kullanarak bu JavaScript kodu yazdım Prototype için DOM manipülasyon):

var require = (function() {
    var _required = {};
    return (function(url, callback) {
        if (typeof url == 'object') {
            // We've (hopefully) got an array: time to chain!
            if (url.length > 1) {
                // Load the nth file as soon as everything up to the
                // n-1th one is done.
                require(url.slice(0, url.length - 1), function() {
                    require(url[url.length - 1], callback);
                });
            } else if (url.length == 1) {
                require(url[0], callback);
            }
            return;
        }
        if (typeof _required[url] == 'undefined') {
            // Haven't loaded this URL yet; gogogo!
            _required[url] = [];

            var script = new Element('script', {
                src: url,
                type: 'text/javascript'
            });
            script.observe('load', function() {
                console.log("script " + url + " loaded.");
                _required[url].each(function(cb) {
                    cb.call(); // TODO: does this execute in the right context?
                });
                _required[url] = true;
            });

            $$('head')[0].insert(script);
        } else if (typeof _required[url] == 'boolean') {
            // We already loaded the thing, so go ahead.
            if (callback) {
                callback.call();
            }
            return;
        }

        if (callback) {
            _required[url].push(callback);
        }
    });
})();

Kullanımı:

<script src="prototype.js"></script>
<script src="require.js"></script>
<script>
    require(['foo.js','bar.js'], function () {
        /* Use foo.js and bar.js here */
    });
</script>

Gist: http://gist.github.com/284442 .


7
jrburke bunu RequireJS olarak yazdı. Github: requirjs.org/docs/requirements.html
Mike Caron

Bu, yüklü komut dosyasını requir (() ifadesinin çağrıldığı kapsamın dışında bırakmıyor mu? Eval () bunu kapsam dahilinde yapmanın tek yolu gibi görünüyor. Ya da başka bir yol var mı?
trusktr

44

İşte Facebook'un her yerde Beğen düğmesi için nasıl yaptığının genelleştirilmiş bir versiyonu:

<script>
  var firstScript = document.getElementsByTagName('script')[0],
      js = document.createElement('script');
  js.src = 'https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js';
  js.onload = function () {
    // do stuff with your dynamically loaded script
    snowStorm.snowColor = '#99ccff';
  };
  firstScript.parentNode.insertBefore(js, firstScript);
</script>

Facebook için çalışıyorsa, sizin için çalışacaktır.

Bunun scriptyerine headveya yerine ilk öğeyi aramamızın nedeni body, bazı tarayıcıların eksikse bir scriptöğe oluşturmamasıdır, ancak bir öğeye sahip olacağımız garantidir - bu. Daha fazla bilgiyi http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/ adresinde bulabilirsiniz .


3
Acayip güzel! Buradaki yöntemlerden bazıları da işe yarıyor, ancak dinamik bir ayar altında bu en iyi sonucu veriyor.
tfont

cumhuriyeti ortadan kaldırmak için senaryonuzu genişlettim
Kamil Dąbrowski

39

Saf JavaScript istiyorsanız, kullanabilirsiniz document.write.

document.write('<script src="myscript.js" type="text/javascript"></script>');

JQuery kitaplığını kullanıyorsanız, $.getScriptyöntemi kullanabilirsiniz .

$.getScript("another_script.js");

8
document.write diğer her şeyi kaldırmaz mı?
Eisa Adil

30

Komut dosyalarınızı PHP kullanarak da birleştirebilirsiniz :

Dosya main.js.php:

<?php
    header('Content-type:text/javascript; charset=utf-8');
    include_once("foo.js.php");
    include_once("bar.js.php");
?>

// Main JavaScript code goes here

16
Nokta gibi geliyor, tüm bunları ön tarafta javascript'te tutmak
Ariel

1
Bunu hatırlattığın için teşekkürler. HTML başlığınızda PHP yazma <script> etiketlerine de sahip olabilirsiniz, böylece ihtiyacınız olan js dosyaları (ve yalnızca bunlar) yüklenir.
Rolf

29

Burada gösterilen çözümlerin çoğu dinamik yükleme anlamına gelir. Bunun yerine tüm bağlı dosyaları tek bir çıktı dosyasına birleştiren bir derleyici arıyordum. Less / Sass ön işlemcilerinin aynısı CSS @importkuralında da geçerlidir. Bu türden iyi bir şey bulamadığım için, sorunu çözen basit bir araç yazdım.

İşte , istenen dosya içeriğinin güvenli bir şekilde değiştirildiği https://github.com/dsheiko/jsic derleyicisi $import("file-path"). İlgili Grunt eklentisi: https://github.com/dsheiko/grunt-jsic .

JQuery master dalında, atomik kaynak dosyaları ile başlayan intro.jsve biten tek bir dosyada birleştirilirler outtro.js. Kaynak kod tasarımında esneklik sağlamadığından bu bana uymuyor. Jsic ile nasıl çalıştığını kontrol edin:

src / main.js

var foo = $import("./Form/Input/Tel");

src / Form / giriş / Tel.js

function() {
    return {
          prop: "",
          method: function(){}
    }
}

Şimdi derleyiciyi çalıştırabiliriz:

node jsic.js src/main.js build/mail.js

Ve birleştirilmiş dosyayı alın

build / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};

2
Bu yayına beri çok daha iyi çözüm geldi - CommonJS modülü derleyicisi - github.com/dsheiko/cjsc Yani basitçe birbirlerine henüz izole kapsamları içinde tutulması CommonJs veya NodeJs modülleri ve okunabilir ve yazılabilir. Yararları: Performansı etkileyen birden fazla HTTP isteğine gerek yok Modül kodunu manuel olarak sarmanıza gerek yoktur - derleyicinin sorumluluğundadır (bu nedenle daha iyi kaynak kodu okunabilirliği) Herhangi bir harici kütüphaneye ihtiyacınız yoktur UMD- ve NodeJs modülleri (örn. jQuery,
Omurgaya

26

JavaScript dosyasını yükleme amacınız içe aktarılan / dahil edilen dosyadaki işlevleri kullanıyorsa, genel bir nesne de tanımlayabilir ve işlevleri nesne öğeleri olarak ayarlayabilirsiniz. Örneğin:

global.js

A = {};

file1.js

A.func1 = function() {
  console.log("func1");
}

file2.js

A.func2 = function() {
  console.log("func2");
}

main.js

A.func1();
A.func2();

Bir HTML dosyasına komut dosyaları eklerken dikkatli olmanız gerekir. Sipariş aşağıdaki gibi olmalıdır:

<head>
  <script type="text/javascript" src="global.js"></script>
  <script type="text/javascript" src="file1.js"></script>
  <script type="text/javascript" src="file2.js"></script>
  <script type="text/javascript" src="main.js"></script>
</head>

22

Bu şunları yapmalıdır:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);

5
evalyanlış olan bu. Gönderen Crockford , " evalkötülük. Olduğunu eval. Bunu önlemek. Fonksiyonu JavaScript en yanlış kullanılan özelliğidir evaladlar vardır. Kullanmayınız Function. Yapıcısı Dizeleri geçmek etmeyin setTimeoutya setInterval." "JavaScript: İyi Parçalar" ı okumadıysanız hemen dışarı çıkın ve bunu yapın. Sen olacak pişman değil.
MattDMo

13
@MattDMo "Birisi kötü olduğunu söyledi" gerçekten bir tartışma değil.
Casey

4
@emodendroket Sanırım Douglas Crockford'un kim olduğunun farkında değilsiniz .
MattDMo

13
@MattDMo onun kim olduğunun tamamen farkındayım, ama o bir insan, bir tanrı değil.
Casey

2
@tggagne: Web alanları arası için çalışmasını sağlamak için ne yapabilirim? (komut dosyasını yükleme http://web.archive.org/web/20140905044059/http://www.howtocreate.co.uk/operaStuff/userjs/aagmfunctions.js)
user2284570

21

Veya çalışma zamanında dahil etmek yerine, yüklemeden önce birleştirme yapmak için bir komut dosyası kullanın.

Kullandığım dişlisi (başkaları da varsa bilmiyorum). JavaScript kodunuzu ayrı dosyalarda oluşturursunuz ve Sprockets altyapısı tarafından işlenen yorumları dahil edersiniz. Geliştirme için dosyaları sırayla ekleyebilir, daha sonra üretim için bunları birleştirebilirsiniz ...

Ayrıca bakınız:


Browserify , Sprockets'ten çok daha popüler.
Dan Dascalescu

18

Basit bir sorunum vardı, ancak bu soruya verilen yanıtlarla şaşırdım.

Başka bir JavaScript dosyasında (main.js) bir JavaScript dosyasında (myvariables.js) tanımlanan bir değişkeni (myVar1) kullanmak zorunda kaldım.

Bunun için aşağıdaki gibi yaptım:

JavaScript kodunu HTML dosyasına önce doğru sırayla, önce myvariables.js, sonra main.js olarak yükledi:

<html>
    <body onload="bodyReady();" >

        <script src="myvariables.js" > </script>
        <script src="main.js" > </script>

        <!-- Some other code -->
    </body>
</html>

Dosya: myvariables.js

var myVar1 = "I am variable from myvariables.js";

Dosya: main.js

// ...
function bodyReady() {
    // ...
    alert (myVar1);    // This shows "I am variable from myvariables.js", which I needed
    // ...
}
// ...

Gördüğünüz gibi, bir JavaScript dosyasındaki başka bir JavaScript dosyasındaki bir değişkeni kullandım, ancak diğerini eklemem gerekmiyordu. İlk JavaScript dosyasının ikinci JavaScript dosyasından önce yüklendiğinden ve ilk JavaScript dosyasının değişkenlerine ikinci JavaScript dosyasında otomatik olarak erişilebilir olduğundan emin olmam gerekiyordu.

Bu benim günümü kurtardı. Umarım bu yardımcı olur.


Bu cevabın sorunu, bunun gibi bir şey olmamasıdır import. Bir js dosyasından diğerine bir şeyler almak için bir HTML dosyasına ihtiyacınız vardır.
Cannicide

Çok doğru. Diğer bazı cevaplar buna çözüm olarak bakıyor. Ancak iki JS dosyam vardı, biri diğer JS değişkenlerini kullanmalı. Node.js, next.js, express.js, vb. Yok, bu yüzden içe aktarma VEYA gereksinimi işe yaramaz, sadece düz .js dosyaları vardı.
Manohar Reddy Poreddy

Bununla birlikte, anlaşılabilir olan soru, aslında bir HTML dosyası kullanarak değişkenlerine erişmekle kalmayıp, bir javascript dosyasını başka bir dosyanın içine aktarmayı istemektedir. Örneğin, bir düğme için işlevsellik yaptığınızı ve biri tıklama işleme, biri fareyle taşıma için, diğeri diğer ikisinin geri aramaları için olmak üzere üç farklı js dosyası kullandığınızı varsayın. Üçüncü js içindeki diğer iki js'yi içe aktarmak ve sadece bir <script>etikete sahip olmak yararlı olacaktır . Bu organizasyonda yardımcı olabilir. Bu cevap basitçe sorunun istediği şey değildir ve bu bağlamda ideal değildir.
21'de Cannicide

Sorunum için çözüm aradığımda doğru yolu araştırdım, ancak Google bunun doğru sayfa olduğunu düşünüyor, bu yüzden buraya geldim. Bu yüzden cevabımı buraya yazdım. Yukarıdaki 15 upvotes nedeniyle doğru yaptım gibi görünüyor. Başkalarının zamanını boşa harcamamak için, senaryonun ne olduğuna net bir başlangıç ​​yaptım - HTML kodunu önce koydum - yardımcı oldu gibi görünüyor, çünkü html sizin senaryonunuz değil. Umut açıkladı.
Manohar Reddy Poreddy

Evet - aslında bazı insanlar bunun biraz farklı bir sorun aradığı, bunun bir çözüm olduğu ve bunu bulduğu anlaşılıyor. Bu her zaman bu sorunun cevabı olmasa da, kesinlikle başka bir benzer sorunun cevabıdır. Bu nedenle, bu cevabı burada bulmak iyidir, çünkü bu cevabı arayanlara yardımcı olur. Bu cevap için teşekkürler, bu açıklığa kavuştu.
Cannicide

16

Web Workers kullanıyorsanız ve çalışanın kapsamına ek komut dosyaları eklemek istiyorsanız, headetikete komut dosyası vb. Eklemekle ilgili verilen diğer yanıtlar sizin için çalışmaz.

Neyse ki, Web Çalışanlarının kendiimportScripts , belirtimin bir parçası olduğu için tarayıcının kendisine özgü olan Web İşçisi kapsamında küresel bir işlev olan işlevlerine sahiptir .

Alternatif olarak, en yüksek ikinci soru vurgular cevabını oylarıyla , RequireJS da bir Web Worker (muhtemelen çağırarak içindeki komut dahil işleyebilir importScriptsancak birkaç diğer yararlı özelliklere sahip, kendisini).


16

Komut dosyasının önceden yüklenmiş olup olmadığını kontrol eden modern dilde:

function loadJs(url){
  return new Promise( (resolve, reject) => {
    if (document.querySelector(`head > script[src="${src}"]`) !== null) return resolve()
    const script = document.createElement("script")
    script.src = url
    script.onload = resolve
    script.onerror = reject
    document.head.appendChild(script)
  });
}

Kullanım (zaman uyumsuz / beklemede):

try { await loadJs("https://.../script.js") } 
catch(error) {console.log(error)}

veya

await loadJs("https://.../script.js").catch(err => {})

Kullanımı (Söz):

loadJs("https://.../script.js").then(res => {}).catch(err => {})

Güzel. Güzel çözüm.
Naftali aka Neal

Özlü ve sadece ES5'e ihtiyaç duyuyor ve resmi olarak geri aranmasını zarif bir şekilde önlüyor. Teşekkür ederim Dmitry!
Eureka

Vay canına, sunucu olmadan tarayıcıda çalışır. pi.js = basitçe var pi = 3.14. loadJS () fonksiyonunu loadJs("pi.js").then(function(){ console.log(pi); });
çağırın

14

@importJavaScript ithal böyle kendi özel aracılığıyla Karışımı gibi bir araç kullanarak mümkün gibi CSS-ulaşmak için sözdizimi .mixdosya türü (bkz burada ). Ben bilmiyorum olsa da, uygulama sadece yukarıda belirtilen yöntemlerden birini interally kullandığını hayal ediyorum.

.mixDosyalar üzerindeki Mixture belgelerinden :

Mix dosyaları .mix ile .js veya .css dosyalarıdır. dosya adında. Bir mix dosyası normal bir stil veya kod dosyasının işlevselliğini genişletir ve içe aktarmanıza ve birleştirmenize izin verir.

.mixBirden fazla .jsdosyayı tek bir dosyada birleştiren örnek bir dosya :

// scripts-global.mix.js
// Plugins - Global

@import "global-plugins/headroom.js";
@import "global-plugins/retina-1.1.0.js";
@import "global-plugins/isotope.js";
@import "global-plugins/jquery.fitvids.js";

Karışım bunu scripts-global.jsminimize edilmiş bir sürüm ( scripts-global.min.js) olarak ve çıktı olarak verir .

Not: Ön uç geliştirme aracı olarak kullanmak dışında, hiçbir şekilde Mixture ile ilişkili değilim. Bir .mixJavaScript dosyasını çalışırken (Mixture kazanlarından birinde) gördükten ve biraz karıştığımda ("bunu yapabilir misin?" Diye düşündüm) kendi kendime düşündüm. Sonra bir uygulamaya özgü dosya türü (biraz hayal kırıklığı, kabul) olduğunu fark ettim. Yine de, bilginin başkaları için yararlı olabileceğini düşündüm.

GÜNCELLEME : Mixture artık ücretsiz (çevrimdışı).

GÜNCELLEME : Karışım artık üretilmiyor. Eski karışım sürümleri hala mevcuttur


Bir düğüm modülü olsaydı bu harika olurdu.
b01

@ b01 Bir meydan okuma gibi geliyor;) Sadece zamanım olsaydı ... belki başka biri yapar mı?
Isaac Gregson


13

Benim her zamanki yöntemim:

var require = function (src, cb) {
    cb = cb || function () {};

    var newScriptTag = document.createElement('script'),
        firstScriptTag = document.getElementsByTagName('script')[0];
    newScriptTag.src = src;
    newScriptTag.async = true;
    newScriptTag.onload = newScriptTag.onreadystatechange = function () {
        (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') && (cb());
    };
    firstScriptTag.parentNode.insertBefore(newScriptTag, firstScriptTag);
}

Harika çalışıyor ve benim için sayfa yeniden yükleme kullanmıyor. AJAX yöntemini denedim (diğer cevaplardan biri) ama benim için iyi çalışmıyor gibi görünüyor.

İşte merak edilenler için kodun nasıl çalıştığına dair bir açıklama: Aslında, URL'nin yeni bir komut dosyası etiketini (ilkinden sonra) oluşturur. Kodun geri kalanını engellememesi için eşzamansız moda ayarlar, ancak readyState (yüklenecek içeriğin durumu) 'yüklenmiş' olarak değiştiğinde bir geri çağırma çağrısı yapar.


13

Her ne kadar bu cevaplar harika olsa da, betik yüklemesi var olduğundan beri var olan basit bir "çözüm" vardır ve çoğu insanın kullanım durumlarının% 99.999'unu kapsayacaktır. İhtiyacınız olan komut dosyasını gerektiren komut dosyasının önüne eklemeniz yeterlidir. Çoğu proje için hangi komut dosyalarının ve hangi sırayla gerekli olduğunu belirlemek uzun sürmez.

<!DOCTYPE HTML>
<html>
    <head>
        <script src="script1.js"></script>
        <script src="script2.js"></script>
    </head>
    <body></body>
</html>

Script2 script1 gerektiriyorsa, bu gerçekten böyle bir şey yapmanın en kolay yoludur. Kimsenin bunu getirmediğine çok şaşırdım, çünkü neredeyse her vakada uygulanacak en açık ve en basit cevap.


1
Kendim de dahil olmak üzere birçok kişi için tahmin ediyorum, dinamik dosya adına ihtiyacımız var.
Stuart McIntyre

1
Bu durumda @StuartMcIntyre, çalışma zamanında komut dosyası etiketinin src özelliğini ayarlayın ve onload olayını bekleyin (elbette 2019'da bu durumda daha iyi çözümler vardır).
KthProg

12

JavaScript'e modül komut dosyaları alma / dahil etme işini otomatikleştiren basit bir modül yazdım. Kodun ayrıntılı açıklaması için JavaScript talep / içe aktarma / dahil etme modüllerine ilişkin blog yayınına bakın .

// ----- USAGE -----

require('ivar.util.string');
require('ivar.net.*');
require('ivar/util/array.js');
require('http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js');

ready(function(){
    //Do something when required scripts are loaded
});

    //--------------------

var _rmod = _rmod || {}; //Require module namespace
_rmod.LOADED = false;
_rmod.on_ready_fn_stack = [];
_rmod.libpath = '';
_rmod.imported = {};
_rmod.loading = {
    scripts: {},
    length: 0
};

_rmod.findScriptPath = function(script_name) {
    var script_elems = document.getElementsByTagName('script');
    for (var i = 0; i < script_elems.length; i++) {
        if (script_elems[i].src.endsWith(script_name)) {
            var href = window.location.href;
            href = href.substring(0, href.lastIndexOf('/'));
            var url = script_elems[i].src.substring(0, script_elems[i].length - script_name.length);
            return url.substring(href.length+1, url.length);
        }
    }
    return '';
};

_rmod.libpath = _rmod.findScriptPath('script.js'); //Path of your main script used to mark
                                                   //the root directory of your library, any library.


_rmod.injectScript = function(script_name, uri, callback, prepare) {

    if(!prepare)
        prepare(script_name, uri);

    var script_elem = document.createElement('script');
    script_elem.type = 'text/javascript';
    script_elem.title = script_name;
    script_elem.src = uri;
    script_elem.async = true;
    script_elem.defer = false;

    if(!callback)
        script_elem.onload = function() {
            callback(script_name, uri);
        };
    document.getElementsByTagName('head')[0].appendChild(script_elem);
};

_rmod.requirePrepare = function(script_name, uri) {
    _rmod.loading.scripts[script_name] = uri;
    _rmod.loading.length++;
};

_rmod.requireCallback = function(script_name, uri) {
    _rmod.loading.length--;
    delete _rmod.loading.scripts[script_name];
    _rmod.imported[script_name] = uri;

    if(_rmod.loading.length == 0)
        _rmod.onReady();
};

_rmod.onReady = function() {
    if (!_rmod.LOADED) {
        for (var i = 0; i < _rmod.on_ready_fn_stack.length; i++){
            _rmod.on_ready_fn_stack[i]();
        });
        _rmod.LOADED = true;
    }
};

_.rmod = namespaceToUri = function(script_name, url) {
    var np = script_name.split('.');
    if (np.getLast() === '*') {
        np.pop();
        np.push('_all');
    }

    if(!url)
        url = '';

    script_name = np.join('.');
    return  url + np.join('/')+'.js';
};

//You can rename based on your liking. I chose require, but it
//can be called include or anything else that is easy for you
//to remember or write, except "import", because it is reserved
//for future use.
var require = function(script_name) {
    var uri = '';
    if (script_name.indexOf('/') > -1) {
        uri = script_name;
        var lastSlash = uri.lastIndexOf('/');
        script_name = uri.substring(lastSlash+1, uri.length);
    } 
    else {
        uri = _rmod.namespaceToUri(script_name, ivar._private.libpath);
    }

    if (!_rmod.loading.scripts.hasOwnProperty(script_name)
     && !_rmod.imported.hasOwnProperty(script_name)) {
        _rmod.injectScript(script_name, uri,
            _rmod.requireCallback,
                _rmod.requirePrepare);
    }
};

var ready = function(fn) {
    _rmod.on_ready_fn_stack.push(fn);
};

10

Bu komut dosyası, başka herhangi bir <script>etiketin üstüne bir JavaScript dosyası ekleyecektir :

(function () {
    var li = document.createElement('script'); 
    li.type = 'text/javascript'; 
    li.src= "http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"; 
    li.async=true; 
    var s = document.getElementsByTagName('script')[0]; 
    s.parentNode.insertBefore(li, s);
})();

10

Ayrıca Head.js de var . Başa çıkmak çok kolaydır:

head.load("js/jquery.min.js",
          "js/jquery.someplugin.js",
          "js/jquery.someplugin.css", function() {
  alert("Everything is ok!");
});

Gördüğünüz gibi, Require.js'den daha kolay ve jQuery'nin $.getScriptyöntemi kadar kullanışlı . Ayrıca koşullu yükleme, özellik algılama ve çok daha fazlası gibi bazı gelişmiş özelliklere de sahiptir .


10

Bu soru için birçok potansiyel cevap var. Cevabım belli ki bunlara dayanıyor. Tüm cevapları okuduktan sonra bunu yaptım.

$.getScriptYükleme tamamlandığında geri arama gerektiren bir sorun ve gerçekten de başka bir çözüm, onu kullanan ve birbirine bağlı birden fazla dosyanız varsa, artık tüm komut dosyalarının ne zaman yüklendiğini (iç içe yerleştirildikten sonra) bilmenin bir yolunun olmamasıdır. birden çok dosyada).

Misal:

file3.js

var f3obj = "file3";

// Define other stuff

file2.js:

var f2obj = "file2";
$.getScript("file3.js", function(){

    alert(f3obj);

    // Use anything defined in file3.
});

file1.js:

$.getScript("file2.js", function(){
    alert(f3obj); //This will probably fail because file3 is only guaranteed to have loaded inside the callback in file2.
    alert(f2obj);

    // Use anything defined in the loaded script...
});

Ajax'ı senkronize olarak çalıştırabileceğinizi veya XMLHttpRequest'i kullanabileceğinizi söylediğinizde haklısınız , ancak mevcut eğilim senkronize istekleri onaylamıyor gibi görünüyor, bu nedenle şimdi veya gelecekte tam tarayıcı desteği alamayabilirsiniz.

$.whenBir dizi ertelenmiş nesneyi kontrol etmek için kullanmayı deneyebilirsiniz , ancak şimdi bunu her dosyada yapıyorsunuz $.whenve geri arama yürütüldüğünde değil yürütüldüğünde dosya2 yüklenmiş olarak kabul edilecektir, bu nedenle dosya1 yüklenmeden önce dosya1 yine de yürütülmeye devam eder . Bu hala aynı problemi yaşıyor.

İleri gitmek yerine geri gitmeye karar verdim. Teşekkürler document.writeln. Tabu olduğunu biliyorum, ama doğru kullanıldığı sürece bu iyi çalışıyor. Kolayca hata ayıklanabilen, DOM'da doğru bir şekilde gösterilen ve bağımlılıkların doğru bir şekilde yüklenmesini sağlayan kodla sonuçlanırsınız.

Elbette $ ("body"). Append () kullanabilirsiniz, ancak artık artık doğru şekilde hata ayıklayamazsınız.

NOT: Bunu yalnızca sayfa yüklenirken kullanmalısınız, aksi takdirde boş bir ekran elde edersiniz. Başka bir deyişle, bunu her zaman belgenin önüne / dışına yerleştirin . Sayfa bir tıklama olayı veya benzeri bir şey yüklendikten sonra bunu kullanarak test etmedim, ancak başarısız olacağından eminim.

JQuery'yi genişletme fikrini beğendim, ancak açıkçası ihtiyacınız yok.

Aramadan önce document.writeln, tüm komut dosyası öğelerini değerlendirerek komut dosyasının önceden yüklenmediğinden emin olur.

Bir komut dosyası, document.readyolayı yürütülene kadar tam olarak yürütülmediğini varsayıyorum . (Kullanmanın document.readygerekli olmadığını biliyorum , ancak birçok kişi bunu kullanıyor ve bunu korumak bir güvenlik önlemi.)

Ek dosyalar yüklendiğinde document.readygeri aramalar yanlış sırada yürütülür. Bir komut dosyası gerçekten yüklendiğinde bu sorunu gidermek için, içe aktarılan komut dosyası yeniden içe aktarılır ve yürütme durdurulur. Bu, kaynak dosyanın artık document.readyiçeri aktardığı herhangi bir komut dosyasından sonra geri çağrılmasını sağlar.

Bu yaklaşım yerine jQuery'yi değiştirmeyi deneyebilirsiniz readyList, ancak bu daha kötü bir çözüm gibi görünüyordu.

Çözüm:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

Kullanımı:

dosya3:

var f3obj = "file3";

// Define other stuff
$(function(){
    f3obj = "file3docready";
});

file2:

$.import_js('js/file3.js');
var f2obj = "file2";
$(function(){
    f2obj = "file2docready";
});

file1:

$.import_js('js/file2.js');

// Use objects from file2 or file3
alert(f3obj); // "file3"
alert(f2obj); // "file2"

$(function(){
    // Use objects from file2 or file3 some more.
    alert(f3obj); //"file3docready"
    alert(f2obj); //"file2docready"
});

Şu anda kabul edilen cevap tam olarak budur: sadece yeterli değil.
Cannicide

Temel fark, eksik bir bağımlılık varsa, bağımlılık için komut dosyası etiketini ekleyecek, aynı zamanda çağıran dosya için komut dosyası etiketini ekleyeceği ve yürütmeyi durduran bir hata atayacağıdır. Bu, komut dosyalarının işlenmesine ve doğru sırada çalıştırılmasına neden olur ve geri arama gereksinimini ortadan kaldırır. Böylece bağımlı komut dosyası, iç içe yerleştirmeyi desteklerken arama komut dosyasından önce yüklenecek ve yürütülecektir.
curlyhairedgenius

"Mevcut eğilim eşzamanlı istekleri onaylamıyor gibi görünüyor" söz konusu olduğunda, bu durum yalnızca birçok geliştiricinin bunları kötüye kullanması ve kullanıcıların gereksiz yere beklemesini sağlaması nedeniyle geçerlidir. Bununla birlikte, istek bir Include deyimi gibi doğal olarak senkronize ise, basit senkronize Ajax iyi olur. Bir PHP "sunucu" dosyası çalıştırarak JavaScript'in bir parçası olmayan bir dosyayı okumak gibi işlevleri eşzamanlı olarak yürüten genel bir JavaScript uzantısı işlevi oluşturdum ve JavaScript kullanarak uygulamalar yazarken çok yararlı buluyorum. Bu Ajax için yerel bir web sunucusu gerekli değildir.
David Spector

10

Javascript'te modülleri uygulamanın birkaç yolu vardır, İşte en popüler 2 tanesi:

ES6 Modülleri

Tarayıcılar bu modülasyon sistemini henüz desteklemediğinden, bu sözdizimini kullanabilmeniz için webpack gibi bir paketleyici kullanmanız gerekir. Zaten bir paketleyici kullanmak daha iyidir çünkü bu, tüm farklı dosyalarınızı tek bir (veya çift ilişkili) dosyada birleştirebilir. Bu, sunucudan istemciye dosyaları daha hızlı sunacaktır çünkü her HTTP isteğinin yanında bazı ilişkili ek yükler vardır. Böylece genel HTTP isteğini azaltarak performansı geliştiriyoruz. İşte ES6 modüllerine bir örnek:

// main.js file

export function add (a, b) {
  return a + b;
}

export default function multiply (a, b) {
  return a * b;
}


// test.js file

import {add}, multiply from './main';   // for named exports between curly braces {export1, export2}
                                        // for default exports without {}

console.log(multiply(2, 2));  // logs 4

console.log(add(1, 2));  // logs 3

CommonJS ( NodeJS'de kullanılır)

Bu modülasyon sistemi NodeJS'de kullanılır. Dışa aktarmalarınızı temel olarak adlandırılan bir nesneye eklersiniz module.exports. Daha sonra bu nesneye a require('modulePath'). Burada önemli olan, bu modüllerin önbelleğe alındığını fark etmektir, bu nedenle require()belirli bir modülün iki katı ise, önceden oluşturulmuş modülü döndürür.

// main.js file

function add (a, b) {
  return a + b;
}

module.exports = add;  // here we add our add function to the exports object


// test.js file

const add = require('./main'); 

console.log(add(1,2));  // logs 3

9

Bu soruya geldim çünkü yararlı JavaScript eklentileri koleksiyonunu korumanın basit bir yolunu arıyordum. Buradaki bazı çözümleri gördükten sonra şunu buldum:

  1. "Plugins.js" (veya extensions.js veya istediğinizi) adlı bir dosya oluşturun. Eklenti dosyalarınızı bu tek bir ana dosya ile birlikte saklayın.

  2. plugins.js, pluginNames[]tekrarlayacağımız ve each()sonra <script>her eklenti için başlığa bir etiket ekleyeceğimiz adlı bir diziye sahip olacak

//set array to be updated when we add or remove plugin files
var pluginNames = ["lettering", "fittext", "butterjam", etc.];

//one script tag for each plugin
$.each(pluginNames, function(){
    $('head').append('<script src="js/plugins/' + this + '.js"></script>');
});
  1. Manuel olarak kafanızdaki tek bir dosyayı arayın:
    <script src="js/plugins/plugins.js"></script>

FAKAT:

Tüm eklentiler, gerektiği gibi kafa etiketine bırakılsa da, sayfayı tıkladığınızda veya yenilediğinizde tarayıcı tarafından her zaman çalıştırılmazlar.

Ben sadece bir PHP dahil komut dosyası etiketleri yazmak daha güvenilir bulduk. Sadece bir kez yazmanız gerekir ve bu eklentiyi JavaScript kullanarak çağırmak kadar işe yarar.


@will, çözümünüz benimkinden çok daha temiz görünüyor ve benimkini kullanırsam bazı hatalar olabileceğinden endişe ediyorum. Bunu kullanmak için, eklemek istediğiniz her eklenti dosyası için bu işlevi bir kez çağırabilirsiniz?
rgb_life
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.