file подгрузка js - Как включить файл JavaScript в другой файл JavaScript?





15 Answers

Если кто-то ищет что-то более продвинутое, попробуйте RequireJS . Вы получите дополнительные преимущества, такие как управление зависимостями, лучший параллелизм и избегайте дублирования (т. Е. Извлекаете сценарий несколько раз).

Вы можете писать свои файлы JavaScript в «modules», а затем ссылаться на них как на зависимости в других сценариях. Или вы можете использовать RequireJS как простое решение «get get this script».

Пример:

Определить зависимости как модули:

некоторые-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 - ваш «основной» JavaScript-файл, который зависит от some-dependency.js

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

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

Выдержка из GitHub README:

RequireJS загружает простые файлы JavaScript, а также более определенные модули. Он оптимизирован для использования в браузере, в том числе в Web Worker, но его можно использовать в других средах JavaScript, таких как Rhino и Node. Он реализует API асинхронного модуля.

RequireJS использует теги обычного сценария для загрузки модулей / файлов, поэтому он должен обеспечивать легкую отладку. Его можно использовать просто для загрузки существующих файлов JavaScript, поэтому вы можете добавить его в свой существующий проект, не переписывая файлы JavaScript.

...

теги структура файла

Есть ли что-то в JavaScript, подобное @import в CSS, которое позволяет вам включать файл JavaScript в другой файл JavaScript?




Другой способ, который, на мой взгляд, намного чище, состоит в том, чтобы сделать синхронный запрос Ajax вместо использования <script> . Это также относится к Node.js

Вот пример использования 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);
        }
    });
}

Затем вы можете использовать его в своем коде, как обычно, используйте include:

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

И иметь возможность вызывать функцию из требуемого скрипта в следующей строке:

subscript.doSomethingCool(); 



Возможно динамическое создание тега JavaScript и добавление его в HTML-документ из другого кода JavaScript. Это загрузит целевой файл 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");



Возможно, вы можете использовать эту функцию, которую я нашел на этой странице. Как включить файл JavaScript в файл 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)
}



Я просто написал этот код JavaScript (используя Prototype для DOM манипуляции):

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

Использование:

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




Если вы хотите использовать чистый JavaScript, вы можете использовать document.write .

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

Если вы используете библиотеку jQuery, вы можете использовать метод $.getScript .

$.getScript("another_script.js");



Вы также можете собрать свои скрипты с помощью PHP :

Файл 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



Это должно сделать:

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



Если вы используете веб-работников и хотите включить дополнительные сценарии в сферу действия рабочего, другие ответы, связанные с добавлением скриптов в head тег и т. Д., Не будут работать для вас.

К счастью, у веб-рабочих есть своя функция importScripts которая является глобальной функцией в рамках Web Worker, родной самому браузеру, поскольку она является частью спецификации .

В качестве альтернативы, в качестве второго наиболее высоко RequireJS ответа на ваш вопрос подчеркивается , RequireJS также может обрабатывать в том числе скрипты внутри Web Worker (вероятно, сам вызов importScripts , но с несколькими другими полезными функциями).




@importСинтаксис для достижения CSS-как JavaScript импортирования можно с помощью такого инструмента, как смеси через их особый .mixтип файла (см here ). Я полагаю, что приложение просто использует один из вышеупомянутых методов, хотя я не знаю.

Из документации по .mixфайлам Mixture :

Файлы Mix - это файлы .js или .css с .mix. в имени файла. Микс-файл просто расширяет функциональность обычного стиля или файла сценария и позволяет импортировать и комбинировать.

Вот пример .mixфайла, который объединяет несколько .jsфайлов в один:

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

Смесь выводит это как, scripts-global.jsа также как сокращенную версию ( scripts-global.min.js).

Примечание. Я никоим образом не связан с Mixture, кроме использования его в качестве средства разработки на начальном этапе. Я столкнулся с этим вопросом, увидев .mixфайл JavaScript в действии (в одном из шаблонов Mixture) и немного смущенный им («вы можете это сделать?» Подумал я про себя). Затем я понял, что это тип файла приложения (несколько разочаровывающий, согласованный). Тем не менее, полагал, что знание может быть полезным для других.

UPDATE : смесь теперь бесплатна (офлайн).

UPDATE : смесь прекращается. Старые выпуски смеси по-прежнему доступны




Мой обычный метод:

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

Он отлично работает и не использует никаких перезагрузок страниц для меня. Я пробовал метод AJAX (один из других ответов), но он не работает так хорошо для меня.

Вот объяснение того, как код работает для любопытных: по существу, он создает новый тег сценария (после первого) URL-адреса. Он устанавливает его в асинхронный режим, поэтому он не блокирует остальную часть кода, но вызывает обратный вызов, когда readyState (состояние загружаемого содержимого) изменяется на «загружен».




На современном языке это было бы

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}



Существует также Head.js . С этим очень легко справиться:

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

Как вы видите, это проще, чем Require.js и так же удобно, как $.getScriptметод jQuery . Он также имеет некоторые дополнительные функции, такие как условная загрузка, обнаружение функций и многое другое .




На этот вопрос есть много потенциальных ответов. Мой ответ, очевидно, основан на некоторых из них. Это то, что я закончил, прочитав все ответы.

Проблема с $.getScriptи действительно любое другое решение, требующее обратного вызова при загрузке, завершено в том, что если у вас несколько файлов, которые его используют и зависят друг от друга, у вас больше нет возможности узнать, когда загружены все сценарии (когда они вложены в нескольких файлах).

Пример:

file3.js

var f3obj = "file3";

// Define other stuff

file2.js:

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

    alert(f3obj);

    // Use anything defined in file3.
});

file1.js:

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

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

Вы правы, когда говорите, что можете указать Ajax для синхронного запуска или использования XMLHttpRequest , но текущая тенденция, как представляется, заключается в том, чтобы отклонять синхронные запросы, поэтому вы не можете получить полную поддержку браузера сейчас или в будущем.

Вы можете попытаться использовать $.whenмассив отложенных объектов, но теперь вы делаете это в каждом файле, и файл2 будет считаться загруженным, как только он $.whenбудет выполнен не тогда, когда выполняется обратный вызов, так что файл1 продолжает выполнение до того, как будет загружен файл3 , Это по-прежнему имеет ту же проблему.

Я решил вернуться назад, а не вперед. Благодарю вас document.writeln. Я знаю, что это табу, но до тех пор, пока оно используется правильно, это хорошо работает. Вы получаете код, который легко отлаживается, отображается в DOM правильно и может гарантировать правильность загрузки зависимостей.

Конечно, вы можете использовать $ («body»). Append (), но тогда вы больше не можете отлаживать корректно.

ПРИМЕЧАНИЕ. Вы должны использовать это только во время загрузки страницы, иначе вы получите пустой экран. Другими словами, всегда размещайте это перед / за пределами document.ready . Я не тестировал это после того, как страница загружена в событие щелчка или что-то в этом роде, но я уверен, что она потерпит неудачу.

Мне понравилась идея расширения jQuery, но, очевидно, вам это не нужно.

Перед вызовом document.writelnон проверяет, чтобы сценарий еще не загружался, оценивая все элементы сценария.

Я предполагаю, что сценарий не выполнен полностью до document.readyтех пор, пока его событие не будет выполнено. (Я знаю, что использование document.readyне требуется, но многие люди используют его, и обработка этого является защитой.)

Когда дополнительные файлы загружаются, document.readyобратные вызовы будут выполнены в неправильном порядке. Чтобы решить эту проблему, когда сценарий загружен, скрипт, который импортировал его, повторно импортирован сам и выполнение остановлено. Это приводит к тому, что исходный файл теперь document.readyвыполняет обратный вызов после любого из любых импортируемых им скриптов.

Вместо этого подхода вы можете попытаться изменить jQuery readyList, но это казалось худшим решением.

Решение:

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

Использование:

file3:

var f3obj = "file3";

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

File2:

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

File1:

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

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

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



Лучше использовать способ jQuery . Чтобы задержать готовое событие, сначала вызовите $.holdReady(true). Пример ( source ):

$.holdReady(true);
$.getScript("myplugin.js", function() {
    $.holdReady(false);
});





Related