Czy jest coś w JavaScript podobnym do @import w CSS, który umożliwia dołączenie pliku JavaScript w innym pliku JavaScript?

5510
Alec Smart 4 czerwiec 2009, 15:59

27 odpowiedzi

Najlepsza odpowiedź

Stare wersje JavaScript nie miały importu, obejmują lub wymagają, ponieważ opracowano wiele różnych podejść do tego problemu.

Ale od 2015 r. (ES6), JavaScript miał Moduły ES6 do importowania modułów w węzła.js , który jest również obsługiwany przez najnowocześniejszych przeglądarek.

W przypadku kompatybilności ze starszymi przeglądarkami, narzędzia budować, takie jak webpack i ROLLUP i / lub narzędzia do transpacji, takie jak Babel może być używany.

Moduły ES6.

Moduły ECMAScript (ES6) były Obsługiwane w węzła.js od V8.5, z {{ X0}} Flaga, a ponieważ przynajmniej node.js v13.8.0 bez flagi. Aby włączyć "ESM" (w porównaniu z poprzednim systemem modułu Moduł w stylu Commonjs "[" CJS "]) Używasz "type": "module" w package.json lub podaj pliki przedłużenie .mjs. (Podobnie, moduły napisane za pomocą poprzedniego modułu CJS Node.js można nazwać .cjs Jeśli domyślnie jest EMS.)

Używanie package.json:

{
    "type": "module"
}

Następnie module.js:

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

Następnie main.js:

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

Używanie .mjs, miałbyś module.mjs:

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

Następnie main.mjs:

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

Moduły ekmasscript w przeglądarkach

Przeglądarki posiadali bezpośrednio ładowania modułów ECMAScript (bez narzędzi, takich jak WebPack) od Safari 10.1, Chrome 61, Firefox 60 i Edge 16. Sprawdź aktualne wsparcie w Canius. Nie ma potrzeby użycia Node.js '.mjs Rozszerzenie; Przeglądarki całkowicie ignorują rozszerzenia plików na modułach / skryptach.

<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);
}

Czytaj więcej w https://jakearchid.com/2017/ES-modules-in-browsers /.

Dynamiczny import w przeglądarkach

Dynamiczne impormy Niech skrypt ładuje inne skrypty w razie potrzeby:

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

Czytaj więcej na stronie https://developers.google.com/web/updates/ 2017/11 / Dynamiczny import

Node.js wymagają

Starszy styl modułu CJS, wciąż szeroko stosowany w węzeł }} system.

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

Istnieją inne sposoby dla JavaScript, aby uwzględnić zewnętrzne zawartości JavaScript w przeglądarkach, które nie wymagają wstępnie wstępnego.

Ładowanie Ajax.

Możesz załadować dodatkowy skrypt za pomocą połączenia AJAX, a następnie użyj eval, aby go uruchomić. Jest to najbardziej prosty sposób, ale jest ograniczony do Twojej domeny ze względu na model bezpieczeństwa JavaScript Sandbox. Korzystanie z eval również otwiera drzwi do błędów, hacków i problemów z bezpieczeństwem.

Pobieraj ładowanie

Podobnie jak import dynamiczny, możesz załadować jeden lub wiele skryptów za pomocą połączenia {{x0} "Rel =" NefErr "> Fetch Wstecz biblioteka:

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 Loading.

jQuery biblioteka zapewnia funkcjonalność ładowania w jednej linii:

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

Dynamiczny ładowanie skryptu.

Możesz dodać znacznik skryptu z adresem URL skryptu do HTML. Aby uniknąć nadwygłego jQuery, jest to idealne rozwiązanie.

Skrypt może nawet przebywać na innym serwerze. Ponadto przeglądarka ocenia kod. Znacznik {{x0} można wstrzyknąć na stronę internetową <head> lub włożona tuż przed zamknięciem {x2}}.

Oto przykład, jak to może działać:

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)
}

Ta funkcja będzie dodać znacznik nowego {x0}} na końcu sekcji głowy strony, w której atrybut src jest ustawiony na adres URL, który podano funkcję jako pierwszy parametr.

Oba te rozwiązania są omawiane i zilustrowane w Madness JavaScript: Dynamic Script Loading.

Wykrywanie, gdy skrypt został wykonany

Teraz jest duży problem, o którym musisz wiedzieć. Robiąc to, że zdalnie załadujesz kod . Nowoczesne przeglądarki internetowe załadują plik i wykonują bieżący skrypt, ponieważ ładują wszystko asynchronicznie, aby poprawić wydajność. (Dotyczy to zarówno metody jQuery, jak i manualnej metody ładowania skryptu dynamicznego).

Oznacza to, że jeśli używasz tych sztuczek bezpośrednio, nie będziesz mógł użyć nowo załadowanego kodu następnego wiersza po zwróceniu go do załadowania , ponieważ nadal będzie ładować.

Na przykład: my_lovely_script.js zawiera 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

Następnie przeładujesz Uderzanie strony F5 . I to działa! Mylące...

więc co z tym zrobić?

Cóż, możesz użyć hack autor sugeruje w linku, który ci dałem. Podsumowując, dla osób w pośpiechu, używa zdarzenia, aby uruchomić funkcję wywołania zwrotnego po załadowaniu skryptu. Możesz więc umieścić cały kod za pomocą zdalnej biblioteki w funkcji wywołania zwrotnego. Na przykład:

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);
}

Następnie napiszesz kod, którego chcesz użyć po załadowaniu skryptu w Funkcja Lambda:

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

Następnie prowadzisz to wszystko:

loadScript("my_lovely_script.js", myPrettyCode);

Należy pamiętać, że skrypt może wykonywać po załadowaniu lub wcześniej, w zależności od przeglądarki i niezależnie od tego, czy włączyłeś linię script.async = false;. Jest Świetny artykuł na temat ładowania JavaScript w ogólnie, który omówi to.

Kod źródłowy Scal / PROCESSING

Jak wspomniano na szczycie tej odpowiedzi, wielu deweloperów korzysta z narzędzi budowy / transpilacji, takich jak paczka, webpack lub babel w swoich projektach, umożliwiając im korzystanie z nadchodzącej składni JavaScript, zapewnić kompatybilność wstecz dla starszych przeglądarek, łącząc, minify, Wykonaj rozszczepienie kodu itp.

4742
T.J. Crowder 21 marzec 2020, 09:09

Ten skrypt dodać plik JavaScript na górę dowolnego innego {X0}} Tag:

(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
Peter Mortensen 19 październik 2014, 18:14

Jeśli ktoś szuka czegoś bardziej zaawansowanego, wypróbuj wymagać. Dostaniesz dodatkową korzyści, takie jak zarządzanie zależność, lepsza współbieżność i unikać powielania (czyli, pobieranie skryptu więcej niż raz).

Możesz napisać pliki JavaScript w "Modułach", a następnie odniesienia do nich jako zależności w innych skryptach. Możesz też używać rozwiązania Wagi jako prostego "GO Get Ten skrypt".

Przykład:

Zdefiniuj zależności jako moduły:

niektóre-zależne.js.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
});

implementacja.js to twój plik JavaScript "główny", który zależy od niektórych zależności

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

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

Fragment z GitHub Readme:

Oddaje się ładować zwykłe pliki JavaScript, a także bardziej zdefiniowanych modułów. Jest zoptymalizowany do użytku w przeglądarce, w tym w pracownika internetowym, ale może być stosowany w innych środowiskach JavaScript, takich jak Rhino i węzeł. Implementuje Asynchroniczne API modułu.

Wymagać spożywania zwykłych znaczników skryptów do załadowania modułów / plików, więc powinno Pozwól na łatwe debugowanie. Może być używany tylko do załadowania istniejących Pliki JavaScript, więc Możesz dodać go do istniejącego projektu bez Muszę ponownie napisać pliki JavaScript.

...

592
Peter Mortensen 28 wrzesień 2013, 13:11

W rzeczywistości istnieje jest sposobem załadowania pliku JavaScript nie asynchronicznie, dzięki czemu można użyć funkcji zawartych w nowo załadowanym pliku zaraz po załadowaniu i myślę, że działa Wszystkie przeglądarki.

Musisz użyć jQuery.append() na elemencie <head>, czyli:

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

Jednak ta metoda ma również problem: jeśli błąd nastąpi w importowanym pliku JavaScript, Firebug (a także konsola błędów Firefox i Chrome Developer Tool również) Zgłoszenie Nieprawidłowe miejsce, co jest dużym problemem, jeśli używasz ognisk, aby śledzić błędy javascript w dół (robię). Firebug Po prostu nie wie o nowo załadowanym pliku z jakiegoś powodu, więc jeśli wystąpi błąd w tym pliku, informuje, że wystąpiło to w głównym HTML plik, a będziesz miał problem z odkryciem prawdziwego powodu błędu.

Ale jeśli to nie jest problem, to ta metoda powinna działać.

Napisałem wtyczkę jquery zwaną $. Import_js () , który wykorzystuje tę metodę:

(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);

Więc wszystko, co musisz zrobić, aby zaimportować JavaScript:

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

Wykonałem również prosty test na to w przykład.

Obejmuje plik main.js w głównym HTML, a następnie skrypt w main.js używa $.import_js(), aby zaimportować dodatkowy plik o nazwie included.js, który określa tę funkcję:

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

I zaraz po tym, włączony jest funkcja hello() hello() i otrzymasz alert.

(Ta odpowiedź jest w odpowiedzi na e-satis "komentarz).

212
31piy 21 marzec 2018, 04:29

Jest dla ciebie dobra wiadomość. Wkrótce będzie można łatwo załadować kod JavaScript. Stanie się standardowym sposobem importowania modułów kodu JavaScript i będzie częścią samego JavaScript Core.

Po prostu musisz napisać import cond from 'cond.js';, aby załadować makro o nazwie {x1}} z pliku cond.js.

Więc nie musisz polegać na żadnym ramie JavaScript, ani nie musisz wyraźnie zrobić ajax połączenia.

Odnosić się do:

108
Peter Mortensen 19 październik 2014, 18:05

Możliwe jest dynamiczne generuje znacznik JavaScript i dołącz go do dokumentu HTML od wewnątrz innego kodu JavaScript. Spowoduje to załadowanie ukierunkowanego pliku JavaScript.

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");
106
Peter Mortensen 28 wrzesień 2013, 12:44

Oświadczenie import jest w ECMAScript 6.

Składnia

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;
78
Peter Mortensen 11 grudzień 2016, 09:47

Może można użyć tej funkcji, którą znalazłem na tej stronie Jak dołączyć javascript Plik w pliku JavaScript? :

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

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

    head.appendChild(script)
}
64
Ajeet Lakhani 15 listopad 2014, 17:01

Oto synchroniczna wersja bez jQuery :

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);
}

Należy pamiętać, że aby uzyskać tę robotną domenę, serwer będzie musiała ustawić nagłówek allow-origin w odpowiedzi.

57
Flimm 18 czerwiec 2015, 14:44

Właśnie napisałem ten kod JavaScript (używając prototyp dla Dom Manipulacja):

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);
        }
    });
})();

Stosowanie:

<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.

52
Talha Awan 25 czerwiec 2017, 21:04

Oto uogólniona wersja tego, jak Facebook robi na ich wszechobecnym jak przycisk:

<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>

Jeśli działa na Facebooku, będzie to działać.

Powodem, dla którego szukamy pierwszego elementu script zamiast head lub body jest dlatego, że niektóre przeglądarki nie tworzą go, jeśli brakuje nam, ale gwarantujemy mieć {{x3 }} Element - Ten. Czytaj więcej w http://www.jspatterns.com/the--ridiculous- CASE-of-adding-A-Script-Element /.

46
Dan Dascalescu 8 lipiec 2015, 02:48

Jeśli chcesz w czystym javascript, możesz użyć document.write.

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

Jeśli korzystasz z biblioteki jQuery, możesz użyć metody $.getScript.

$.getScript("another_script.js");
45
Peter Mortensen 3 październik 2020, 20:47

Możesz także montować swoje skrypty za pomocą PHP:

Plik 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
32
Peter Mortensen 28 wrzesień 2013, 12:50

Większość wyświetlanych tutaj rozwiązań implikuje dynamiczne ładowanie. Wyszukiwałem zamiast kompilatora, który montuje wszystkie zależne pliki w jednym pliku wyjściowym. Tak samo jak Mniej / Sass Preprocesory radzą sobie z regułą CSS @import. Odkąd nie znalazłem żadnego zadowolenia tego rodzaju, napisałem proste narzędzie rozwiązujące problem.

Oto kompilator, https://github.com/dsheiko/jsic, który zastępuje $import("file-path") z żądanym Bezpiecznie zawartość plików. Oto odpowiednia https: // github.com/dsheiko/grunt-jsic.

Na gałęzi mistrza jQuery po prostu po prostu połączyć pliki źródłowe atomowego w pojedynczy, zaczynając od intro.js i kończąc się z outtro.js. To nie pasuje do mnie, ponieważ nie zapewnia elastyczności projektu kodu źródłowego. Sprawdź, jak działa z JSIC:

src / main.js

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

src / formularz / wejście / tel.js

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

Teraz możemy uruchomić kompilator:

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

I zdobądź kombinowany plik

budować / main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
30
Peter Mortensen 19 październik 2014, 18:13

Jeśli zamiar załadowania pliku JavaScript jest za pomocą funkcji z importowanego / zawarte pliku , można również zdefiniować globalny obiekt i ustaw funkcje jako elementy obiektu. Na przykład:

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();

Wystarczy być ostrożnym, gdy włączysz się skrypty w pliku HTML. Zamówienie powinno być poniżej:

<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>
27
Peter Mortensen 11 grudzień 2016, 09:42

To powinno wystarczyć:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
23
Peter Mortensen 2 listopad 2014, 13:50

Miałem prosty problem, ale byłem zaskoczony odpowiedziami na to pytanie.

Musiałem użyć zmiennej (myvar1) zdefiniowanej w jednym pliku JavaScript (myvariatles.js) w innym pliku JavaScript (Main.js).

Dla tego zrobiłem jak poniżej:

Załadował kod JavaScript w pliku HTML, we właściwej kolejności, najpierw MyVariatles.js najpierw, a następnie main.js:

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

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

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

Plik: myvaritebles.js.

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

Plik: Main.js.

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

Jak widziałem, użyłem zmiennej w jednym pliku JavaScript w innym pliku JavaScript, ale nie musiałem włączyć jednego w innym. Właśnie musiałem upewnić się, że pierwszy plik JavaScript został załadowany przed drugim plikiem JavaScript, a pierwsze zmienne pliku JavaScript są dostępne w drugim pliku JavaScript, automatycznie.

To uratowało mój dzień. Mam nadzieję, że to pomoże.

21
Peter Mortensen 11 grudzień 2016, 09:45

W przypadku, gdy używasz pracownicy Web i chcesz dołączyć Dodatkowe skrypty w zakresie robotnika, inne odpowiedzi podane na temat dodawania skryptów do znacznika {x0}} itp. Nie będzie działać dla Ciebie.

Na szczęście, Pracownicy Web mają własne importScripts Funkcja, która jest funkcją globalną w zakresie pracownika internetowego, pochodzący z samej przeglądarki, jak go jest częścią specyfikacji.

Alternatywnie, Jako druga najwyższa głosowa odpowiedź na twoje wyniki pytania, Wagi może również obsługiwać skrypty wewnątrz pracownika internetowego (prawdopodobnie wywołanie importScripts, ale z kilkoma innymi użytecznymi funkcjami).

17
Community 23 maj 2017, 12:34

Składnia @import do osiągnięcia importowania JavaScript CSS jest możliwa przy użyciu narzędzia, takiego jak mieszanina za pomocą ich specjalnego .mix typ pliku (patrz Oto). Wyobrażam sobie, że aplikacja po prostu wykorzystuje jedną z wyżej wymienionych metod w interkwie, chociaż nie wiem.

Z dokumentacji mieszanki na plikach .mix:

Pliki mieszania są po prostu plikami .js lub .css z .mix. W nazwie pliku. Plik mieszanki po prostu rozszerza funkcjonalność normalnego stylu lub pliku skryptowego i umożliwia importowanie i łączenie.

Oto przykład .mix, który łączy wiele plików .js do jednego:

// 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";

Mieszanina Wyjścia to jako scripts-global.js, a także jako wersja minify (scripts-global.min.js).

Uwaga: Nie jestem w żaden sposób powiązany z mieszaniną, inną niż używając go jako narzędzia do rozwoju front-end. Nadszedłem na to pytanie, po zobaczeniu pliku JavaScript .mix w akcji (w jednej z kotłach mieszanki) i bycie nieco zdezorientowanym ("możesz to zrobić?" Pomyślałem sobie). Wtedy zdałem sobie sprawę, że był to typ pliku specyficzny dla aplikacji (nieco rozczarowujący, uzgodniony). Niemniej jednak wiedza może być pomocna dla innych.

Aktualizacja : Mieszanka jest teraz za darmo (offline).

Aktualizacja : Mieszanina jest teraz przerwana. Old Mieszanina wersje są nadal dostępne

16
Isaac Gregson 5 październik 2020, 17:34

Chociaż te odpowiedzi są świetne, istnieje proste "rozwiązanie", które znajdują się w pobliżu, ponieważ istnieje obciążenie skryptowe i obejmuje 99,999% przypadków wykorzystania większości ludzi. Wystarczy zawierać skrypt, którego potrzebujesz przed skryptem, który go wymaga. Dla większości projektów nie trwa długo, aby określić, które skrypty są potrzebne i w jakiej kolejności.

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

Jeśli script2 wymaga skryptu1, to naprawdę absolutny najłatwiejszy sposób zrobić coś takiego. Jestem bardzo zaskoczony, nikt tego nie przyniósł, ponieważ jest to najbardziej oczywista i najprostsza odpowiedź, która będzie miała zastosowanie w prawie każdej sprawie.

15
KthProg 12 kwiecień 2018, 19:38
var js = document.createElement("script");

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

document.body.appendChild(js);
14
Spudley 22 sierpień 2012, 06:44

Moja zwykła metoda to:

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);
}

Działa świetnie i nie używa dla mnie przeładowania stron. Próbowałem metody Ajax (jedna z innych odpowiedzi), ale nie wydaje się, aby nie działa tak ładnie dla mnie.

Oto wyjaśnienie, jak działa kod dla tych, którzy są ciekawi: zasadniczo, tworzy nową znacznik skryptu (po pierwszym) URL. Ustawia go do trybu asynchronicznego, dzięki czemu nie blokuje reszty kodu, ale wywołuje wywołanie zwrotne, gdy ReadyState (stan zawartości do załadowania) zmienia się na "załadowany".

13
Christopher Dumas 26 sierpień 2017, 17:02

Napisałem prosty moduł, który automatyzuje zadanie importowania / włuchania skryptów modułów w JavaScript. Szczegółowe wyjaśnienie kodu znajduje się w blogu post JavaScript wymaga / importuj / zawierać moduły .

// ----- 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);
};
12
Peter Mortensen 19 październik 2014, 18:26

Istnieje również Head.js. Jest bardzo łatwy do czynienia z:

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

Jak widzisz, łatwiej niż wymagać.js i tak wygodne jak metoda jQuery Posiada również kilka zaawansowanych funkcji, takich jak obciążenie warunkowe, wykrywanie funkcji i znacznie więcej.

10
Peter Mortensen 19 październik 2014, 18:18

Istnieje wiele potencjalnych odpowiedzi na to pytanie. Moja odpowiedź jest oczywiście oparta na ich wielu. To właśnie skończyło się po przeczytaniu wszystkich odpowiedzi.

Problem z $.getScript i naprawdę wszelkie inne rozwiązania, które wymaga zwrotnego podczas ładowania, jest to, że jeśli masz wiele plików, które go używają i zależą od siebie, nie masz już sposobu, aby wiedzieć, kiedy wszystkie skrypty zostały załadowane (Po zagnieżdżaniu w wielu plikach).

Przykład:

File3.js.

var f3obj = "file3";

// Define other stuff

Plik2.js:

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

    alert(f3obj);

    // Use anything defined in file3.
});

Plik1.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...
});

Masz rację, gdy mówisz, że można określić AJAX do uruchomienia synchronicznie lub używać XMLHTTPREQUEST, ale Bieżący trend wydaje się być niedoszacowywanie żądań synchronicznych, dzięki czemu możesz teraz uzyskać pełną obsługę przeglądarki teraz lub w przyszłości.

Możesz spróbować użyć $.when, aby sprawdzić tablicę odroczonych obiektów, ale teraz robisz to w każdym pliku, a plik2 zostanie uznany za załadowany, gdy tylko $.when zostanie wykonany, gdy wywołanie wywołania wywołania wywołania zwrotnego , więc plik1 nadal kontynuuje wykonanie przed załadowaniem pliku3. To naprawdę ma ten sam problem.

Postanowiłem iść do tyłu zamiast do przodu. Dziękuję document.writeln. Wiem, że to tabu, ale tak długo, jak służy poprawnie, to działa dobrze. Skończysz z kodem, który można łatwo debugować, pokazuje poprawnie w Domu i może zapewnić porządek, które zależności są ładowane prawidłowo.

Możesz oczywiście użyć $ ("body"). Dołącz (), ale wtedy nie możesz już dłużej debugować.

Uwaga: Musisz użyć tego tylko podczas ładowania strony, w przeciwnym razie otrzymasz pusty ekran. Innymi słowy, zawsze umieszczają to przed / na zewnątrz dokumentu.Ready . Nie przetestowałem tego, gdy strona jest załadowana w zdarzeniu kliknięcia lub cokolwiek takiego, ale jestem pewien, że nie powiedzie się.

Podobał mi się pomysł rozszerzania jQuery, ale oczywiście nie musisz.

Przed wywołaniem {X0}} sprawdza, czy skrypt nie został jeszcze załadowany, oceniając wszystkie elementy skryptu.

Zakładam, że skrypt nie jest w pełni wykonany, dopóki document.ready wydarzenia zostało wykonane. (Wiem, że używam document.ready nie jest wymagane, ale wielu ludzi używa go, a obsługuje to zabezpieczenie.)

Po załadowaniu dodatkowych plików document.ready wywołania zwrotne będą wykonywane w niewłaściwym porządku. Aby rozwiązać to, gdy skrypt jest faktycznie załadowany, skrypt, który importowany jest ponownie importowany, a wykonanie zatrzymane. Powoduje to teraz, że plik pochodzący ma document.ready Callback wykonany po każdym z dowolnych skryptów, które importuje.

Zamiast tego podejścia można próbować zmodyfikować jQuery readyList, ale wydawało się to najgorszym rozwiązaniem.

Rozwiązanie:

$.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;
    }
});

Stosowanie:

Plik3:

var f3obj = "file3";

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

Plik2:

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

Plik1:

$.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"
});
10
Community 20 czerwiec 2020, 09:12

Doszedłem do tego pytania, ponieważ szukałem prostego sposobu utrzymania kolekcji przydatnych wtyczek JavaScript. Po obejrzeniu niektórych rozwiązań tutaj wymyśliłem:

  1. Skonfiguruj plik o nazwie "plugins.js" (lub rozszerzenia.js lub cokolwiek chcesz). Zachowaj pliki wtyczki razem z tym jednym plikiem głównym.

  2. Wtyczki Następnie załóż znacznik <script> do głowy dla każdej wtyczki

//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. Ręcznie zadzwoń tylko jeden plik w głowie:
    <script src="js/plugins/plugins.js"></script>

ALE:

Nawet jeśli wszystkie wtyczki zostają upuszczone do tagu głowy, jak powinni, nie zawsze są prowadzone przez przeglądarkę po kliknięciu na stronę lub odświeżanie.

Znalazłem, że jest bardziej niezawodny, aby wpisać tagi skryptów w PHP, obejmują. Musisz tylko napisać go raz, a tyle tak dużo pracy jako dzwoniąc do wtyczki za pomocą JavaScript.

10
rgb_life 10 styczeń 2020, 05:03

Istnieje kilka sposobów na wdrożenie modułów w JavaScript, tutaj są 2 najbardziej popularne:

moduły ES6

Przeglądarki nie obsługują jeszcze tego systemu modułu, aby korzystać z tej składni, musisz użyć tej składni, jak webpack. Korzystanie z Bundlera jest lepsze, ponieważ może to połączyć wszystkie różne pliki w pojedynczą (lub parę związanych). Dotyczy to plików z serwera do klienta szybciej, ponieważ każde żądanie HTTP ma jakieś powiązane nadwyżek towarzyszący mu. Zatem zmniejszając żądanie Overal HTTP poprawiamy wydajność. Oto przykład modułów ES6:

// 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 (używane w NodeJs)

Ten system modułu używany jest w NodeJs. Zasadniczo dodasz eksport do obiektu, który nazywa się module.exports. Następnie możesz uzyskać dostęp do tego obiektu za pomocą require('modulePath'). Ważne jest, aby uświadomić sobie, że te moduły są buforowane, więc jeśli require() niektóre moduł dwukrotnie zwróci już utworzony moduł.

// 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
10
Peter Mortensen 3 październik 2020, 20:17