Vraag Hoe voeg ik een JavaScript-bestand toe aan een ander JavaScript-bestand?


Is er iets in JavaScript vergelijkbaar met @import in CSS waarmee je een JavaScript-bestand in een ander JavaScript-bestand kunt opnemen?


4146
2018-06-04 11:59


oorsprong


antwoorden:


De oude versies van JavaScript hadden geen invoer, omvatten of vereisen, er zijn zoveel verschillende benaderingen voor dit probleem ontwikkeld.

Maar recente versies van JavaScript hebben normen zoals ES6-modules om modules te importeren, hoewel dit nog niet wordt ondersteund door de meeste browsers. Veel mensen die modules gebruiken met browsertoepassingen gebruiken bouwen en / of transpilation tools om het praktisch te maken om nieuwe syntaxis te gebruiken met functies zoals modules.

ES6-modules

Merk op dat momenteel de ondersteuning van browsers voor ES6-modules niet bijzonder goed is, maar dat deze onderweg is. Volgens dit StackOverflow-antwoord, ze worden ondersteund in Chrome 61, Firefox 54 (achter de dom.moduleScripts.enabled instellen in about:config) en MS Edge 16, waarbij alleen Safari 10.1 ondersteuning biedt zonder vlaggen.

U zult dus op dit moment nog steeds build- en / of transpilation-tools moeten gebruiken om geldig JavaScript te valideren dat wordt uitgevoerd zonder dat de gebruiker die browserversies hoeft te gebruiken of vlaggen hoeft in te schakelen.

Eens ES6-modules gebruikelijk zijn, is dit de manier om ze te gebruiken:

// module.js
export function hello() {
  return "Hello";
}
// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";

Node.js vereist

Node.js gebruikt momenteel een module.exports / vereisen systeem. Je kunt gebruiken babel om te transponeren als je de import syntaxis.

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

Er zijn andere manieren waarop JavaScript externe JavaScript-inhoud kan opnemen in browsers die geen voorverwerking vereisen.

AJAX laden

U kunt een extra script met een AJAX-aanroep laden en vervolgens gebruiken eval om het uit te voeren. Dit is de meest eenvoudige manier, maar het is beperkt tot uw domein vanwege het JavaScript-sandbox-beveiligingsmodel. Gebruik makend van eval opent ook de deur naar bugs, hacks en beveiligingsproblemen.

jQuery wordt geladen

De jQuery bibliotheek biedt laadfunctionaliteit op één regel:

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

Dynamic Script Loading

U kunt een scripttag met de script-URL toevoegen aan de HTML. Om de overhead van jQuery te vermijden, is dit een ideale oplossing.

Het script kan zelfs op een andere server staan. Verder evalueert de browser de code. De <script> tag kan in de webpagina worden geïnjecteerd <head>, of ingevoegd vlak voor het sluiten </body> label.

Hier is een voorbeeld van hoe dit zou kunnen werken:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script"); // Make a script DOM node
    script.src = url; // Set it's 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)
}

Deze functie voegt een nieuw toe <script> tag aan het einde van het hoofdgedeelte van de pagina, waar de src attribuut is ingesteld op de URL die aan de functie wordt gegeven als de eerste parameter.

Beide oplossingen worden besproken en geïllustreerd in JavaScript Madness: laden van dynamisch script.

Detecteren wanneer het script is uitgevoerd

Nu, er is een groot probleem dat u moet weten. Doen dat impliceert dat je laadt de code op afstand. Moderne webbrowsers laden het bestand en blijven uw huidige script uitvoeren omdat ze alles asynchroon laden om de prestaties te verbeteren. (Dit geldt voor zowel de jQuery-methode als de handmatige dynamische scriptbeladingsmethode.)

Het betekent dat als je deze tricks rechtstreeks gebruikt, je zult je nieuw geladen code niet meer kunnen gebruiken op de volgende regel nadat je hem hebt gevraagd om te worden geladen, omdat het nog steeds wordt geladen.

Bijvoorbeeld: my_lovely_script.js bevat 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

Vervolgens laadt u de pagina opnieuw F5. En het werkt! Verwarrend...

Dus wat te doen?

Welnu, je kunt de hack gebruiken die de auteur suggereert in de link die ik je gaf. Samengevat, voor mensen die haast hebben, gebruikt hij een gebeurtenis om een ​​callback-functie uit te voeren wanneer het script wordt geladen. U kunt dus alle code gebruiken met behulp van de externe bibliotheek in de callback-functie. Bijvoorbeeld:

function loadScript(url, callback)
{
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    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);
}

Vervolgens schrijft u de code die u wilt gebruiken NA het script in a is geladen lambda-functie:

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

Dan loop je dat allemaal:

loadScript("my_lovely_script.js", myPrettyCode);

Merk op dat het script kan worden uitgevoerd nadat de DOM is geladen of daarvoor, afhankelijk van de browser en of u de regel hebt opgenomen script.async = false;. Er is een geweldig artikel over Javascript-laden in het algemeen die dit bespreekt.

Broncode samenvoegen / voorverwerking

Zoals boven aan dit antwoord wordt vermeld, gebruiken veel ontwikkelaars nu bouw / transpilatietool (s) zoals WebPack, Babel of Gulp in hun projecten, waardoor ze nieuwe syntaxis en ondersteuningsmodules beter kunnen gebruiken, bestanden kunnen combineren, verkleinen, enz.


3579
2018-06-04 12:13



Als iemand op zoek is naar iets geavanceerder, probeer het dan RequireJS. U krijgt extra voordelen zoals afhankelijkheidsbeheer, betere gelijktijdigheid en vermijd duplicatie (dat wil zeggen, het ophalen van een script meer dan eens).

U kunt uw JavaScript-bestanden in "modules" schrijven en ze vervolgens verwijzen naar afhankelijkheden in andere scripts. Of u kunt RequireJS gebruiken als een eenvoudige oplossing "ga dit script halen".

Voorbeeld:

Definieer afhankelijkheden als modules:

sommige-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 is uw "hoofd" JavaScript-bestand dat ervan afhankelijk is sommige-dependency.js

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

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

Fragment uit de GitHub LEESMIJ:

RequireJS laadt gewone JavaScript-bestanden en meer gedefinieerd   modules. Het is geoptimaliseerd voor in-browser gebruik, ook in een web   Werknemer, maar het kan ook in andere JavaScript-omgevingen worden gebruikt   Rhino en Node. Het implementeert de Asynchronous Module API.

RequireJS gebruikt duidelijke scripttags om modules / bestanden te laden, dus het zou moeten   zorgen voor eenvoudig debuggen. Het kan eenvoudig worden gebruikt om bestaande te laden   JavaScript-bestanden, dus je kunt het toevoegen aan je bestaande project zonder   je JavaScript-bestanden opnieuw moeten schrijven.

...


513
2018-06-07 20:55



Eigenlijk is een manier om een ​​JavaScript-bestand te laden niet asynchroon, zodat je de functies in je nieuw geladen bestand direct na het laden kon gebruiken, en ik denk dat het in alle browsers werkt.

Je moet gebruiken jQuery.append()op de <head> element van uw pagina, dat is:

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

Deze methode heeft echter ook een probleem: als er een fout optreedt in het geïmporteerde JavaScript-bestand, Firebug (en ook Firefox-foutconsole en Chrome-ontwikkelaarstools ) zal zijn plaats onjuist rapporteren, wat een groot probleem is als je Firebug gebruikt om JavaScript-fouten veel bij te houden (ik doe het). Firebug weet eenvoudigweg niet wat het nieuw geladen bestand is, dus als er een fout optreedt in dat bestand, meldt het dat het in jouw HTML bestand en u zult problemen ondervinden om de echte reden voor de fout te achterhalen.

Maar als dat geen probleem voor u is, zou deze methode moeten werken.

Ik heb eigenlijk een jQuery-plugin geschreven genaamd $ .import_js () welke deze methode gebruikt:

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

Dus alles wat u zou moeten doen om JavaScript te importeren is:

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

Ik heb hier ook een eenvoudige test voor gemaakt Voorbeeld.

Het bevat een main.js bestand in de hoofd HTML en dan het script in main.js toepassingen $.import_js() om een ​​extra bestand met de naam te importeren included.js, die deze functie definieert:

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

En meteen na inclusief included.js, de hello() functie wordt gebeld en u krijgt de waarschuwing.

(Dit antwoord is een reactie op de opmerking van e-satis).


162
2018-04-28 15:25



Een andere manier, die naar mijn mening veel schoner is, is om een ​​synchroon Ajax-verzoek te doen in plaats van een <script> label. En dat is ook hoe Node.js grepen omvat.

Hier is een voorbeeld met behulp van jQuery:

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

U kunt het dan in uw code gebruiken zoals u gewoonlijk een include gebruikt:

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

En in de volgende regel een functie uit het vereiste script kunnen aanroepen:

subscript.doSomethingCool(); 

133
2017-09-08 18:22



Er is goed nieuws voor je. Binnenkort kunt u gemakkelijk JavaScript-code laden. Het wordt een standaardmanier om modules met JavaScript-code te importeren en maakt deel uit van core JavaScript zelf.

Je hoeft alleen maar te schrijven import cond from 'cond.js'; om een ​​macro met de naam te laden cond van een bestand cond.js.

U hoeft dus niet te vertrouwen op een JavaScript-framework, en u hoeft dit ook niet expliciet te doen Ajax noemt.

Verwijzen naar:


86
2017-07-03 13:32



Het is mogelijk om een ​​JavaScript-tag dynamisch te genereren en toe te voegen aan het HTML-document vanuit andere JavaScript-code. Dit laadt een gericht JavaScript-bestand.

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

72
2018-06-04 12:02



Uitspraak import staat in ECMAScript 6.

Syntaxis

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;

58
2018-04-17 01:56



Misschien kunt u deze functie gebruiken die ik op deze pagina heb gevonden Hoe voeg ik een JavaScript-bestand toe aan een JavaScript-bestand?:

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

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

    head.appendChild(script)
}

47
2018-06-04 12:04



Hier is een synchrone versie zonder 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);
}

Houd er rekening mee dat de server moet worden ingesteld om dit werkdomeinsoverschrijdend te krijgen allow-origin header in zijn antwoord.


46
2017-12-11 11:54



Ik heb net deze JavaScript-code geschreven (met Prototype voor DOM manipulatie):

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

Gebruik:

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

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


41
2018-01-23 05:20