Comment inclure un fichier JavaScript dans un autre fichier JavaScript?

y a-t-il quelque chose dans JavaScript similaire à @import dans CSS qui vous permet d'inclure un fichier JavaScript dans un autre fichier JavaScript?

4286
demandé sur Steven Vascellaro 2009-06-04 15:59:50

30 réponses

les anciennes versions de JavaScript n'ont eu aucune importation, inclure, ou exiger, tant de différentes approches à ce problème ont été développées.

mais depuis 2015 (ES6), JavaScript a le modules ES6 standard pour importer des modules dans le noeud.js, qui est également pris en charge par la plupart des navigateurs modernes .

pour la compatibilité avec les navigateurs plus anciens, build et / ou transpilation des outils peuvent être utilisés.

Modules ES6

Les modules

ECMAScript (ES6) ont été pris en charge dans Node.js depuis v8.5, avec le drapeau --experimental-modules . Tous les fichiers concernés doivent avoir l'extension .mjs .

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

modules ECMAScript dans les navigateurs

Les navigateurs

ont eu la possibilité de charger des modules ECMAScript directement (aucun outil comme Webpack requis) depuis Safari 10.1, Chrome 61, Firefox 60, et Edge 16. Vérifiez le support actuel au caniuse .

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

pour en savoir plus: https://jakearchibald.com/2017/es-modules-in-browsers /

Dynamique des importations dans les navigateurs

Dynamique des importations de laisser le script à charger d'autres scripts comme nécessaire:

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

pour en savoir plus: https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js besoin

l'ancien style d'importation de modules, encore largement utilisé dans le noeud.js, est le module .les exportations/exiger du système.

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

il y a d'autres façons pour JavaScript d'inclure le contenu JavaScript externe dans les navigateurs qui ne nécessitent pas prétraitement.

AJAX Loading

vous pouvez charger un script supplémentaire avec un appel AJAX et ensuite utiliser eval pour l'exécuter. C'est le moyen le plus simple, mais il est limité à votre domaine en raison du modèle de sécurité JavaScript sandbox. L'utilisation de eval ouvre également la porte aux bogues, aux piratages et aux problèmes de sécurité.

jQuery Loading

Le jQuery de la bibliothèque fournit la fonctionnalité de chargement dans une ligne :

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

Dynamic Script Loading

vous pouvez ajouter une balise script avec L'URL script dans le HTML. Pour éviter les frais généraux de jQuery, c'est une solution idéale.

le script peut même résider sur un serveur différent. De plus, le navigateur évalue le code. La balise <script> peut être injectée dans la page web <head> , ou inséré juste avant la fermeture </body> étiquette.

voici un exemple de comment cela pourrait fonctionner:

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

cette fonction va ajouter une nouvelle balise <script> à la fin de la section head de la page, où l'attribut src est défini à L'URL qui est donnée à la fonction comme premier paramètre.

ces deux solutions sont discutées et illustrées dans JavaScript Madness: Dynamic Chargement Du Script .

Détecter lorsque le script a été exécuté

maintenant, il y a un gros problème que vous devez connaître. Faire cela implique que vous chargez à distance le code . Les navigateurs Web modernes chargeront le fichier et continueront d'exécuter votre script actuel parce qu'ils chargent tout de façon asynchrone pour améliorer les performances. (Ceci s'applique à la fois à la méthode jQuery et à la méthode de chargement dynamique manuelle des scripts.)

cela signifie que si vous utilisez ces astuces directement, vous ne pourrez pas utiliser votre code nouvellement chargé la ligne suivante après que vous lui ayez demandé d'être chargé , parce qu'il sera encore chargé.

par exemple: my_lovely_script.js contient 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

puis vous rechargez la page en tapant F5 . Et ça marche!!! Déroutant...

alors que faire ?

bien, vous pouvez utiliser le hack que l'auteur suggère dans le lien que je vous ai donné. En résumé, pour les gens pressés, il utilise un événement pour exécuter une fonction de rappel lorsque le script est chargé. Vous pouvez donc mettre tout le code en utilisant la bibliothèque distante dans la fonction de rappel. Par exemple:

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

puis vous écrivez le code que vous voulez utiliser après le script est chargé dans un lambda fonction :

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

puis vous exécutez tout cela:

loadScript("my_lovely_script.js", myPrettyCode);

notez que le script peut s'exécuter après le chargement du DOM, ou avant, selon le navigateur et si vous avez inclus la ligne script.async = false; . Il y a un grand article sur le chargement Javascript en général qui discute de ceci.

Code Source Fusion /Prétraitement

comme mentionné à en haut de cette réponse, de nombreux développeurs utilisent des outils de construction/transpilation comme Parcel, Webpack, ou Babel dans leurs projets, leur permettant d'utiliser la syntaxe JavaScript à venir, fournir une compatibilité ascendante pour les navigateurs plus anciens, combiner des fichiers, minify, effectuer le dédoublement de code, etc.

3679
répondu e-satis 2018-10-08 16:11:26

si quelqu'un cherche quelque chose de plus avancé, essayez RequireJS . Vous obtiendrez des avantages supplémentaires tels que la gestion des dépendances, une meilleure concurrence, et éviterez la duplication (c'est-à-dire récupérer un script plus d'une fois).

vous pouvez écrire vos fichiers JavaScript dans" modules " et les référencer comme des dépendances dans d'Autres scripts. Ou vous pouvez utiliser Require JS comme une solution simple "go get this script".

exemple:

Définir les dépendances entre les modules:

quelques-dépendance.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
});

la mise en œuvre.js est votre fichier JavaScript" principal "qui dépend de la dépendance .js

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

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

extrait du GitHub README:

Requerjs charge des fichiers javascript simples ainsi que de plus en plus définie module. Il est optimisé pour une utilisation dans le navigateur, y compris dans un Mais il peut être utilisé dans D'autres environnements JavaScript, comme Le rhinocéros et le Nœud. Il implémente l'API de Module asynchrone.

Requerjs utilise des balises de script simples pour charger des modules / fichiers, il devrait donc permettre un débogage facile. Il peut être utilisé simplement pour charger existant JavaScript fichiers, si vous pouvez l'ajouter à votre projet existant sans avoir à réécrire votre Les fichiers JavaScript.

...

517
répondu John Strickler 2013-09-28 13:11:26

Il ya effectivement est une façon de charger un fichier JavaScript pas asynchrone, de sorte que vous pourriez utiliser les fonctions incluses dans votre fichier nouvellement chargé juste après le chargement, et je pense qu'il fonctionne dans tous les navigateurs.

vous devez utiliser jQuery.append() sur l'élément <head> de votre page, c'est-à-dire:

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

cependant, cette méthode a également un problème: si une erreur se produit dans le le fichier JavaScript importé, Firebug (et aussi Firefox Error Console et Chrome Developer Tools ainsi) signalera son emplacement incorrect, ce qui est un gros problème si vous utilisez Firebug pour suivre les erreurs JavaScript dans beaucoup (je le fais). Firebug ne sait tout simplement pas à propos du fichier nouvellement chargé pour une raison quelconque, donc si une erreur se produit dans ce fichier, il signale qu'il s'est produit dans votre fichier principal HTML , et vous aurez des problèmes trouver la vraie raison de l'erreur.

Mais si ce n'est pas un problème pour vous, alors cette méthode devrait fonctionner.

j'ai en fait écrit un plugin jQuery appelé $.import_js () qui utilise cette méthode:

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

donc tout ce que vous auriez à faire pour importer JavaScript est:

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

j'ai aussi fait un test simple pour cela à exemple .

il inclut un fichier main.js dans le HTML principal et puis le script dans main.js utilise $.import_js() pour importer un fichier additionnel appelé included.js , qui définit cette fonction:

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

et juste après avoir inclus included.js , la fonction hello() est appelée, et vous obtenez l'alerte.

(cette réponse est en réponse au commentaire d'e-satis).

167
répondu Kipras 2018-03-21 04:29:29

une autre façon, qui à mon avis est beaucoup plus propre, est de faire une requête Ajax synchrone au lieu d'utiliser une étiquette <script> . Qui est aussi comment noeud.les poignées js comprennent.

voici un exemple d'utilisation de 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);
        }
    });
}

vous pouvez alors l'utiliser dans votre code comme vous utilisez habituellement un inclure:

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

et pouvoir appeler une fonction à partir du script requis à la ligne suivante:

subscript.doSomethingCool(); 
134
répondu Ariel 2013-09-28 12:55:50

il y a une bonne nouvelle pour vous. Très bientôt, vous serez en mesure de charger le code JavaScript facilement. Il deviendra un moyen standard d'importer des modules de code JavaScript et fera partie du noyau JavaScript lui-même.

il suffit d'écrire import cond from 'cond.js'; pour charger une macro nommée cond à partir d'un fichier cond.js .

donc vous n'avez pas à vous appuyer sur un cadre JavaScript ni à faire explicitement Ajax appeler.

se référer à:

87
répondu Imdad 2014-10-19 18:05:37

il est possible de générer dynamiquement une balise JavaScript et de l'ajouter au document HTML à partir d'un autre code JavaScript. Cela chargera le fichier JavaScript ciblé.

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");
73
répondu Svitlana Maksymchuk 2013-09-28 12:44:30

Déclaration import est en ECMAScript 6.

syntaxe

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;
59
répondu draupnie 2016-12-11 09:47:07

peut-être Pouvez-vous utiliser cette fonction que j'ai trouvée sur cette page Comment puis-je inclure un fichier JavaScript dans un fichier 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)
}
48
répondu Arnaud Gouder de Beauregard 2014-11-15 17:01:22

voici un synchrone version sans 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);
}

Notez que pour obtenir ce travail inter-domaine, le serveur devra définir allow-origin tête dans sa réponse.

46
répondu heinob 2015-06-18 14:44:10

je viens d'écrire ce code JavaScript (en utilisant Prototype pour DOM manipulation):

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

Utilisation:

<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>
"151920920 de" Résumé: http://gist.github.com/284442 .

41
répondu nornagon 2017-06-25 21:04:40

Voici la version généralisée de comment Facebook le fait pour leur omniprésent comme bouton:

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

si ça marche pour Facebook, ça marchera pour vous.

la raison pour laquelle nous recherchons le premier élément script au lieu de head ou body est parce que certains navigateurs ne créent pas s'ils sont manquants, mais nous sommes garantis d'avoir un élément script - celui-ci. Lire la suite http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element / .

34
répondu Dan Dascalescu 2015-07-08 02:48:05

si vous voulez en JavaScript pur, vous pouvez utiliser document.write .

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

si vous utilisez la bibliothèque jQuery, vous pouvez utiliser la méthode $.getScript .

$.getScript("another_script.js");
29
répondu Venu immadi 2018-03-30 21:20:07

la plupart des solutions présentées ici impliquent une charge dynamique. Je cherchais plutôt un compilateur qui assemblerait tous les fichiers dépendants en un seul fichier de sortie. Le même que moins / Sass les préprocesseurs traitent avec le CSS @import at-rule. Comme je n'ai rien trouvé de décent de ce genre, j'ai écrit un simple outil pour résoudre le problème.

voici donc le compilateur, https://github.com/dsheiko/jsic , qui remplace $import("file-path") par le contenu du fichier demandé en toute sécurité. Voici le correspondant Grunt plugin: https://github.com/dsheiko/grunt-jsic .

sur la branche principale de jQuery, ils concaténent simplement les fichiers sources atomiques en un seul à partir de intro.js et se terminant par outtro.js . Cela ne me convient pas car cela ne fournit aucune flexibilité sur la conception du code source. De vérifier comment il fonctionne avec jsic:

src / main.js

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

src/Forme/Input/Tél.js

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

maintenant nous pouvons exécuter le compilateur:

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

et obtenir le fichier combiné

build/main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
23
répondu Dmitry Sheiko 2014-10-19 18:13:46

vous pouvez également assembler vos scripts en utilisant PHP :

Fichier 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
22
répondu Calmarius 2013-09-28 12:50:11

si votre intention de charger le fichier JavaScript est en utilisant les fonctions du fichier importé/inclus , vous pouvez également définir un objet global et définir les fonctions comme des objets. Par exemple:

global.js

A = {};

fichier1.js

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

fichier2.js

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

principal.js

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

vous avez juste besoin d'être prudent quand vous incluez des scripts dans un fichier HTML. L'ordre devrait être le suivant:

<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>
19
répondu Adem İlhan 2016-12-11 09:42:00

cela devrait faire:

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
17
répondu tggagne 2014-11-02 13:50:20

ou plutôt que d'inclure au moment de l'exécution, utilisez un script pour concaténer avant de télécharger.

j'utilise Pignons (je ne sais pas si il en existe d'autres). Vous créez votre code JavaScript dans des fichiers séparés et incluez des commentaires qui sont traités par le moteur Sprockets comme includes. Pour le développement, vous pouvez inclure des fichiers séquentiellement, puis pour la production de les fusionner...

voir aussi:

16
répondu JMawer 2014-10-19 18:02:51

dans le cas où vous utilisez Web Workers et que vous voulez inclure des scripts supplémentaires dans le champ d'application du worker, les autres réponses fournies sur l'ajout de scripts à la balise head , etc. ne fonctionne pas pour vous.

heureusement, les travailleurs Web ont leur propre importScripts fonction qui est une fonction globale dans la portée du travailleur Web, natif du navigateur lui-même comme il fait partie de la spécification .

alternativement, comme la deuxième réponse la plus élevée votée à votre question met en évidence , RequireJS peut également gérer l'inclusion de scripts à l'intérieur D'un travailleur Web (appelant probablement importScripts lui-même, mais avec quelques autres fonctionnalités utiles).

13
répondu Turnerj 2017-05-23 12:34:59

j'avais un problème simple, mais j'ai été déconcerté par les réponses à cette question.

j'ai dû utiliser une variable (myVar1) définie dans un fichier JavaScript (myvariables.js) dans un autre fichier JavaScript (main.js).

pour ceci j'ai fait comme ci-dessous:

a chargé le code JavaScript dans le fichier HTML, dans le bon ordre, myvariables.js d'abord, puis principal.js:

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

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

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

fichier: myvariables.js

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

Fichier: main.js

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

comme vous l'avez vu, j'avais utilisé une variable dans un fichier JavaScript dans un autre fichier JavaScript, mais je n'avais pas besoin d'inclure une variable dans un autre. J'avais juste besoin de m'assurer que le premier fichier JavaScript chargé avant le deuxième fichier JavaScript, et les variables du premier fichier JavaScript sont accessibles dans le deuxième fichier JavaScript, automatiquement.

ça m'a sauvé la vie. J'espère que cette aide.

12
répondu Manohar Reddy Poreddy 2016-12-11 09:45:11

la syntaxe @import pour réaliser l'importation JavaScript de type CSS est possible en utilisant un outil tel que Mixture via leur type de fichier spécial .mix (voir ici ). J'imagine que l'application utilise simplement l'une des méthodes mentionnées ci-dessus, même si je ne sais pas.

de la documentation sur le mélange dans les fichiers .mix :

Les fichiers de mélange

sont simples .js ou .les fichiers css .mélange. dans le nom de fichier. Un mélanger fichier simplement étend les fonctionnalités d'un style normal ou script file et vous permet d'importer et de combiner.

voici un exemple .mix fichier qui combine plusieurs .js fichiers en un seul:

// 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";
Le mélange

produit ceci en tant que scripts-global.js et aussi en tant que version réduite ( scripts-global.min.js ).

Note: Je ne suis en aucune façon affilié à Mixture, sauf en l'utilisant comme un outil de développement frontal. Je suis tombé sur cette question en voyant un .mix fichier JavaScript en action (dans l'un des boilerplates de mélange) et d'être un peu confus par elle ("vous pouvez faire cela?"J'ai pensé à moi-même). Puis j'ai réalisé qu'il s'agissait d'un type de dossier propre à une application (quelque peu décevant, d'accord). Néanmoins, j'ai pensé que cette connaissance pourrait être utile à d'autres.

mise à jour : le mélange est maintenant libre (Offline.)

mise à jour : le mélange est maintenant arrêté. anciens rejets de mélanges sont toujours disponibles

11
répondu Isaac Gregson 2017-12-17 11:53:48

j'ai écrit un module simple qui automatise le travail d'importation/y compris des scripts de module en JavaScript. Pour une explication détaillée du code, reportez-vous à l'article de blog JavaScript require / import / include modules .

// ----- 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
répondu stamat 2014-10-19 18:26:26

ma méthode habituelle est:

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

cela fonctionne très bien et n'utilise pas de page-recharge pour moi. J'ai essayé la méthode AJAX (l'une des autres réponses), mais il ne semble pas fonctionner aussi bien pour moi.

voici une explication du fonctionnement du code pour ceux qui sont curieux: essentiellement, il crée une nouvelle balise script (après la première) de l'URL. Il le met en mode asynchrone pour qu'il ne bloque pas le reste du code, mais appelle un callback quand la readyState (l'état du contenu à charger) modifications "chargé".

10
répondu Christopher Dumas 2017-08-26 17:02:15
var js = document.createElement("script");

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

document.body.appendChild(js);
9
répondu Sam4Code 2012-08-22 06:44:32

dans la langue moderne il serait

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}
9
répondu Dmitry Sheiko 2017-07-20 15:15:02

ce script ajoutera un fichier JavaScript en haut de n'importe quelle autre étiquette <script> :

(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);
})();
8
répondu Vicky Gonsalves 2014-10-19 18:14:07

il y a aussi tête.js . Il est très facile de traiter avec:

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

comme vous le voyez, c'est plus facile que nécessaire.js et aussi pratique que la méthode $.getScript de jQuery. Il dispose également de certaines fonctionnalités avancées, comme le chargement conditionnel, la détection de fonctionnalités et beaucoup plus .

8
répondu Ale 2014-10-19 18:18:01

je suis venu à cette question parce que je cherchais un moyen simple pour maintenir une collection de plugins JavaScript utiles. Après avoir vu quelques-unes des solutions ici, je suis venu avec ceci:

  1. "configurer un fichier appelé" plugins.js" (ou extensions.js ou qu'avez-vous). Gardez vos fichiers plugin ensemble avec ce fichier maître.

  2. plugins.js aura un tableau appelé " pluginNames []" que nous itérer sur chaque(), puis ajoutez une étiquette à la tête pour chaque plugin

    / / set array à mettre à jour lorsque nous ajoutons ou supprimons des fichiers plugin var pluginNames = ["caractères", "fittext", "butterjam", etc.]; // une étiquette de script pour chaque plugin $.chaque (pluginNames, fonction(){ $('head').annexer''(); });

  3. n'appelez manuellement qu'un seul fichier dans votre tête:

    <script src="js/plugins/plugins.js"></script>

j'ai trouvé que même si tous les plugins étaient tombés dans l'étiquette de tête de la façon dont ils devaient, ils n'étaient pas toujours exécutés par le navigateur quand vous cliquez sur dans la page ou rafraîchir.

j'ai trouvé qu'il est plus fiable de simplement écrire les balises de script dans un include PHP. Vous n'avez qu'à l'écrire une seule fois et c'est tout autant de travail que d'appeler le plugin en utilisant JavaScript.

8
répondu rgb_life 2018-03-30 21:21:29

Il y a beaucoup de réponses possibles à cette question. Ma réponse est évidemment basée sur un certain nombre d'entre eux. C'est ce que j'ai après avoir lu toutes les réponses.

le problème avec $.getScript et vraiment toute autre solution qui nécessite un rappel lorsque le chargement est terminé est que si vous avez plusieurs fichiers qui l'utilisent et dépendent les uns des autres, vous n'avez plus de façon de savoir quand tous les scripts ont été chargés (une fois qu'ils sont imbriqués dans plusieurs fichiers).

exemple:

fichier3.js

var f3obj = "file3";

// Define other stuff

fichier2.js:

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

    alert(f3obj);

    // Use anything defined in file3.
});

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

vous avez raison quand vous dites que vous pouvez spécifier Ajax pour exécuter de manière synchrone ou utiliser XMLHttpRequest , mais la tendance actuelle semble être de déprécier les requêtes synchrones, de sorte que vous ne pouvez pas obtenir le support complet du navigateur maintenant ou dans le avenir.

vous pouvez essayer d'utiliser $.when pour vérifier un tableau d'objets différés, mais maintenant vous le faites dans chaque fichier et file2 sera considéré chargé dès que le $.when est Exécuté pas lorsque le callback est exécuté, donc file1 continue l'exécution avant que file3 ne soit chargé. - Ce vraiment encore a le même problème.

j'ai décidé d'aller en arrière plutôt qu'en avant. Merci document.writeln . Je sais que c'est tabou, mais tant que il est utilisé correctement, cela fonctionne bien. Vous finissez avec du code qui peut être débogué facilement, s'affiche correctement dans le DOM et peut assurer l'ordre dans lequel les dépendances sont chargées correctement.

vous pouvez bien sûr utiliser $ ("corps").ajouter (), mais alors vous ne pouvez plus déboguer correctement.

NOTE: vous devez utiliser ceci seulement pendant que la page charge, sinon vous obtenez un écran vide. En d'autres termes, toujours placer ce avant / à l'extérieur de document.prêt . Je n'ai pas testé en utilisant ceci après que la page soit chargée dans un événement de clic ou quelque chose comme ça, mais je suis assez sûr qu'il échouera.

j'ai aimé l'idée d'étendre jQuery, mais évidemment vous n'avez pas besoin.

avant d'appeler document.writeln , il vérifie pour s'assurer que le script n'a pas déjà été chargé en évaluant tous les éléments du script.

je suppose qu'un script n'est pas entièrement exécuté avant son événement document.ready a été exécuté. (Je sais qu'il n'est pas nécessaire d'utiliser document.ready , mais beaucoup de gens l'utilisent, et le manipuler est une garantie.)

lorsque les fichiers supplémentaires sont chargés les callbacks document.ready seront exécutés dans le mauvais ordre. Pour résoudre ce problème lorsqu'un script est chargé, le script qui l'a importé est réimporté lui-même et l'exécution est arrêtée. Cela fait que le fichier source a maintenant son rappel document.ready exécuté après n'importe quel de tous les scripts qu'il importe.

au lieu de cette approche , vous pourriez essayer de modifier le jQuery readyList , mais cela a semblé comme une solution pire.

Solution:

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

Utilisation:

Fichier3:

var f3obj = "file3";

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

Fichier2:

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

Fichier1:

$.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"
});
8
répondu curlyhairedgenius 2018-03-30 21:22:17

j'ai créé une fonction qui vous permettra d'utiliser un verbiage similaire à C#/Java pour inclure un fichier JavaScript. Je l'ai testé un peu même à l'intérieur de un autre fichier JavaScript et il semble fonctionner. Il ne nécessite jQuery bien pour un peu de "magie" à la fin.

j'ai mis ce code dans un fichier à la racine de mon répertoire script (Je l'ai appelé global.js , mais vous pouvez utiliser ce que vous voulez. Sauf si je me trompe avec jQuery. devrait être le seul script requis sur une page donnée. Gardez à l'esprit que ceci est largement non testé au-delà d'une certaine utilisation de base, de sorte qu'il peut y avoir ou non des problèmes avec la façon dont je l'ai fait; utilisez à vos propres risques yadda yadda Je ne suis pas responsable si vous foirez quelque chose yadda yadda:

/**
* @fileoverview This file stores global functions that are required by other libraries.
*/

if (typeof(jQuery) === 'undefined') {
    throw 'jQuery is required.';
}

/** Defines the base script directory that all .js files are assumed to be organized under. */
var BASE_DIR = 'js/';

/**
* Loads the specified file, outputting it to the <head> HTMLElement.
*
* This method mimics the use of using in C# or import in Java, allowing
* JavaScript files to "load" other JavaScript files that they depend on
* using a familiar syntax.
*
* This method assumes all scripts are under a directory at the root and will
* append the .js file extension automatically.
*
* @param {string} file A file path to load using C#/Java "dot" syntax.
*
* Example Usage:
* imports('core.utils.extensions');
* This will output: <script type="text/javascript" src="/js/core/utils/extensions.js"></script>
*/
function imports(file) {
    var fileName = file.substr(file.lastIndexOf('.') + 1, file.length);

    // Convert PascalCase name to underscore_separated_name
    var regex = new RegExp(/([A-Z])/g);
    if (regex.test(fileName)) {
        var separated = fileName.replace(regex, ",").replace(',', '');
        fileName = separated.replace(/[,]/g, '_');
    }

    // Remove the original JavaScript file name to replace with underscore version
    file = file.substr(0, file.lastIndexOf('.'));

    // Convert the dot syntax to directory syntax to actually load the file
    if (file.indexOf('.') > 0) {
        file = file.replace(/[.]/g, '/');
    }

    var src = BASE_DIR + file + '/' + fileName.toLowerCase() + '.js';
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = src;

    $('head').find('script:last').append(script);
}
7
répondu Wayne Molina 2014-10-18 21:45:38

Mieux utiliser le jQuery . Pour retarder l'événement, appelez d'abord $.holdReady(true) . Exemple ( source ):

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});
6
répondu weageoo 2014-10-19 18:06:16