Как включить файл JavaScript в другой файл JavaScript?

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

4194
задан Alec Smart 04 июня '09 в 14:59
источник поделиться
55 ответов
  • 1
  • 2

В старых версиях JavaScript не было импорта, включения или необходимости, так много разных подходов к этой проблеме были разработаны.

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

Модули ES6

Обратите внимание, что в настоящее время поддержка браузера для модулей ES6 не особенно велика, но она уже в пути. Согласно qaru.site/questions/23046/..., они поддерживаются в Chrome 61, Firefox 54 (за кодом dom.moduleScripts.enabled в about: config) и MS Edge 16, причем только Safari 10.1 обеспечивает поддержку без флагов.

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

Как только ES6-модули являются обычными, вот как вы могли бы их использовать:

 //module.js
экспорт функции hello() { return  "Hello";
}
Код>
 //main.js
import {hello} из 'module';//или './module'
пусть val = hello();//val -  "Hello";
Код>

Node.js требует

В настоящее время Node.js использует module.exports/require. Вы можете использовать babel, чтобы преобразовать, если вы хотите синтаксис import.

 //mymodule.js
module.exports = {  hello: function() {     return  "Hello";  }
}
Код>
 //server.js
const myModule = require ('./mymodule');
пусть val = myModule.hello();//val - это  "Hello" 
Код>

Есть и другие способы включения JavaScript в JavaScript для браузеров, которые не требуют предварительной обработки.

Загрузка AJAX

Вы можете загрузить дополнительный скрипт с помощью вызова AJAX, а затем использовать eval для его запуска. Это самый простой способ, но он ограничен вашим доменом из-за модели безопасности песочницы JavaScript. Использование eval также открывает дверь для ошибок, хаков и проблем безопасности.

Загрузка jQuery

Библиотека jQuery предоставляет функции загрузки в одной строке:

  $. getScript ( "my_lovely_script.js", function() {  alert ( "Сценарий загружен, но не обязательно выполняется" );
});
Код>

Загрузка динамического сценария

Вы можете добавить тег скрипта с URL-адресом сценария в HTML. Чтобы избежать накладных расходов на jQuery, это идеальное решение.

Сценарий может находиться на другом сервере. Кроме того, браузер оценивает код. Тег <script> можно вводить либо на веб-страницу <head>, либо вставлять непосредственно перед закрывающим </body>.

Вот пример того, как это могло бы работать:

  function dynamicallyLoadScript (url) {   var script = document.createElement( "script" );//Создание узла DOM скрипта   script.src= url;//Устанавливаем src в предоставленный URL
   document.head.appendChild(сценарий);//Добавьте его в конец раздела главы страницы (можно изменить 'head' на 'body', чтобы добавить его в конец секции body)
}
Код>

Эта функция добавит новый тег <script> в конец раздела главы страницы, где для атрибута src установлен URL-адрес, который указан к функции в качестве первого параметра.

Оба этих решения обсуждаются и проиллюстрированы в Безумие JavaScript: загрузка динамического скрипта.

Обнаружение при выполнении сценария

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

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

Например: my_lovely_script.js содержит MySuperObject:

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

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

document.body.appendChild(JS);

var s = new MySuperObject();

Ошибка: MySuperObject не определен
Код>

Затем вы перезагрузите страницу, нажав F5. И это работает! Смешение...

Итак, что с этим делать?

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

  функция loadScript (url, callback)
{   // Добавление тега скрипта в голову, как было предложено ранее   var head = document.getElementsByTagName('head') [0];   var script = document.createElement('script');   script.type = 'text/javascript';   script.src= url;
   // Затем привяжите событие к функции обратного вызова.   // Существует несколько событий для совместимости кросс-браузера.   script.onreadystatechange = обратный вызов;   script.onload = обратный вызов;
   // Пожар загрузки   head.appendChild(сценарий);
}
Код>

Затем вы пишете код, который хотите использовать ПОСЛЕ того, как скрипт загружается в лямбда-функцию

  var myPrettyCode = function() {  // Здесь делай, что хочешь
};
Код>

Затем вы запустите все это:

  loadScript ( "my_lovely_script.js", myPrettyCode);
Код>

Обратите внимание, что сценарий может выполняться после загрузки DOM или раньше, в зависимости от браузера, и включил ли строка script.async = false;. Существует отличная статья о загрузке JavaScript в целом, в которой говорится об этом.

Слияние/предварительная обработка исходного кода

Как упоминалось в начале этого ответа, многие разработчики теперь используют в своих проектах инструменты (средства) для создания/транспиляции, такие как WebPack, Babel или Gulp, позволяя им лучше использовать новые модули синтаксиса и поддержки, объединять файлы, и др.

3610
ответ дан e-satis 04 июня '09 в 15:13
источник поделиться

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

Вы можете написать свои файлы 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
});

реализация .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, а также более определенные модули. Он оптимизирован для использования в браузере, в том числе в Интернете Worker, но он может использоваться в других средах JavaScript, например Rhino и Node. Он реализует API асинхронного модуля.

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

...

515
ответ дан John Strickler 07 июня '12 в 23:55
источник поделиться

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

Вам нужно использовать jQuery.append() в элементе <head> вашей страницы, то есть:

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

Однако этот метод также имеет проблему: если в импортированном файле JavaScript произошла ошибка, Firebug (а также Firefox Error Console и инструменты разработчика Chrome) также сообщают о своем месте неправильно, что является большой проблемой, если вы используете Firebug для отслеживания Ошибок JavaScript много (я). По какой-то причине Firebug просто не знает о недавно загруженном файле, поэтому, если в этом файле произошла ошибка, он сообщает, что он произошел в вашем основном HTML- файле, и у вас возникнут проблемы с поиском истинной причины ошибки.

Но если это не проблема для вас, тогда этот метод должен работать.

Я на самом деле написал плагин jQuery с именем $.import_js(), который использует этот метод:

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

Итак, все, что вам нужно будет сделать для импорта JavaScript:

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

Я также сделал простой пример этого примера.

Он включает файл main.js в основном HTML, а затем скрипт в main.js использует $.import_js() для импорта дополнительного файла с именем included.js, который определяет эту функцию:

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

И сразу после включения included.js вызывается функция hello(), и вы получаете предупреждение.

(Этот ответ отвечает на комментарий e-satis).

162
ответ дан Kipras 28 апр. '11 в 18:25
источник поделиться

Другой способ, который, на мой взгляд, намного чище, заключается в том, чтобы сделать синхронный запрос 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");

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

subscript.doSomethingCool(); 
133
ответ дан Ariel 08 сент. '11 в 21:22
источник поделиться

Для вас есть хорошая новость. Очень скоро вы сможете легко загрузить код JavaScript. Он станет стандартным способом импорта модулей кода JavaScript и будет частью самого основного JavaScript.

Вам просто нужно написать import cond from 'cond.js'; для загрузки макроса с именем cond из файла cond.js.

Таким образом, вам не нужно полагаться на какие-либо рамки JavaScript, и вы не должны явно делать вызовы Ajax.

Обратитесь к:

86
ответ дан Imdad 03 июля '12 в 16:32
источник поделиться

Возможно динамическое создание тега 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");
73
ответ дан Svitlana Maksymchuk 04 июня '09 в 15:02
источник поделиться

Заявление import находится в ECMAScript 6.

Синтаксис

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
ответ дан draupnie 17 апр. '15 в 4:56
источник поделиться

Возможно, вы можете использовать эту функцию, которую я нашел на этой странице Как включить файл 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)
}
48
ответ дан Arnaud Gouder de Beauregard 04 июня '09 в 15:04
источник поделиться

Вот синхронная версия без 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);
}

Обратите внимание, что для получения этой рабочей кросс-домена серверу необходимо будет установить заголовок allow-origin в ответ.

46
ответ дан heinob 11 дек. '13 в 14:54
источник поделиться

Я просто написал этот код 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.

40
ответ дан nornagon 23 янв. '10 в 8:20
источник поделиться

Здесь обобщенная версия того, как Facebook делает это для своей вездесущей кнопки Like:

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

Если он работает в Facebook, он будет работать для вас.

Причина, по которой мы ищем первый script элемент вместо head или body, - это то, что некоторые браузеры не создают, если они отсутствуют, но мы гарантированно имеем элемент script - это один. Подробнее читайте на http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/.

33
ответ дан Dan Dascalescu 08 июля '15 в 5:41
источник поделиться

Это, пожалуй, самая большая слабость JavaScript. Это не вызвало у меня никаких проблем на протяжении многих лет с отслеживанием зависимостей. Во всяком случае, похоже, что единственное практическое решение заключается в использовании script в HTML файле и, таким образом, ужасно делает ваш JavaScript-код зависимым от пользователя, включая источник, который вам нужен, и повторное использование недружелюбного.

Извините, если это встречается как лекция;) Это (плохая) привычка, но я хочу это сделать.

Проблема возвращается к тому же, что и все остальное с помощью Интернета, история JavaScript. Он действительно не был предназначен для использования в широко распространенном виде, который он использовал сегодня. Netscape сделал язык, который позволил бы вам контролировать несколько вещей, но они не предполагали его широкого использования для многих вещей, как это теперь по той или иной причине она расширяется оттуда, не затрагивая некоторые основные недостатки исходной стратегии.

Это, конечно, не одно. HTML не был разработан для современной веб-страницы; он был разработан, чтобы быть способом выражения логики документа, чтобы читатели (браузеры в современном мире) могли отображать это в применимой форме, которая была в пределах возможностей системы, и потребовались годы для решения (другое чем хаки MS и Netscape). CSS решает эту проблему, но это было долгое время и еще больше, чтобы заставить людей использовать его, а не установленные методы BAD. Это произошло, хотя хвалу.

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

30
ответ дан Stephen Whipp 24 мая '12 в 12:51
источник поделиться

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

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

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

$.getScript("another_script.js");
29
ответ дан Venu immadi 13 нояб. '13 в 12:18
источник поделиться

Большинство приведенных здесь решений подразумевают динамическую загрузку. Я искал вместо этого компилятор, который собирал все зависящие файлы в один выходной файл. То же, что и Less/Sass, препроцессоры имеют дело с приложением CSS @import. Поскольку я не нашел ничего подходящего в этом роде, я написал простой инструмент для решения проблемы.

Итак, вот компилятор https://github.com/dsheiko/jsic, который надежно заменяет содержимое $import("file-path") запрошенным файлом. Вот соответствующий Grunt плагин: https://github.com/dsheiko/grunt-jsic.

В ветки мастера jQuery они просто объединяют исходные файлы атома в один, начиная с intro.js и заканчивая на outtro.js. Это меня не устраивает, поскольку он не обеспечивает гибкости при разработке исходного кода. Посмотрите, как это работает с jsic:

ЦСИ/main.js

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

ЦСИ/Форма/вход/Tel.js

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

Теперь мы можем запустить компилятор:

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

И получите объединенный файл

Build/main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};
23
ответ дан Dmitry Sheiko 14 июля '13 в 0:44
источник поделиться

Вы также можете собрать свои сценарии, используя 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
23
ответ дан Calmarius 28 дек. '11 в 0:03
источник поделиться

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

xhr = new XMLHttpRequest();
xhr.open("GET", "/soap/ajax/11.0/connection.js", false);
xhr.send();
eval(xhr.responseText);
18
ответ дан tggagne 24 марта '13 в 22:32
источник поделиться

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

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

Вам просто нужно быть осторожным, когда вы включаете скрипты в файл HTML. Порядок должен быть следующим:

<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>
18
ответ дан Adem İlhan 24 июля '15 в 9:53
источник поделиться

Или вместо включения во время выполнения используйте script для конкатенации перед загрузкой.

Я использую Sprockets (я не знаю, есть ли другие). Вы создаете свой код JavaScript в отдельных файлах и включаете комментарии, которые обрабатываются движком Sprockets, в том числе. Для разработки вы можете включать файлы последовательно, затем для их слияния...

См. также:

16
ответ дан JMawer 07 июня '12 в 23:48
источник поделиться

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

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

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

13
ответ дан Turnerj 01 янв. '15 в 11:58
источник поделиться

У меня была простая проблема, но я был озадачен ответами на этот вопрос.

Мне пришлось использовать переменную (myVar1), определенную в одном файле JavaScript (myvariables.js) в другом файле JavaScript (main.js).

Для этого я сделал следующее:

Загрузите код JavaScript в файл HTML в правильном порядке, сначала myvariables.js, затем main.js:

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

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

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

Файл: myvariables.js

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

Файл: main.js

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

Как вы видели, я использовал переменную в одном файле JavaScript в другом файле JavaScript, но мне не нужно было включать ее в другую. Мне просто нужно было убедиться, что первый файл JavaScript загружен перед вторым файлом JavaScript, и первые переменные файла JavaScript доступны во втором файле JavaScript автоматически.

Это спасло мой день. Надеюсь, это поможет.

11
ответ дан Manohar Reddy Poreddy 22 июля '15 в 5:15
источник поделиться

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

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

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

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

 //scripts-global.mix.js
// Плагины - глобальные

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

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

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

UPDATE: Mixture теперь бесплатно (offline).

ОБНОВЛЕНИЕ. Смесь теперь прекращена. Старые релизы смеси все еще доступны

11
ответ дан Isaac Gregson 14 марта '14 в 7:40
источник поделиться

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

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 (один из других ответов), но, похоже, он не работает так хорошо для меня.

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

10
ответ дан Christopher Dumas 31 мая '13 в 22:31
источник поделиться

Я написал простой модуль, который автоматизирует работу по импорту/включая скрипты модулей в JavaScript. Подробное объяснение кода см. В сообщении блога 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
ответ дан stamat 12 апр. '13 в 19:34
источник поделиться
var js = document.createElement("script");

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

document.body.appendChild(js);
9
ответ дан Sam4Code 22 авг. '12 в 7:33
источник поделиться

В современном языке было бы

function loadJs( url ){
  return new Promise( resolve => {
    const script = document.createElement( "script" );
    script.src = url;
    script.onload = resolve;
    document.head.appendChild( script );
  });
}
8
ответ дан Dmitry Sheiko 20 июля '17 в 18:15
источник поделиться

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

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

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

8
ответ дан Ale 22 нояб. '13 в 21:40
источник поделиться

Я пришел к этому вопросу, потому что я искал простой способ поддерживать набор полезных плагинов JavaScript. Посмотрев некоторые из решений здесь, я придумал следующее:

  • Настройте файл с именем "plugins.js" (или extensions.js или что у вас есть). Храните файлы плагинов вместе с одним основным файлом.

  • plugins.js будет иметь массив под названием "pluginNames []", который мы будем перебирать по каждому(), затем добавьте тег в голову для каждого плагина

    //установить массив для обновления при добавлении или удалении файлов плагинов  var pluginNames = [ "надпись", "fittext", "butterjam" и т.д.]; // один тег script для каждого плагина  $.each(pluginNames, function() {  $ ( 'Голова') добавить ( '');  });

  • вручную вызовите только один файл в вашей голове:
    < script src= "js/plugins/plugins.js" > </script>

Я обнаружил, что, несмотря на то, что все плагины попадают в заголовок так, как им следовало бы, они не всегда запускались браузером при нажатии на страницу или обновлении.

Я нашел, что более надежно просто писать теги script в PHP include. Вам нужно только написать один раз, и это так же много работает, как вызвать плагин с помощью JavaScript.

8
ответ дан rgb_life 01 дек. '11 в 8:36
источник поделиться

Этот script добавит файл JavaScript в начало любого другого тега <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
ответ дан Vicky Gonsalves 26 окт. '13 в 6:42
источник поделиться

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

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

Пример:

file3.js

  var f3obj = "file3" ;

// Определить другие вещи
Код>

file2.js:

  var f2obj = "file2" ;
$.getScript( "file3.js", function() {
   оповещения (f3obj);
   // Используйте все, что определено в файле3.
});
Код>

file1.js:

  $. getScript ( "file2.js", function() {   оповещения (f3obj);//Это, вероятно, будет неудачно, потому что файл3 только гарантированно загружен внутри обратного вызова в файле2.   оповещения (f2obj);
   // Используйте все, что определено в загруженном скрипте...
});
Код>

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

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

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

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

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

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

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

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

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

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

Решение:

<Предварительно > <код > $. Простираться (правда, {   import_js: function (scriptpath, reAddLast)   {       if (typeof reAddLast === "undefined" || reAddLast === null)       {           reAddLast = true;//По умолчанию это значение равно true. Он не используется конечным пользователем, только для правильной рекурсии.       }       var found = false;       if (reAddLast == true)//Если мы повторно добавляем исходный script, нам все равно, если он уже был добавлен.       {           found = $('script'). filter (function() {               return ($ (this).attr('src') == scriptpath);           }). length!= 0;//jQuery, чтобы проверить, существует ли script. (замените его прямым JavaScript, если вам не нравится jQuery.       }       if (found == false) {           var callScriptPath = $('script'). last(). attr ( "src" );//Получаем script, который в настоящее время загружается. Опять же, это создает ограничение, когда это не должно использоваться в кнопке и только до document.ready.           document.writeln( "< script type = 'text/javascript' src= '" + scriptpath + "' > </script/gt;" );//Добавьте script в документ с помощью writeln           if (reAddLast)           {               $.import_js (callScriptPath, false);//Вызовите себя с исходным script, чтобы исправить порядок.               throw 'Readding script, чтобы исправить порядок:' + scriptpath + '< '+ callScriptPath;//Это останавливает выполнение исходной script, поскольку она перезагружается. Если вы поставили try/catch на вызов $.import_js, результаты будут разными.           }           return true;       }       return false;   } }); Код >

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

file3:

  var f3obj = "file3" ;

// Определить другие вещи
$ (Функция() {   f3obj =  "file3docready";
});
Код>

File2:

<Предварительно > <код > $import_js ( 'JS/file3.js'). var f2obj = "file2" ; $ (Функция() {   f2obj = "file2docready"; }); Код >

File1:

<Предварительно > <код > $import_js ( 'JS/file2.js'). // Использовать объекты из file2 или file3 оповещения (f3obj);// "file3" оповещения (f2obj);// "file2" $ (Функция() {   // Использовать объекты из file2 или file3 еще немного.   оповещения (f3obj);// "file3docready"   оповещения (f2obj);// "file2docready" }); Код >
8
ответ дан curlyhairedgenius 11 янв. '15 в 23:19
источник поделиться

Я создал функцию, которая позволит вам использовать аналогичную формулировку для С#/Java для включения файла JavaScript. Я тестировал его немного даже изнутри другого файла JavaScript и, похоже, работает. Это требует jQuery, хотя для немного "магии" в конце.

Я помещаю этот код в файл в корень моего каталога script (я назвал его global.js, но вы можете использовать все, что захотите. Если я не ошибаюсь, это и jQuery должны быть единственными необходимыми скриптами на на данной странице. Имейте в виду, что это в значительной степени непроверено за пределами некоторого базового использования, поэтому могут быть или не быть какие-либо проблемы с тем, как я это сделал, использовать на свой страх и риск yadda yadda Я не несу ответственности, 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, ",$1").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
ответ дан Wayne Molina 20 янв. '12 в 0:27
источник поделиться
  • 1
  • 2

Другие вопросы по меткам