javascript - require区别 - js includes方法




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

也许您可以使用我在此页面上找到的此功能如何在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中是否有类似于@import的内容,允许您在另一个JavaScript文件中包含JavaScript文件?


以下是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/


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

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

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

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

$.getScript("another_script.js");

如果您要加载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>

如果有人想要更高级的东西,请尝试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文件。

...


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

我刚写了这个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


我通常的方法是:

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


或者不是在运行时包括在上载之前使用脚本连接。

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

也可以看看:


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

你只需import cond from 'cond.js';写下import cond from 'cond.js'; 从文件cond.js加载名为cond的宏。

因此,您不必依赖任何JavaScript框架,也不必显式地进行Ajax调用。

参考:


用现代语言来说就是这样

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

这应该做:

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

这是没有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标头。


@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样板中)并且有点混淆(“你能做到吗?”我想到了这个问题。然后我意识到这是一个特定于应用程序的文件类型(有点令人失望,同意)。然而,认为这些知识可能对其他人有所帮助。

更新:混合物现在免费的(离线)。

更新:混合物现已停产。旧的混合物发布仍然可用


我创建了一个函数,允许您使用与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中导入/包含模块脚本的工作。有关代码的详细说明,请参阅博客文章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);
};

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

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

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


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

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

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

你当然可以使用$(“body”)。append(),但是你再也无法正确调试了。

注意:您必须仅在页面加载时使用此选项,否则您将获得一个空白屏幕。换句话说,始终将此放在document.ready之前/之外。在点击事件或类似事件中加载页面后,我没有使用过此测试,但我很确定它会失败。

我喜欢扩展jQuery的想法,但显然你不需要。

在调用之前document.writeln,它会通过评估所有脚本元素来检查以确保脚本尚未加载。

我假设脚本在其document.ready事件执行之前未完全执行。(我知道使用document.ready不是必需的,但很多人使用它,处理这是一个安全措施。)

加载其他文件后,document.ready回调将以错误的顺序执行。为了在实际加载脚本时解决此问题,导入它的脚本将自行重新导入并暂停执行。这会导致原始文件现在在其document.ready导入的任何脚本之后执行其回调。

您可以尝试修改jQuery readyList,而不是这种方法,但这似乎是一个更糟糕的解决方案。

解:

$.extend(true,
{
    import_js : function(scriptpath, reAddLast)
    {
        if (typeof reAddLast === "undefined" || reAddLast === null)
        {
            reAddLast = true; // Default this value to true. It is not used by the end user, only to facilitate recursion correctly.
        }

        var found = false;
        if (reAddLast == true) // If we are re-adding the originating script we do not care if it has already been added.
        {
            found = $('script').filter(function () {
                return ($(this).attr('src') == scriptpath);
            }).length != 0; // jQuery to check if the script already exists. (replace it with straight JavaScript if you don't like jQuery.
        }

        if (found == false) {

            var callingScriptPath = $('script').last().attr("src"); // Get the script that is currently loading. Again this creates a limitation where this should not be used in a button, and only before document.ready.

            document.writeln("<script type='text/javascript' src='" + scriptpath + "'></script>"); // Add the script to the document using writeln

            if (reAddLast)
            {
                $.import_js(callingScriptPath, false); // Call itself with the originating script to fix the order.
                throw 'Readding script to correct order: ' + scriptpath + ' < ' + callingScriptPath; // This halts execution of the originating script since it is getting reloaded. If you put a try / catch around the call to $.import_js you results will vary.
            }
            return true;
        }
        return false;
    }
});

用法:

文件3:

var f3obj = "file3";

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

文件2:

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

文件1:

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






include