如何在另一个JavaScript文件中包含JavaScript文件?

时间:2009-06-04 11:59:51

标签: javascript file import include

CSS中是否存在与@import类似的内容,允许您在另一个JavaScript文件中包含JavaScript文件?

64 个答案:

答案 0 :(得分:4025)

旧版本的JavaScript没有导入,包含或要求,因此已经开发了许多不同的方法来解决这个问题。

但自2015年(ES6)以来,JavaScript已经有ES6 modules标准来导入Node.js中的模块,most modern browsers也支持这些模块。

为了与旧版浏览器兼容,可以使用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模块

浏览器已经支持直接加载ECMAScript模块(不需要像Webpack这样的工具)since Safari 10.1,Chrome 61,Firefox 60和Edge 16.检查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);
}

https://jakearchibald.com/2017/es-modules-in-browsers/

了解详情

浏览器中的动态导入

动态导入允许脚本根据需要加载其他脚本:

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

https://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也可以打开错误,黑客和安全问题的大门。

获取加载

与动态导入类似,您可以使用promises加载一个或多个脚本,并使用Fetch Inject库来控制脚本依赖项的执行顺序:

fetch

jQuery加载

jQuery库提供加载功能in one line

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})

动态脚本加载

您可以将带有脚本URL的脚本标记添加到HTML中。为了避免jQuery的开销,这是一个理想的解决方案。

该脚本甚至可以驻留在不同的服务器上。此外,浏览器评估代码。 $.getScript("my_lovely_script.js", function() { alert("Script loaded but not necessarily executed."); }); 代码可以注入网页<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>属性设置为作为第一个参数赋予函数的URL。

JavaScript Madness: Dynamic Script Loading中讨论并说明了这两种解决方案。

检测脚本何时执行

现在,您必须了解一个大问题。这样做意味着您远程加载代码。现代Web浏览器将加载文件并继续执行当前脚本,因为它们异步加载所有内容以提高性能。 (这适用于jQuery方法和手动动态脚本加载方法。)

这意味着如果您直接使用这些技巧,在您要求加载后,您将无法在下一行使用新加载的代码,因为它仍将加载。

例如:src包含my_lovely_script.js

MySuperObject

然后你重新加载点击 F5 的页面。它的工作原理!混乱...

那该怎么办呢?

好吧,你可以在我给你的链接中使用作者建议的黑客。总之,对于匆忙的人,他在加载脚本时使用事件来运行回调函数。因此,您可以使用远程库将所有代码放在回调函数中。例如:

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

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

document.body.appendChild(js);

var s = new MySuperObject();

Error : MySuperObject is undefined

然后在lambda function加载脚本后编写要使用的代码:

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

然后你运行所有:

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

请注意,脚本可能在DOM加载之后或之前执行,具体取决于浏览器以及是否包含行loadScript("my_lovely_script.js", myPrettyCode); 。有一个great article on Javascript loading in general讨论了这一点。

源代码合并/预处理

正如本答案的顶部所述,许多开发人员在他们的项目中使用像Parcel,Webpack或Babel这样的构建/转换工具,允许他们使用即将推出的JavaScript语法,为旧版浏览器提供向后兼容性,组合文件,缩小,执行代码分割等。

答案 1 :(得分:540)

如果有人想要更高级的东西,请试试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 是您的“主要”JavaScript文件,依赖于 some-dependency.js

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

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

摘自GitHub自述文件:

  

RequireJS加载纯JavaScript文件以及更多定义   模块。它针对浏览器内使用进行了优化,包括在Web中   工作者,但它可以在其他JavaScript环境中使用,例如   Rhino和Node。它实现了异步模块API。

     

RequireJS使用普通脚本标签加载模块/文件,因此它应该   允许轻松调试。它可以简单地用于加载现有的   JavaScript文件,因此您可以将其添加到现有项目中   必须重新编写JavaScript文件。

     

...

答案 2 :(得分:176)

实际上一种异步加载JavaScript文件而不是的方法,因此您可以在加载后立即使用新加载的文件中包含的函数,我认为它适用于所有浏览器。

您需要在页面的jQuery.append()元素上使用<head>,即:

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

但是,此方法也存在问题:如果导入的JavaScript文件中发生错误,Firebug(以及Firefox错误控制台和Chrome Developer Tools)也会错误地报告其位置,这是如果您使用Firebug来跟踪JavaScript错误(我这样做),这是一个大问题。由于某种原因,Firebug根本不知道新加载的文件,因此如果该文件中发生错误,它会报告它发生在您的主HTML文件中,并且您将无法找到真正的原因错误。

但如果这对你来说不是问题,那么这种方法应该有用。

我实际上已经编写了一个名为 $ .import_js()的jQuery插件,该插件使用了这种方法:

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

我还在Example进行了一次简单的测试。

它在主HTML中包含main.js文件,然后main.js中的脚本使用$.import_js()导入名为included.js的附加文件,该文件定义了此功能:< / p>

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

在包含included.js之后,调用了hello()函数,您就会收到警报。

(这个答案是对e-satisf'评论的回应)。

答案 3 :(得分:140)

另一种方式,在我看来更清晰,是制作同步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(); 

答案 4 :(得分:90)

有一个好消息要告诉你。很快您就可以轻松加载JavaScript代码了。它将成为导入JavaScript代码模块的标准方式,并将成为核心JavaScript本身的一部分。

您只需编写import cond from 'cond.js';即可从文件cond加载名为cond.js的宏。

因此,您不必依赖任何JavaScript框架,也不必明确进行Ajax次调用。

参考:

答案 5 :(得分:81)

可以动态生成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");

答案 6 :(得分:62)

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

答案 7 :(得分:52)

也许您可以使用我在此页面上找到的此功能 How do I include a JavaScript file in a JavaScript file?

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

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

    head.appendChild(script)
}

答案 8 :(得分:47)

以下是同步没有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标头。

答案 9 :(得分:43)

我刚刚编写了这段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/284442

答案 10 :(得分:37)

以下是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元素而不是headbody的原因是因为某些浏览器在缺少时会创建一个,但我们保证会有script元素 - 这一个。阅读更多http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/

答案 11 :(得分:32)

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

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

如果使用jQuery库,则可以使用$.getScript方法。

$.getScript("another_script.js");

答案 12 :(得分:25)

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

答案 13 :(得分:24)

此处显示的大多数解决方案都意味着动态加载。我正在搜索一个编译器,它将所有依赖的文件组合成一个输出文件。与Less / Sass预处理程序相同,处理CSS @import at-rule。由于我没有找到这种类似的东西,我写了一个简单的工具来解决这个问题。

所以这里是编译器https://github.com/dsheiko/jsic,它可以安全地用{1}}替换所请求的文件内容。以下是相应的Grunt插件:https://github.com/dsheiko/grunt-jsic

在jQuery master分支上,他们只是将原子源文件连接成一个以$import("file-path")开头并以intro.js结尾的文件。这不适合我,因为它没有提供源代码设计的灵活性。看看它如何与jsic一起使用:

的src / main.js

outtro.js

SRC /形式/输入/ Tel.js

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

现在我们可以运行编译器了:

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

获取合并文件

建立/ main.js

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

答案 14 :(得分:20)

如果您打算使用导入/包含文件中的函数加载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>

答案 15 :(得分:18)

这应该做:

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

答案 16 :(得分:17)

或者不是在运行时包含,而是在上传之前使用脚本进行连接。

我使用Sprockets(我不知道是否还有其他人)。您可以在单独的文件中构建JavaScript代码,并包含由Sprockets引擎作为包括处理的注释。对于开发,您可以按顺序包含文件,然后生产以合并它们......

另见:

答案 17 :(得分:14)

如果您使用Web Workers并希望在工作人员范围内包含其他脚本,则提供的有关向head标记添加脚本等的其他答案将不适合您。

幸运的是,Web Workers have their own importScripts function是Web Worker范围内的全局函数,它本身就是浏览器本身is part of the specification

或者,as the second highest voted answer to your question highlightsRequireJS也可以处理Web Worker中的脚本(可能会调用importScripts本身,但还有一些其他有用的功能)。

答案 18 :(得分:14)

我有一个简单的问题,但我对这个问题的回答感到困惑。

我不得不在另一个JavaScript文件(main.js)中使用一个JavaScript文件(myvariables.js)中定义的变量(myVar1)。

为此我做了如下:

以正确的顺序加载HTML文件中的JavaScript代码,首先是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文件的变量可以在第二个JavaScript文件中自动访问。

这节省了我的一天。我希望这会有所帮助。

答案 19 :(得分:12)

使用Mixture等工具通过其特殊@import文件类型(参见here),可以实现.mix语法,以实现类似CSS的JavaScript导入。我想应用程序只是在内部使用上述方法之一,但我不知道。

来自.mix文件的混合文档:

  

混合文件只是带有.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文件在运行中(在其中一个混合物样板中)并且被它弄得有点困惑(&#34;你可以这样做?&#34;我想到了自己)时遇到了这个问题)。然后我意识到这是一个特定于应用程序的文件类型(有点令人失望,同意)。然而,认为这些知识可能对其他人有所帮助。

更新:混合为now free(离线)。

更新:混合物现已停止使用。 Old mixture releases仍可用

答案 20 :(得分:11)

我编写了一个简单的模块,可以自动执行在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);
};

答案 21 :(得分:11)

我通常的方法是:

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(要加载的内容的状态)更改为“已加载”时调用回调。

答案 22 :(得分:11)

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

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

document.body.appendChild(js);

答案 23 :(得分:10)

在现代语言中它将是

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

答案 24 :(得分:9)

此脚本会将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);
})();

答案 25 :(得分:9)

还有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方法一样方便。它还具有一些高级功能,如条件加载,特征检测和much more

答案 26 :(得分:9)

我遇到了这个问题,因为我正在寻找一种简单的方法来维护一组有用的JavaScript插件。在看到这里的一些解决方案之后,我想出了这个:

  1. 设置一个名为&#34; plugins.js&#34;的文件。 (或extensions.js或你有什么)。将您的插件文件与一个主文件保持在一起。

  2. plugins.js将有一个名为&#34; pluginNames []&#34;的数组。我们将遍历每个(), 然后在每个插件的头部附加一个标签

    //在我们添加或删除插件文件时设置要更新的数组  var pluginNames = [&#34;刻字&#34;,&#34; fittext&#34;,&#34; butterjam&#34;等等]; //每个插件的一个脚本标记  $ .each(pluginNames,function(){    $(&#39;头&#39;)。追加(&#39;&#39;);  });

  3. 手动调用你头脑中的一个文件:
    <script src="js/plugins/plugins.js"></script>

  4. 我发现即使所有的插件都按照他们应该的方式被放入头标签,但当你点击页面或刷新时,他们并不总是被浏览器运行。

    我发现在PHP包中编写脚本标记更加可靠。您只需编写一次,这与使用JavaScript调用插件一样多。

答案 27 :(得分:8)

这个问题有很多潜在的答案。我的回答显然基于其中的一些。这是我在阅读完所有答案后最终得到的结果。

$.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来检查延迟对象数组,但现在您在每个文件中执行此操作,并且只要$.when执行时,file2将被视为已加载执行回调,因此file1在加载file3之前仍然继续执行。这仍然有同样的问题。

我决定倒退而不是前锋。谢谢document.writeln。我知道这是禁忌,但只要使用得当,这种方法效果很好。您最终得到的代码可以轻松调试,正确显示在DOM中,并且可以确保正确加载依赖项的顺序。

你当然可以使用$(&#34; body&#34;)。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;
    }
});

用法:

文件3:

var f3obj = "file3";

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

文件2:

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

答案 28 :(得分:7)

虽然这些答案很棒,但是有一个简单的“解决方案”,因为脚本加载已存在,它将覆盖大多数人的99.999%的用例。只需在需要它的脚本之前包含所需的脚本。对于大多数项目来说,确定需要哪些脚本以及按什么顺序确定需要很长时间。

<!DOCTYPE HTML>
<html>
    <head>
        <script src="script1.js"></script>
        <script src="script2.js"></script>
    </head>
    <body></body>
</html>

如果script2需要script1,这确实是做这样的事情的绝对最简单的方法。我很惊讶没有人提出这个问题,因为这是几乎每一个案例中最明显和最简单的答案。

答案 29 :(得分:7)

我创建了一个函数,允许您使用与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);
}

答案 30 :(得分:6)

我基本上像下面这样做,创建一个新元素并将其附加到头部:

var x = document.createElement('script');
x.src = 'http://example.com/test.js';
document.getElementsByTagName("head")[0].appendChild(x);

jQuery中:

// jQuery
$.getScript('/path/to/imported/script.js', function()
{
    // Script is now loaded and executed.
    // Put your dependent JavaScript code here.
});

答案 31 :(得分:6)

以下是使用HTML导入的 for browsers (非Node.js)的解决方法。

首先,所有JavaScript类和脚本都不在.js个文件中,但在.js.html个文件中( .js html只是为了识别HTML页面和完整的JavaScript脚本/类),在<script>标记内,如下所示:

MyClass.js.html

<script>
   class MyClass {

      // Your code here..

   }

</script>

然后,如果您想导入您的类,您只需要使用HTML导入:

<link rel="import" href="relative/path/to/MyClass.js.html"/>

<script>
   var myClass = new MyClass();
   // Your code here..
</script>

编辑:HTML导入将被删除

HTML导入和ES6模块are both already well implemented in most browser accross the world,因为HTML导入绝对不会成为标准的一部分,与ES6模块不同,它的开发将被删除,那么你应该明确地开始使用ES6模块。

答案 32 :(得分:6)

有几种方法可以用Javascript实现模块,以下是两种最受欢迎​​的方法:

ES6模块

浏览器尚不支持此调制系统,因此,要使您使用此语法,必须使用像webpack这样的捆绑器。无论如何,使用捆绑器会更好,因为这可以将所有不同的文件合并为一个(或几个相关的)文件。这将更快地将文件从服务器传送到客户端,因为每个HTTP请求都伴随有一些相关的开销。因此,通过减少总体HTTP请求,我们可以提高性能。这是ES6模块的示例:

// main.js file

export function add (a, b) {
  return a + b;
}

export default function multiply (a, b) {
  return a * b;
}


// test.js file

import {add}, multiply from './main';   // for named exports between curly braces {export1, export2}
                                        // for default exports without {}

console.log(multiply(2, 2));  // logs 4

console.log(add(1, 2));  // logs 3

CommonJS (在NodeJS中使用)

此调制系统在NodeJS中使用。基本上,您将导出添加到名为module.exports的对象中。然后,您可以通过require('modulePath')访问该对象。在这里重要的是要意识到这些模块已被缓存,因此,如果您两次require()某个模块两次,它将返回已经创建的模块。

// main.js file

function add (a, b) {
  return a + b;
}

module.exports = add;  // here we add our add function to the exports object


// test.js file

const add = require('./main'); 

console.log(add(1,2));  // logs 3

答案 33 :(得分:6)

保持简洁,简洁,易于维护! :

// 3rd party plugins / script (don't forget the full path is necessary)
var FULL_PATH = '', s =
[
    FULL_PATH + 'plugins/script.js'      // Script example
    FULL_PATH + 'plugins/jquery.1.2.js', // jQuery Library 
    FULL_PATH + 'plugins/crypto-js/hmac-sha1.js',      // CryptoJS
    FULL_PATH + 'plugins/crypto-js/enc-base64-min.js'  // CryptoJS
];

function load(url)
{
    var ajax = new XMLHttpRequest();
    ajax.open('GET', url, false);
    ajax.onreadystatechange = function ()
    {
        var script = ajax.response || ajax.responseText;
        if (ajax.readyState === 4)
        {
            switch(ajax.status)
            {
                case 200:
                    eval.apply( window, [script] );
                    console.log("library loaded: ", url);
                    break;
                default:
                    console.log("ERROR: library not loaded: ", url);
            }
        }
    };
    ajax.send(null);
}

 // initialize a single load 
load('plugins/script.js');

// initialize a full load of scripts
if (s.length > 0)
{
    for (i = 0; i < s.length; i++)
    {
        load(s[i]);
    }
}

此代码只是一个简短的功能示例,可能需要其他功能,以便在任何(或给定)平台上提供全面支持。

答案 34 :(得分:6)

这是一个Grunt插件,允许您在包含JavaScript文件的任何文件中使用@import "path/to/file.js";语法。它可以与uglify或手表或任何其他插件配对。

可以使用npm install:https://npmjs.org/package/grunt-import

进行安装

答案 35 :(得分:6)

更好地使用jQuery方式。要延迟就绪事件,请先致电$.holdReady(true)。 示例(source):

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

答案 36 :(得分:5)

仅适用于NodeJS,这对我来说是最好的!

我在这里尝试了大多数解决方案,但是在不更改范围的情况下仅加载另一个文件并没有帮助我。最后我用了这个。保留范围和所有内容。这与您的代码一样好。

const fs = require('fs');
eval(fs.readFileSync('file.js')+'');

答案 37 :(得分:4)

这很简单。假设您要在文件B.js中导入文件A.js。

现在确定您已在HTML文件中链接了B.js,然后在该HTML文件中将B.js链接到B.js之前。然后A.js的公共变量将在B.js

中提供

这不需要复杂的答案。

答案 38 :(得分:4)

如果你使用Angular,那么插件模块$ocLazyLoad可以帮助你做到这一点。

以下是其文档中的一些引用:

  

加载一个或多个模块&amp;包含多个文件的组件:

$ocLazyLoad.load(['testModule.js', 'testModuleCtrl.js', 'testModuleService.js']);
     

使用多个文件加载一个或多个模块,并在必要时指定类型:   注意:使用requireJS样式格式(例如,在开头使用js!)时,请勿指定文件扩展名。使用其中一种。

$ocLazyLoad.load([
  'testModule.js',
   {type: 'css', path: 'testModuleCtrl'},
   {type: 'html', path: 'testModuleCtrl.html'},
   {type: 'js', path: 'testModuleCtrl'},
   'js!testModuleService',
   'less!testModuleLessFile'
]);
     

您可以加载外部库(非角度):

$ocLazyLoad.load(['testModule.js', 
   'bower_components/bootstrap/dist/js/bootstrap.js', 'anotherModule.js']);
     

您还可以加载css和模板文件:

 $ocLazyLoad.load([
     'bower_components/bootstrap/dist/js/bootstrap.js',
     'bower_components/bootstrap/dist/css/bootstrap.css',
     'partials/template1.html'
 ]);

答案 39 :(得分:4)

是的,有......

继续阅读,在 ES6 中,我们可以将exportimport部分或整个javascript文件转换为另一个...

但是等等,所有浏览器都不支持 ES6 ,所以您需要的是使用babel.js进行转换...

所以你创建了一个类如下:

class Person {
  constructor(name) {
    this.name = name;
  }

  build() {
    return new Person(this);
  }
}

module.exports = Person;

在另一个JavaScript文件中,执行以下导入:

import { Person } from 'Person';

您还可以要求文件:

const Person = require('./Person');

如果您使用的是较旧的JavaScript版本,则可以使用 requirejs

requirejs(["helper/util"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

如果您想坚持使用旧版本的内容,例如 jQuery ,您还可以使用 getScript 之类的内容:

jQuery.getScript('./another-script.js', function() {
    // Call back after another-script loaded
});

最后但并非最不重要,请不要忘记您可以使用<script>标记将脚本放在一起的传统方式......

<script src="./first-script.js"></script>
<script src="./second-script.js"></script>
<script src="./third-script.js"></script>

还有 async defer 属性,我应该在这里提一下......

  

注意:有多种方法可以执行外部脚本:

     
  • 如果存在异步:脚本以异步方式执行   与页面的其余部分(脚本将在页面执行   继续解析)
  • 如果不存在异步并且延迟是   present:页面完成后执行脚本   解析
  • 如果不存在异步或延迟:脚本是   在浏览器继续之前立即获取并执行   解析页面

答案 40 :(得分:4)

我要求异步加载一系列JavaScript文件,并在最后进行回调。基本上我最好的方法如下:

// Load a JavaScript file from other JavaScript file
function loadScript(urlPack, callback) {
    var url = urlPack.shift();
    var subCallback;

    if (urlPack.length == 0) subCallback = callback;
    else subCallback = function () {
        console.log("Log script: " + new Date().getTime());
        loadScript(urlPack, 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 = subCallback;
    script.onload = subCallback;

    // Fire the loading
    head.appendChild(script);
}

示例:

loadScript(
[
    "js/DataTable/jquery.dataTables.js",
    "js/DataTable/dataTables.bootstrap.js",
    "js/DataTable/dataTables.buttons.min.js",
    "js/DataTable/dataTables.colReorder.min.js",
    "js/DataTable/dataTables.fixedHeader.min.js",
    "js/DataTable/buttons.bootstrap.min.js",
    "js/DataTable/buttons.colVis.min.js",
    "js/DataTable/buttons.html5.min.js"
], function() { gpLoad(params); });

第二个脚本在第一个脚本完全加载之前不会加载,所以......

结果:

Result

答案 41 :(得分:3)

使用与Node.js一起使用的ES6导入和导出模块

扩展名为.mjs而不是.js的文件

创建文件

touch main.mjs lib.mjs

main.js

import { add } from './lib.mjs';
console.log(add(40, 2));

lib.mjs

export let add = (x,y) => {
  return x + y
}

运行

node --experimental-modules main.js

答案 42 :(得分:3)

var s=["Hscript.js","checkRobert.js","Hscript.js"];
for(i=0;i<s.length;i++){
  var script=document.createElement("script");
  script.type="text/javascript";
  script.src=s[i];
  document.getElementsByTagName("head")[0].appendChild(script)
};

答案 43 :(得分:3)

现在,我可能完全被误导了,但这是我最近开始做的...... 使用回车符开始和结束JavaScript文件,放在PHP脚本中,然后再回车一次。 PHP会忽略JavaScript注释“//”,因此无论如何都会包含。回车的目的是使所包含的JavaScript的第一行不被注释掉。

从技术上讲,您不需要评论,但它会在Dreamweaver中发布令我烦恼的错误。如果您在不发布错误的IDE中编写脚本,则不需要注释或回车。

\n
//<?php require_once("path/to/javascript/dependency.js"); ?>

function myFunction(){
    // stuff
}
\n

答案 44 :(得分:3)

不要忘记查看LAB.js

<script type="text/javascript">
       $LAB
       .script("jquery-1.8.3.js").wait()
       .script("scripts/clientscript.js");      
</script>

答案 45 :(得分:3)

在过去的项目中,我使用ajile来导入可重用的JavaScript文件取得了相当大的成功。我一直希望有一个内置于JavaScript本身的功能。

答案 46 :(得分:2)

我用另一种方法尝试了这个问题,

脚本导入的顺序在这里无效。

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Trials</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="main.js"></script>
    <script src="scriptA.js"></script>
</head>

<body>
<h3>testing js in js (check console logs)</h3>
<button onclick="fnClick()">TEST</button>
</body>

</html>

main.js

function fnClick() {
  console.log('From\tAAAAA');
  var pro = myExpo.hello();
  console.log(pro);
}

scriptA.js

myExpo = {
    hello: function () {
        console.log('From\tBBBBB');
        return "Hello";
    }
}

结果

From    AAAAA
From    BBBBB
Hello

答案 47 :(得分:2)

您无法导入,但可以参考。

PhpShtorm IDE。要在一个.js文件中引用另一个.js,只需将其添加到文件顶部:

<reference path="../js/file.js" />

当然,您应该将自己的PATH用于JavaScript文件。

我不知道它是否适用于其他IDE。可能是的,试试吧。它也应该在Visual Studio中工作。

答案 48 :(得分:2)

另一种方法是使用HTML导入。这些可以包含脚本引用以及样式表引用。

您只需链接HTML文件,例如

Imports Microsoft.VisualBasic.PowerPacks

Public Class MDIParent1
    Dim C As New ShapeContainer
    Dim WithEvents R As New RectangleShape

    Private Sub MDIParent1_Load(sender As Object, e As EventArgs) Handles Me.Load

        C.Parent = Me
        R.Parent = C
        R.Top = 0
        R.Left = 0
        Me.Controls.Add(C)

    End Sub

    Private Sub MDIParent1_Resize(sender As Object, e As EventArgs) Handles Me.Resize

        R.Height = Me.Height
        R.Width = Me.Width

    End Sub

    Private Sub R_DoubleClick(sender As Object, e As EventArgs) Handles R.DoubleClick

        MessageBox.Show("Shape Double-click")

    End Sub
...
End Class

<link rel="import" href="vendorScripts.html"/> 文件中,您可以包含脚本引用,例如:

vendorScripts.html

请查看HTML Imports了解更多详情。

不幸的是,这仅适用于Chrome。

答案 49 :(得分:2)

这可能是另一种方式!在Node.js中,您可以像下面这样做! http://requirejs.org/docs/node.html

<强> sub.js

module.exports = {
  log: function(string) {
    if(console) console.log(string);
  }
  mylog: function(){
    console.log('just for log test!');
  }
}

<强> main.js

var mylog =require('./sub');

mylog.log('Hurray, it works! :)');
mylog.mylog();

答案 50 :(得分:1)

这是一个极端的情况。但是,如果您需要从远程源加载JavaScript,则大多数现代浏览器可能会由于CORS或类似原因而阻止您的跨站点请求。很正常

<script src="https://another-domain.com/example.js"></script>

不起作用。并且执行document.createElement('script').src = '...'也不会削减。相反,您可以做的是通过标准GET请求将Java脚本作为资源加载,然后执行以下操作:

<script type="text/javascript">
    var script = document.createElement('script');
    script.type = 'text/javascript';

    let xhr = new XMLHttpRequest();
    xhr.open("GET", 'https://raw.githubusercontent.com/Torxed/slimWebSocket/master/slimWebSocket.js', true);
    xhr.onreadystatechange = function() {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
            script.innerHTML = this.responseText; // <-- This one
            document.head.appendChild(script);
        }
    }
    xhr.send();
</script>

通过自己抓取内容,浏览器将不会发现恶意意图,并允许您执行请求。然后,将其添加到<script>的{​​{1}}中。这仍然会导致浏览器(至少在Chrome中经过测试)解析/执行脚本。

同样,这是一个边缘案例用例。而且您可能没有向后兼容性或浏览器兼容性。但是有趣/有用的事情。

答案 51 :(得分:1)

Step 1: Declare the function in another class.

    export const myreport = (value) => {
    color = value.color;
    name = value.name;
    
    var mytext = name + " | " + color;
    return mytext;
    }

Step 2:- Import that function which is needed to be used.

    import {myreport} from '../../Test'

Step 3:- Use that function.

let val = { color: "red", name: "error" }
var resultText = myreport(val)
console.log("resultText :- ", resultText)

答案 52 :(得分:1)

发出 fetch 请求并 eval 结果。

答案 53 :(得分:1)

我的通用解决方案取自 EdgeS (我编写的)efekt.js.st 库。

<块引用>

无耻的插件警报 - 我在其他 stackexchange 网络站点上。这是 https://codereview.stackexchange.com/questions/263764/dynamic-load-css-or-script 的重新链接。

您将使用什么代码或设计来支持 cssscripts 的动态加载?

要求

  • 支持promise-await-async,包括错误处理
  • 支持一次性加载缓存,包括重新加载
  • 支持 headbody 或当前 script-element 中的负载
  • 支持加载cssjsmjs 模块或其他脚本类型
  • 支持其他标签属性,例如noncecrossorigin
static loadScriptOrStyle(url, options) {
  // provenance :<# **Smallscript EdgeS efekt** `efekt.js.st` github libraries #>
  // returns    :<Promise#onload;onerror>
  // options    :<# `fIgnoreCache`, `fAppendToHead`, `fUrlIsStyle`, `attrs:{}` #>
  const head = document.head; let node = options?.fAppendToBody ? document.body : head;
  const url_loader_cache = document.head.url_loader_cache
    ? head.url_loader_cache
    : (head.url_loader_cache = {script:{},link:{}})
  const kind = (options?.fUrlIsStyle || /\.css(?:(?:\?|#).*)?$/i.test(url))
    ? 'link' : 'script';
  // check already-loaded cache
  if(url_loader_cache[kind][url]) {
    const el = url_loader_cache[kind][url];
    // support `fIgnoreCache` reload-option; should not use on `head`
    if(options?.fIgnoreCache)
      el.remove();
    else
      return(new CustomEvent('cache',{detail:el}));
  }
  // (re)create and record it
  const self = document.currentScript;
  const el = url_loader_cache[kind][url] = document.createElement(kind);
  const append = (!self || options?.fAppendToHead || options?.fAppendToBody)
    ? el => node.appendChild(el)
    : el => self.parentNode.insertBefore(el, self);
  const load = new Promise((resolve, reject) => {
    el.onload  = e => {e.detail = el;resolve(e)};
    el.onerror = e => {e.detail = el;reject(e)};
    // `onload` or `onerror` possibly alter `cache` value
    // throw(new URIError(`The ${url} didn't load correctly.`))
  });
  // configure `module` attr, as appropriate
  if(/\.mjs(?:(?:\?|#).*)?$/i.test(url))
    el.type = 'module'
  // configure other attrs as appropriate (referrer, nonce, etc)
  for(const key in options?.attrs) {el[key] = attrs[key]}
  // trigger it
  if(kind === 'link') el.rel = 'stylesheet', el.href = url; else el.src = url;
  append(el);
  return(load);
}

答案 54 :(得分:0)

如果您发现有2个或更多脚本在调用时占用相同的功能,那么我们不能同时包含它们,我们需要通过用户选择动态。< / p>

使用jQuery$.getScript中包含其他文件,自脚本will not be cached by default起作用。所以我们保存以调用另一个脚本。电话可以安排如下:

<强> HTML

<select class="choice">
  <option value="script1" selected>Script-1</option>
  <option value="script2">Script-2</option>
</select>

JS

  $(".choice").change(on_change);

    var url = "https://example.com";
    $.url1 = url + "/script1.js";
    $.url2 = url + "/script2.js";

  function on_change() {
    if ($(".choice").val()=="script1") {
        script1();
    } else {
        script2();
    }

    // script1
    function script1() {   
      $.getScript($.url1, function( data, textStatus, jqxhr ) {
          //excecute here
      });  
    }

    // script2
    function script2() {
       $.getScript($.url2, function( data, textStatus, jqxhr ) {
          //excecute here
      });  
    }

答案 55 :(得分:0)

请注意,我们通常使用静态脚本。所以我们希望尽可能地从缓存中获取。 这样可以节省网络流量并加快着陆速度。

用法

$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
  console.log( textStatus );
});

cache:true 选项已添加到ajax方法

答案 56 :(得分:0)

var xxx = require("../lib/your-library.js")

import xxx from "../lib/your-library.js" //get default export
import {specificPart} from '../lib/your-library.js' //get named export
import * as _name from '../lib/your-library.js'  //get full export to alias _name

答案 57 :(得分:0)

按顺序动态加载多个脚本

如果仅加载一个脚本,或者您不关心多个脚本的加载顺序,则上述功能可以正常工作。如果某些脚本依赖于其他脚本,则需要使用Promise来指定加载顺序。其背后的原因是Javascript异步加载了诸如脚本和图像之类的资源。加载顺序不取决于异步调用的顺序,这意味着即使在调用dynamicallyLoadScript("scrip1")之前调用dynamicallyLoadScript("scrip2")

,也不能保证在script2之前加载script1

因此,这是保证加载顺序的dynamicLoadScript的另一个版本:

// Based on: https://javascript.info/promise-basics#example-loadscript
function dynamicallyLoadScript(url) {
        return new Promise(function(resolve, reject) {
        var script = document.createElement("script");
        script.src = url;
        script.onload = resolve;
        script.onerror = () => reject(new Error(`Error when loading ${url}!`));
        document.body.appendChild(script);
    });

有关承诺的更多信息,请参见this excellent page

这个新的dynamicLoadScript的用法非常简单:

dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => dynamicallyLoadScript("script4.js"))
.then(() => dynamicallyLoadScript("script5.js"))
//...

现在,脚本以script1.js,script2.js,script3.js等的顺序加载。

脚本加载后运行相关代码

此外,您可以在脚本加载后立即运行使用脚本的代码。加载脚本后,只需添加另一个.then

dynamicallyLoadScript("script1.js")
.then(() => dynamicallyLoadScript("script2.js"))
.then(() => foo()) // foo can be a function defined in either script1, script2
.then(() => dynamicallyLoadScript("script3.js"))
.then(() => {
     if (var1){ // var1 can be a global variable defined in either script1, script2, or script3
          bar(var1); // bar can be a function defined in either script1, script2, or script3
     } else {
          foo(var1);
     }
})
//more .then chains...

处理加载错误

要显示未处理的承诺拒绝(加载脚本等错误),请将此unhandledrejection事件监听器放在代码顶部:

// Based on: https://javascript.info/promise-error-handling#unhandled-rejections
window.addEventListener('unhandledrejection', function(event) {
     // the event object has two special properties:
     console.error(event.promise);// the promise that generated the error
     console.error(event.reason); // the unhandled error object
});

现在,将通知您任何脚本加载错误。


快捷键功能

如果您要加载许多脚本而在加载后没有立即执行代码,则此速记功能可能会派上用场:

function dynamicallyLoadScripts(urls){
        if (urls.length === 0){
            return;
        }
        let promise = dynamicallyLoadScript(urls[0]);
        urls.slice(1).forEach(url => {
            promise = promise.then(() => dynamicallyLoadScript(url));
        });
    }

要使用它,只需传递如下这样的脚本网址数组即可:

const scriptURLs = ["dist/script1.js", "dist/script2.js", "dist/script3.js"];
dynamicallyLoadScripts(scriptURLs);

脚本将按照它们在数组中出现的顺序进行加载。

答案 58 :(得分:0)

您可以使用我的loadScript ES module加载JavaScript文件。

用法:

在您的head标签中,包含以下代码:

<script src="https://raw.githack.com/anhr/loadScriptNodeJS/master/build/loadScript.js"></script>

现在,您可以使用window.loadScript加载JavaScript文件。

loadScript.async(src,[options])

异步加载JavaScript文件。

src:外部脚本文件的URL或脚本文件名的数组。

选项:以下选项可用

onload: function () The onload event occurs when a script has been loaded. Default is undefined.

onerror: function ( str, e ) The onerror event occurs when an error has been occured. Default is undefined.

    str: error details

    e: event

appendTo: The node to which the new script will be append. Default is head node.

例如

loadScript.async( "JavaScript.js",
        {
            onload: function () {

                var str = 'file has been loaded successfully';
                console.log( str );

            },
            onerror: function ( str, e ) {

                console.error( str );

            },

        } );

Example of usage

答案 59 :(得分:0)

从facebook创意中获取的答案@Dan Dascalescu扩展到lib。

(function() {   
var __ = {};
this._ = function(name, callback) {
    if(__[name]==undefined) {
        __[name] = true;
        var firstScript = document.getElementsByTagName('script')[0],
          js = document.createElement('script');
          js.src =  name;
          js.onload = callback;
          firstScript.parentNode.insertBefore(js, firstScript);
    }
}
})();

(new _('https://cdnjs.cloudflare.com/ajax/libs/Snowstorm/20131208/snowstorm-min.js', function() {
 snowStorm.snowColor = '#99ccff';
}));

答案 60 :(得分:0)

ES6:是,在脚本标签(support)中使用type =“ module”

<script type="module" src="script.js"></script>

script.js文件中,包含另一个类似的文件:

import { hello } from './module.js';
...
// alert(hello());

在“ module.js”中,您必须export function/class要导入

export function hello() {
    return "Hello World";
}

工作example here

答案 61 :(得分:0)

我没有看到一个答案,即您在一个文件中创建一个包含所有函数和变量的对象,然后将该对象用作在另一个文件中引用该对象的参数。

例如,您拥有名为“ jsMod.js”,“ jsView”和“ jsContr.js”的文件:


    //jsMod.js file
    JSMODOBJ = {};
    JSMODOBJ.valueAddition = function(/* element value 1 */ val1,
                                          /* element value 2 */ val2) {
        return val1 + val2;
    }


    //jsView.js file
    JSVIEWOBJ = {};
    JSVIEWOBJ.elementColour = function(/* element id to change colour */ id,
                                          /* css colour classname */ col) {
        document.getElementById(id).className = col;
    }


    //jsContr.js file
    JSCONTROBJ = {};
    var jsMod = JSMODOBJ;
    var jsView = JSVIEWOBJ;

    JSCONTROBJ.changeColourByValue = function (val1, val2, id, clss) {
        if (jsMod.valueAddition(val1,val2) !== 0) {
            jsView.elementColour(id, clss);
        }
    }

然后,您可以通过将scripts回显到.html或.php文件中来动态设置.js文件:

<?php
    echo "<script src = './js/dleafView.js'></script>
        <script src = './js/dleafModule.js'></script>
        <script src = './js/dleafContr.js'></script>";
?>

然后只需在<script type="text/javascript"></script>标记内调用控制函数。当然,从一开始就需要花费很多时间,但是从长远来看,它可以节省您的时间。

我以稍微不同的方式使用它,但是这种方式也可以。

答案 62 :(得分:0)

您还可以将gulpgulp-concatgulp-typescript/// <reference path=包括:

packages.json

{
  "scripts": {
    "gulp": "gulp main"
  },
  "dependencies": {
    "@types/gulp": "^4.0.6",
    "@types/gulp-concat",
    "@types/gulp-typescript",
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-resolve-dependencies": "^3.0.1",
    "gulp-typescript": "^6.0.0-alpha.1",
    "typescript": "^3.7.3"
  }
}

src / someimport.ts

class SomeClass {
    delay: number;
}

src / main.ts

/// <reference path="./someimport.ts" />

someclass = new SomeClass();
someclass.delay = 1;

main gulp任务(在gulpfile.js上)仅针对src/main.js文件,从而解决了其所有/// <reference path=...包含引用。这些包括称为Triple-Slash Directives,它们仅用于编译器工具来组合文件。在我们的情况下,.pipe(resolveDependencies({和打字稿本身会在检查文件中是否缺少类型,变量等时明确使用它们。

  1. https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html
  2. When do I need a triple slash reference?

如果您想自定义var tsProject = ts.createProject调用而不使用tsconfig.json文件或覆盖其参数,请参考https://github.com/ivogabe/gulp-typescript#api-overview

gulpfile.js

var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');

var ts = require("gulp-typescript");
var tsProject = ts.createProject("tsconfig.json");

gulp.task("main", function() {
  return gulp
    .src(["src/main.ts"])
    .pipe(resolveDependencies({
      pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
    }))
    .on('error', function(err) {
        console.log(err.message);
    })
    .pipe(tsProject())
    .pipe(concat('main.js'))
    .pipe(gulp.dest("build/"));
});

如果您希望将所有类型脚本项目文件作为目标,而不仅仅是src/main.ts,则可以替换为:

  return gulp
    .src(["src/main.ts"])
    .pipe(resolveDependencies({
    ...
// -->
  return tsProject
    .src()
    .pipe(resolveDependencies({
    ...

如果您不想使用typescript,则可以使用此简化的gulpfile.js并从typescript中删除所有package.json包含的内容:

gulpfile.js

var gulp = require("gulp");
var concat = require('gulp-concat');
var resolveDependencies = require('gulp-resolve-dependencies');

gulp.task("main", function() {
  return gulp
    .src(["src/main.js"])
    .pipe(resolveDependencies({
      pattern: /^\s*\/\/\/\s*<\s*reference\s*path\s*=\s*(?:"|')([^'"\n]+)/gm
    }))
    .on('error', function(err) {
        console.log(err.message);
    })
    .pipe(concat('main.js'))
    .pipe(gulp.dest("build/"));
});

packages.json

{
  "scripts": {
    "gulp": "gulp main"
  },
  "dependencies": {
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-resolve-dependencies": "^3.0.1"
  }
}

然后,在运行命令npm run gulp之后,将创建文件build/main.js,其内容如下:

build / main.js

class SomeClass {
}
/// <reference path="./someimport.ts" />
someclass = new SomeClass();
someclass.delay = 1;

在提供script目录文件后,允许我使用build标签在浏览器中添加它:

<html>
    <head>
        <script src="main.js"></script>
    </head>
    <body>
        <script type="text/javascript">
            console.log(someclass.delay);
        </script>
    </body>
</html>

相关问题:

  1. https://www.typescriptlang.org/docs/handbook/gulp.html
  2. Can I use the typescript without requireJS?
  3. Gulp simple concatenation of main file that requires another JS file
  4. Client on node: Uncaught ReferenceError: require is not defined
  5. How can typescript browser node modules be compiled with gulp?
  6. Concatenate files using babel
  7. How to require CommonJS modules in the browser?
  8. Is there an alternative to Browserify?

答案 63 :(得分:-3)

您应使用此:

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

容易!