file import用法 - 如何在另一個JavaScript文件中包含JavaScript文件?




js link (25)

如果您正在使用Web Workers並希望在worker的範圍內包含其他腳本,則提供有關向head標記添加腳本等的其他答案將不適合您。

幸運的是, Web Workers有自己的importScripts函數 ,它是Web Worker範圍內的全局函數,是瀏覽器本身的本機函數,因為它是規範的一部分

或者,作為對您的問題的第二高投票答案,RequireJS還可以處理包含Web Worker中的腳本(可能稱之為importScripts自己,但具有一些其他有用的功能)。

在JavaScript中是否有類似於@import的內容,允許您在另一個JavaScript文件中包含JavaScript文件?


如果您想要純JavaScript,可以使用document.write

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

如果使用jQuery庫,則可以使用$.getScript方法。

$.getScript("another_script.js");

這應該做:

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

此腳本將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);
})();

這是沒有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標頭。


另一種方式,在我看來更清晰,是製作同步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);
        }
    });
}

然後,您可以在代碼中使用它,因為您通常使用包含:

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

並且能夠在下一行中從所需腳本調用函數:

subscript.doSomethingCool(); 

或者不是在運行時包括在上載之前使用腳本連接。

我使用Sprockets (我不知道是否還有其他Sprockets )。 您可以在單獨的文件中構建JavaScript代碼,並包含由Sprockets引擎作為包含處理的註釋。 對於開發,您可以按順序包含文件,然後生產以合併它們...

也可以看看:


可以動態生成JavaScript標記,並將其從其他JavaScript代碼中添加到HTML文檔中。 這將加載有針對性的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");

您還可以使用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

用現代語言來說就是這樣

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

我通常的方法是:

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方法(其他一個答案),但它似乎對我來說效果不佳。

下面解釋了代碼如何為那些好奇的人工作:基本上,它創建了一個新的腳本標記(在第一個之後)。它將其設置為異步模式,因此它不會阻止其餘代碼,但在readyState(要加載的內容的狀態)更改為“已加載”時調用回調。


我創建了一個函數,允許您使用與C#/ Java類似的措辭來包含JavaScript文件。我甚至從另一個 JavaScript文件內部測試了一下它似乎工作。它確實需要jQuery,但最後需要一些“魔術”。

我把這段代碼放在腳本目錄根目錄下的文件中(我把它命名為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);
}

舊版本的JavaScript沒有導入,包含或要求,因此開發了許多不同的方法來解決這個問題。

但自2015年(ES6)以來,JavaScript已經有了ES6模塊標準來導入Node.js中的模塊, 大多數現代瀏覽器也支持這種模塊。

為了與舊版瀏覽器兼容,可以使用build和/或transpilation工具。

ES6模塊

自v8.5起,Node.js支持ECMAScript(ES6)模塊,帶有--experimental-modules標誌。 涉及的所有文件必須具有.mjs擴展名。

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

瀏覽器中的ECMAScript模塊

since Safari 10.1,Chrome 61,Firefox 60和Edge 16 since ,瀏覽器已經支持直接加載ECMAScript模塊(不需要像Webpack這樣的工具)。檢查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);
}

欲了解更多信息, since訪問: sincesince

瀏覽器中的動態導入

動態導入允許腳本根據需要加載其他腳本:

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

欲了解更多信息, https://developers.google.com/web/updates/2017/11/dynamic-import訪問: https://developers.google.com/web/updates/2017/11/dynamic-importhttps://developers.google.com/web/updates/2017/11/dynamic-import

Node.js需要

仍然在Node.js中廣泛使用的舊模式導入模塊是module.exports/require系統。

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

JavaScript還有其他方法可以在不需要預處理的瀏覽器中包含外部JavaScript內容。

AJAX加載

您可以使用AJAX調用加載其他腳本,然後使用eval運行它。 這是最簡單的方法,但由於JavaScript沙箱安全模型,它僅限於您的域。 使用eval還可以打開錯誤,黑客和安全問題的大門。

jQuery加載

jQuery在一行中提供加載功能:

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

動態腳本加載

您可以將帶有腳本URL的腳本標記添加到HTML中。 為了避免jQuery的開銷,這是一個理想的解決方案。

該腳本甚至可以駐留在不同的服務器上。 此外,瀏覽器評估代碼。 <script>標記可以注入網頁<head> ,也可以在結束</body>標記之前插入。

以下是一個如何工作的示例:

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

此函數將新的<script>標記添加到頁面的head部分的末尾,其中src屬性設置為作為第一個參數賦予函數的URL。

這些解決方案都在JavaScript瘋狂:動態腳本加載中進行了討論和說明。

檢測腳本何時執行

現在,您必須了解一個大問題。 這樣做意味著您遠程加載代碼 。 現代Web瀏覽器將加載文件並繼續執行當前腳本,因為它們異步加載所有內容以提高性能。 (這適用於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();

Error : MySuperObject is undefined

然後你重新加載頁面擊中F5 。 它的工作原理! 混亂...

那該怎麼辦呢?

好吧,你可以在我給你的鏈接中使用作者建議的黑客。 總之,對於匆忙的人,他在加載腳本時使用事件來運行回調函數。 因此,您可以使用遠程庫將所有代碼放在回調函數中。 例如:

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

然後在lambda函數中加載腳本後編寫要使用的代碼:

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

然後你運行所有:

loadScript("my_lovely_script.js", myPrettyCode);

請注意,腳本可以在DOM加載之後或之前執行,具體取決於瀏覽器以及是否包含行script.async = false; 。 有一篇關於Javascript加載的文章 ,討論了這個問題。

源代碼合併/預處理

如本答案的頂部所述,許多開發人員在他們的項目中使用像Parcel,Webpack或Babel這樣的構建/轉換工具,允許他們使用即將推出的JavaScript語法,為舊瀏覽器提供向後兼容性,組合文件,縮小,執行代碼拆分等


也許您可以使用我在此頁面上找到的此功能如何在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中導入/包含模塊腳本的工作。有關代碼的詳細說明,請參閱博客文章JavaScript require / import / include模塊

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

有一個好消息要告訴你。 很快您就可以輕鬆加載JavaScript代碼了。 它將成為導入JavaScript代碼模塊的標準方式,並將成為核心JavaScript本身的一部分。

你只需import cond from 'cond.js';寫下import cond from 'cond.js'; 從文件cond.js加載名為cond的宏。

因此,您不必依賴任何JavaScript框架,也不必顯式地進行Ajax調用。

參考:


我剛寫了這個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>

要點: http://gist.github.com/284442http://gist.github.com/284442


這裡顯示的大多數解決方案都意味著動態加載。 我正在搜索一個編譯器,它將所有依賴的文件組合成一個輸出文件。 與Less / Sass預處理器相同,處理CSS @import at-rule。 由於我沒有找到這種類似的東西,我寫了一個簡單的工具來解決這個問題。

所以這裡是編譯器, https://github.com/dsheiko/jsic ,它可以安全地用所需的文件內容替換$import("file-path") 。 這是相應的Grunt插件: https://github.com/dsheiko/grunt-jsichttps://github.com/dsheiko/grunt-jsic

在jQuery master分支上,他們只是簡單地將原子源文件連接成一個以intro.js並以outtro.js結尾的outtro.js 。 這不適合我,因為它沒有提供源代碼設計的靈活性。 看看它如何與jsic一起使用:

SRC / main.js

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

SRC /表格/輸入/ Tel.js

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

現在我們可以運行編譯器了:

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

並獲得組合文件

建立/ main.js

var foo = function() {
    return {
          prop: "",
          method: function(){}
    }
};

更好地使用jQuery方式。要延遲就緒事件,請先撥打電話$.holdReady(true)。示例(source):

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

如果有人想要更高級的東西,請嘗試RequireJS 。 您將獲得額外的好處,例如依賴關係管理,更好的並發性,並避免重複(即,多次檢索腳本)。

您可以在“模塊”中編寫JavaScript文件,然後在其他腳本中將它們作為依賴項引用。 或者您可以將RequireJS用作簡單的“go 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是依賴some-dependency.js的 “主”JavaScript文件

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

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

摘自GitHub自述文件:

RequireJS加載純JavaScript文件以及更多已定義的模塊。 它針對瀏覽器內使用進行了優化,包括在Web Worker中,但它可以在其他JavaScript環境中使用,如Rhino和Node。 它實現了異步模塊API。

RequireJS使用普通腳本標記來加載模塊/文件,因此它應該允許輕鬆調試。 它可以簡單地用於加載現有的JavaScript文件,因此您可以將其添加到現有項目中,而無需重新編寫JavaScript文件。

...


語句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;

@import實現CSS-像JavaScript語法進口可能使用的工具,如通過其特殊的混合.mix文件類型(見here)。我想應用程序只是在內部使用上述方法之一,但我不知道。

從文件的混合文檔.mix

混合文件只是帶有.mix的.js或.css文件。在文件名中。混合文件只是擴展了普通樣式或腳本文件的功能,並允許您導入和組合。

這是一個.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";

Mixture將此輸出為scripts-global.js縮小版本(scripts-global.min.js)。

注意:除了將它用作前端開發工具之外,我與Mixture無任何關聯。我看到一個.mixJavaScript文件在運行中(在其中一個Mixture樣板中)並且有點混淆(“你能做到嗎?”我想到了這個問題。然後我意識到這是一個特定於應用程序的文件類型(有點令人失望,同意)。然而,認為這些知識可能對其他人有所幫助。

更新:混合物現在免費的(離線)。

更新:混合物現已停產。舊的混合物發布仍然可用


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

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

document.body.appendChild(js);

還有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方法一樣方便。它還具有一些高級功能,如條件加載,功能檢測等等


Underscore.js可用於解決多個瀏覽器的問題。 它使用內置瀏覽器方法(如果存在)。 如果它們不存在,就像舊的Internet Explorer版本一樣,它使用自己的自定義方法。

從數組中刪除元素的簡單示例(來自網站):

_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); // => [2, 3, 4]




javascript file import include