it-swarm-vi.com

Làm cách nào để bao gồm một tệp JavaScript trong một tệp JavaScript khác?

Có một cái gì đó trong JavaScript tương tự như @import trong CSS cho phép bạn bao gồm một tệp JavaScript bên trong một tệp JavaScript khác?

4481
Alec Smart

Các phiên bản cũ của JavaScript không có nhập, bao gồm hoặc yêu cầu, vì vậy nhiều cách tiếp cận khác nhau cho vấn đề này đã được phát triển.

Nhưng kể từ năm 2015 (ES6), JavaScript đã có mô-đun ES6 tiêu chuẩn để nhập mô-đun trong Node.js, cũng được hỗ trợ bởi hầu hết các trình duyệt hiện đại .

Để tương thích với các trình duyệt cũ hơn, build và/hoặc transpilation có thể được sử dụng các công cụ.

Mô-đun ES6

Các mô-đun ECMAScript (ES6) đã được hỗ trợ trong Node.js kể từ v8.5, với cờ --experimental-modules. Tất cả các tệp liên quan phải có phần mở rộng .mjs.

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

Mô-đun ECMAScript trong trình duyệt

Các trình duyệt đã hỗ trợ tải trực tiếp các mô-đun ECMAScript (không yêu cầu công cụ như Webpack) kể từ đó Safari 10.1, Chrome 61, Firefox 60 và Edge 16. Kiểm tra hỗ trợ hiện tại tại 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);
}

Đọc thêm tại https://jakearchibald.com/2017/es-modules-in-browsers/

Nhập động trong trình duyệt

Nhập động cho phép tập lệnh tải các tập lệnh khác khi cần:

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

Đọc thêm tại https://developers.google.com/web/updates/2017/11/dynamic-import

Node.js yêu cầu

Kiểu nhập mô-đun cũ, vẫn được sử dụng rộng rãi trong Node.js, là hệ thống module.exports/required .

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

Có nhiều cách khác để JavaScript đưa nội dung JavaScript bên ngoài vào các trình duyệt không yêu cầu tiền xử lý.

Đang tải AJAX

Bạn có thể tải tập lệnh bổ sung bằng lệnh gọi AJAX và sau đó sử dụng eval để chạy tập lệnh. Đây là cách đơn giản nhất, nhưng nó bị giới hạn trong miền của bạn do mô hình bảo mật hộp cát JavaScript. Sử dụng eval cũng mở ra cơ hội cho các lỗi, hack và các vấn đề bảo mật.

Đang tải

Giống như Nhập khẩu động, bạn có thể tải một hoặc nhiều tập lệnh bằng lệnh gọi fetch bằng cách sử dụng lời hứa để kiểm soát thứ tự thực hiện cho các phụ thuộc tập lệnh bằng cách sử dụng thư viện Fetch Tiêm :

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

đang tải jQuery

Thư viện jQuery cung cấp chức năng tải trong một dòng :

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

Đang tải tập lệnh động

Bạn có thể thêm thẻ tập lệnh với URL tập lệnh vào HTML. Để tránh chi phí hoạt động của jQuery, đây là một giải pháp lý tưởng.

Kịch bản thậm chí có thể nằm trên một máy chủ khác. Hơn nữa, trình duyệt đánh giá mã. Thẻ <script> có thể được chèn vào trang web <head> hoặc được chèn ngay trước thẻ đóng </body>.

Đây là một ví dụ về cách thức này có thể hoạt động:

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

Hàm này sẽ thêm thẻ <script> mới vào cuối phần đầu của trang, trong đó thuộc tính src được đặt thành URL được cung cấp cho hàm làm tham số đầu tiên.

Cả hai giải pháp này đều được thảo luận và minh họa trong JavaScript Madness: Dynamic Script Loading .

Phát hiện khi tập lệnh đã được thực thi

Bây giờ, có một vấn đề lớn bạn phải biết về. Làm điều đó ngụ ý rằng bạn tải mã từ xa . Các trình duyệt web hiện đại sẽ tải tệp và tiếp tục thực thi tập lệnh hiện tại của bạn vì chúng tải mọi thứ không đồng bộ để cải thiện hiệu suất. (Điều này áp dụng cho cả phương thức jQuery và phương thức tải tập lệnh động thủ công.)

Điều đó có nghĩa là nếu bạn sử dụng các thủ thuật này trực tiếp, bạn sẽ không thể sử dụng mã mới được tải của mình dòng tiếp theo sau khi bạn yêu cầu nó được tải , vì nó sẽ vẫn còn tải.

Ví dụ: my_lovely_script.js chứa 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

Sau đó, bạn tải lại trang nhấn F5. Và nó hoạt động! Gây nhầm lẫn...

Vậy phải làm gì với nó?

Chà, bạn có thể sử dụng bản hack mà tác giả gợi ý trong liên kết tôi đưa cho bạn. Tóm lại, đối với những người vội vàng, anh ta sử dụng một sự kiện để chạy chức năng gọi lại khi tập lệnh được tải. Vì vậy, bạn có thể đặt tất cả mã bằng thư viện từ xa trong chức năng gọi lại. Ví dụ:

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

Sau đó, bạn viết mã bạn muốn sử dụng SAU kịch bản được tải trong hàm lambda :

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

Sau đó, bạn chạy tất cả:

loadScript("my_lovely_script.js", myPrettyCode);

Lưu ý rằng tập lệnh có thể thực thi sau khi DOM được tải hoặc trước đó, tùy thuộc vào trình duyệt và liệu bạn có bao gồm dòng script.async = false; không. Có một bài viết tuyệt vời về tải Javascript nói chung trong đó thảo luận về điều này.

Hợp nhất/tiền xử lý mã nguồn

Như đã đề cập ở đầu câu trả lời này, nhiều nhà phát triển sử dụng (các) công cụ xây dựng/dịch mã như Parcel, Webpack hoặc Babel trong các dự án của họ, cho phép họ sử dụng cú pháp JavaScript sắp tới, cung cấp khả năng tương thích ngược cho các trình duyệt cũ hơn, kết hợp các tệp, thu nhỏ, thực hiện tách mã, v.v.

4044
e-satis

Nếu bất cứ ai đang tìm kiếm một cái gì đó cao cấp hơn, hãy thử RequireJS . Bạn sẽ nhận được các lợi ích bổ sung như quản lý phụ thuộc, đồng thời tốt hơn và tránh trùng lặp (nghĩa là truy xuất tập lệnh nhiều lần).

Bạn có thể viết các tệp JavaScript của mình trong "các mô-đun" và sau đó tham chiếu chúng dưới dạng các phụ thuộc trong các tập lệnh khác. Hoặc bạn có thể sử dụng RequireJS như một giải pháp "đi lấy tập lệnh" đơn giản này.

Thí dụ:

Xác định các phụ thuộc dưới dạng các mô-đun:

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

exec.js là tệp JavaScript "chính" của bạn phụ thuộc vào some-Depency.js

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

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

Trích từ GitHub README:

RequireJS tải các tệp JavaScript đơn giản cũng như được xác định rõ hơn mô-đun. Nó được tối ưu hóa để sử dụng trong trình duyệt, bao gồm cả trong Web Công nhân, nhưng nó có thể được sử dụng trong các môi trường JavaScript khác, như Tê giác và nút. Nó triển khai API mô-đun không đồng bộ.

RequireJS sử dụng các thẻ script đơn giản để tải các mô-đun/tệp, do đó, nên cho phép gỡ lỗi dễ dàng. Nó có thể được sử dụng đơn giản để tải Các tệp JavaScript, vì vậy bạn có thể thêm nó vào dự án hiện tại của mình mà không cần phải viết lại các tệp JavaScript của bạn.

... 

533
John Strickler

Thực tế một cách để tải tệp JavaScript không không đồng bộ, vì vậy bạn có thể sử dụng các chức năng có trong tệp mới tải của mình ngay sau khi tải và tôi nghĩ rằng nó hoạt động trong tất cả các trình duyệt.

Bạn cần sử dụng jQuery.append() trên phần tử <head> của trang của bạn, đó là:

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

Tuy nhiên, phương pháp này cũng có một vấn đề: nếu xảy ra lỗi trong tệp JavaScript đã nhập, Fireorms (và cả Firefox Error Console và Chrome Developer Tools cũng) sẽ báo cáo vị trí của nó không chính xác, đó là một lỗi vấn đề lớn nếu bạn sử dụng Fireorms để theo dõi lỗi JavaScript rất nhiều (tôi làm). Vì một lý do nào đó, Fireorms không biết về tệp mới được tải, vì vậy nếu xảy ra lỗi trong tệp đó, nó báo cáo rằng nó đã xảy ra trong tệp chính HTML của bạn và bạn sẽ gặp khó khăn khi tìm ra tệp thật lý do cho lỗi.

Nhưng nếu đó không phải là vấn đề với bạn, thì phương pháp này sẽ hoạt động.

Tôi thực sự đã viết một plugin jQuery có tên $ .import_js () sử dụng phương thức này:

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

Vì vậy, tất cả những gì bạn cần làm để nhập JavaScript là:

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

Tôi cũng đã thực hiện một thử nghiệm đơn giản cho việc này tại Ví dụ .

Nó bao gồm tệp main.js trong HTML chính và sau đó tập lệnh trong main.js sử dụng $.import_js() để nhập tệp bổ sung có tên included.js, định nghĩa chức năng này:

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

Và ngay sau khi bao gồm included.js, hàm hello() được gọi và bạn nhận được cảnh báo.

(Câu trả lời này là để đáp lại bình luận của e-satis).

173
Kipras

Một cách khác, theo tôi là sạch hơn nhiều, là tạo một yêu cầu Ajax đồng bộ thay vì sử dụng thẻ <script>. Đó cũng là cách Node.js xử lý bao gồm.

Đây là một ví dụ sử dụng 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);
        }
    });
}

Sau đó, bạn có thể sử dụng nó trong mã của mình vì bạn thường sử dụng bao gồm:

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

Và có thể gọi một chức năng từ tập lệnh được yêu cầu trong dòng tiếp theo:

subscript.doSomethingCool(); 
138
Ariel

Có một tin tốt cho bạn. Bạn sẽ sớm có thể tải mã JavaScript một cách dễ dàng. Nó sẽ trở thành một cách tiêu chuẩn để nhập các mô-đun mã JavaScript và sẽ là một phần của chính JavaScript cốt lõi. 

Bạn chỉ cần viết import cond from 'cond.js'; để tải macro có tên cond từ tệp cond.js.

Vì vậy, bạn không cần phải dựa vào bất kỳ khung JavaScript nào và bạn cũng không phải thực hiện Ajax cuộc gọi một cách rõ ràng.

Tham khảo:

90
Imdad

Có thể tự động tạo thẻ JavaScript và gắn nó vào tài liệu HTML từ bên trong mã JavaScript khác. Điều này sẽ tải tệp JavaScript được nhắm mục tiêu.

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");
79
Svitlana Maksymchuk

Tuyên bố import nằm trong ECMAScript 6.

Cú pháp

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;
62
draupnie

Có lẽ bạn có thể sử dụng chức năng này mà tôi tìm thấy trên trang này Làm cách nào để đưa tệp JavaScript vào tệp 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)
}

Đây là đồng bộ phiên bản không có 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);
}

Lưu ý rằng để có được tên miền chéo hoạt động này, máy chủ sẽ cần đặt tiêu đề allow-Origin trong phản hồi của nó.

47
heinob

Tôi vừa viết mã JavaScript này (sử dụng Nguyên mẫu cho DOM thao tác):

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

Sử dụng:

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

43
nornagon

Đây là phiên bản tổng quát về cách Facebook thực hiện nó cho nút Like phổ biến của họ:

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

Nếu nó hoạt động cho Facebook, nó sẽ làm việc cho bạn.

Lý do tại sao chúng tôi tìm kiếm phần tử script đầu tiên thay vì head hoặc body là vì một số trình duyệt không tạo một phần tử nếu thiếu, nhưng chúng tôi đảm bảo có phần tử script - phần tử này. Đọc thêm tại http: //www.jspotypes.com/the-ridicificent-case-of-adding-a-script-element/ .

36
Dan Dascalescu

Nếu bạn muốn bằng JavaScript thuần túy, bạn có thể sử dụng document.write.

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

Nếu bạn sử dụng thư viện jQuery, bạn có thể sử dụng phương thức $.getScript.

$.getScript("another_script.js");
31
Venu immadi

Bạn cũng có thể tập hợp các tập lệnh của mình bằng cách sử dụng PHP :

Tệp 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
24
Calmarius

Hầu hết các giải pháp hiển thị ở đây ngụ ý tải động. Thay vào đó, tôi đã tìm kiếm một trình biên dịch tập hợp tất cả các tệp phụ thuộc vào một tệp đầu ra. Giống như Ít hơn / Sass tiền xử lý đối phó với CSS @import theo quy tắc. Vì tôi không tìm thấy bất cứ điều gì tử tế kiểu này, tôi đã viết một công cụ đơn giản để giải quyết vấn đề.

Vì vậy, đây là trình biên dịch, https://github.com/dsheiko/jsic , thay thế $import("file-path") bằng nội dung tệp được yêu cầu một cách an toàn. Đây là Grunt plugin tương ứng: https://github.com/dsheiko/grunt-jsic .

Trên nhánh chính của jQuery, họ chỉ cần ghép các tệp nguồn nguyên tử thành một tệp duy nhất bắt đầu bằng intro.js và kết thúc bằng outtro.js. Điều đó không phù hợp với tôi vì nó không cung cấp sự linh hoạt trong thiết kế mã nguồn. Kiểm tra cách nó hoạt động với jsic:

src/main.js

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

src/Biểu mẫu/Đầu vào/Tel.js

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

Bây giờ chúng ta có thể chạy trình biên dịch:

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

Và lấy tập tin kết hợp

xây dựng/main.js

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

Nếu bạn có ý định tải tệp JavaScript là sử dụng các hàm từ tệp được nhập/bao gồm , bạn cũng có thể xác định một đối tượng toàn cục và đặt các hàm làm các mục đối tượng. Ví dụ:

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

Bạn chỉ cần cẩn thận khi đưa các tập lệnh vào tệp HTML. Thứ tự nên như dưới đây:

<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>
20
Adem İlhan

Điều này nên làm:

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

Hoặc thay vì bao gồm trong thời gian chạy, sử dụng tập lệnh để ghép nối trước khi tải lên.

Tôi sử dụng Sprockets (Tôi không biết nếu có người khác). Bạn xây dựng mã JavaScript của mình trong các tệp riêng biệt và bao gồm các nhận xét được xử lý bởi công cụ Sprockets như bao gồm. Để phát triển, bạn có thể bao gồm các tệp tuần tự, sau đó để sản xuất hợp nhất chúng ...

Xem thêm:

17
JMawer

Trong trường hợp bạn đang sử dụng Công nhân web và muốn bao gồm các tập lệnh bổ sung trong phạm vi của công nhân, các câu trả lời khác được cung cấp về việc thêm tập lệnh vào thẻ head, v.v. sẽ không hiệu quả với bạn.

May mắn thay, Công nhân web có chức năng importScripts của riêng họ là chức năng toàn cầu trong phạm vi của Công nhân web, có nguồn gốc từ chính trình duyệt vì nó là một phần của đặc tả .

Ngoài ra, là câu trả lời được bình chọn cao thứ hai cho các câu hỏi nổi bật của bạn , RequireJS cũng có thể xử lý các tập lệnh bên trong Công cụ web (có thể gọi chính importScripts, nhưng với một vài tính năng hữu ích khác).

14
Turnerj

Tôi đã có một vấn đề đơn giản, nhưng tôi đã gặp khó khăn khi trả lời câu hỏi này.

Tôi đã phải sử dụng một biến (myVar1) được xác định trong một tệp JavaScript (myvariables.js) trong một tệp JavaScript khác (main.js).

Đối với điều này, tôi đã làm như dưới đây:

Đã tải mã JavaScript trong tệp HTML, theo đúng thứ tự, trước tiên là myvariables.js, sau đó là main.js:

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

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

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

Tập tin: myvariables.js

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

Tệp: main.js

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

Như bạn đã thấy, tôi đã sử dụng một biến trong một tệp JavaScript trong một tệp JavaScript khác, nhưng tôi không cần đưa một biến vào một tệp khác. Tôi chỉ cần đảm bảo rằng tệp JavaScript đầu tiên được tải trước tệp JavaScript thứ hai và, các biến của tệp JavaScript đầu tiên có thể truy cập được trong tệp JavaScript thứ hai, tự động.

Điều này đã cứu ngày của tôi. Tôi hi vọng cái này giúp được.

13
Manohar Reddy Poreddy

Cú pháp @import để đạt được nhập JavaScript giống CSS có thể sử dụng một công cụ như Mixture thông qua loại tệp .mix đặc biệt của họ (xem tại đây ). Tôi tưởng tượng ứng dụng chỉ đơn giản là sử dụng một trong những phương pháp đã nói ở trên, mặc dù tôi không biết. 

Từ tài liệu Hỗn hợp trên các tệp .mix

Trộn các tệp chỉ đơn giản là các tệp .js hoặc .css với .mix. trong tên tập tin. A tập tin trộn chỉ đơn giản là mở rộng chức năng của một kiểu bình thường hoặc tập tin kịch bản và cho phép bạn nhập và kết hợp.

Dưới đây là ví dụ tệp .mix kết hợp nhiều tệp .js thành một:

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

Hỗn hợp xuất kết quả này dưới dạng scripts-global.js và cũng là phiên bản rút gọn (scripts-global.min.js).

Lưu ý: Tôi không liên kết với Mixture theo bất kỳ cách nào, ngoài việc sử dụng nó làm công cụ phát triển giao diện người dùng. Tôi đã bắt gặp câu hỏi này khi thấy một tệp .mix JavaScript đang hoạt động (trong một trong các bản mẫu hỗn hợp) và hơi bối rối với nó ("bạn có thể làm điều này không?" Sau đó, tôi nhận ra rằng đó là một loại tệp dành riêng cho ứng dụng (hơi thất vọng, đồng ý). Tuy nhiên, hình dung kiến ​​thức có thể hữu ích cho những người khác.

UPDATE: Hỗn hợp là hiện miễn phí (ngoại tuyến).

UPDATE: Hỗn hợp hiện đã ngưng. Bản phát hành hỗn hợp cũ vẫn có sẵn

12
Isaac Gregson

Phương pháp thông thường của tôi là:

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

Nó hoạt động rất tốt và không sử dụng tải lại trang cho tôi. Tôi đã thử phương pháp AJAX (một trong những câu trả lời khác) nhưng dường như nó không hoạt động tốt với tôi.

Đây là một lời giải thích về cách mã hoạt động cho những người tò mò: về cơ bản, nó tạo ra một thẻ script mới (sau cái đầu tiên) của URL. Nó đặt nó ở chế độ không đồng bộ để nó không chặn phần còn lại của mã, nhưng gọi lại khi readyState (trạng thái của nội dung sẽ được tải) thay đổi thành 'được tải'.

11
Christopher Dumas

Tôi đã viết một mô-đun đơn giản tự động hóa công việc nhập/bao gồm các tập lệnh mô-đun trong JavaScript. Để được giải thích chi tiết về mã, hãy tham khảo bài đăng trên blog JavaScript yêu cầu/nhập/bao gồm các mô-đun.

// ----- 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);
};
11
stamat
var js = document.createElement("script");

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

document.body.appendChild(js);
10
Sam4Code

Trong ngôn ngữ hiện đại, nó sẽ là 

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

Ngoài ra còn có Head.js . Nó rất dễ dàng để đối phó với:

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

Như bạn thấy, nó dễ hơn Require.js và thuận tiện như phương thức $.getScript của jQuery. Nó cũng có một số tính năng nâng cao, như tải có điều kiện, phát hiện tính năng và nhiều hơn nữa .

9
Ale

Tôi đã đến câu hỏi này bởi vì tôi đang tìm kiếm một cách đơn giản để duy trì một bộ sưu tập các plugin JavaScript hữu ích. Sau khi thấy một số giải pháp ở đây, tôi đã nghĩ ra điều này:

  1. Thiết lập một tệp có tên là "plugins.js" (hoặc extend.js hoặc những gì có bạn). Giữ các tệp plugin của bạn cùng với một tệp chủ đó.

  2. plugins.js sẽ có một mảng gọi là "pluginNames []" mà chúng tôi sẽ lặp qua từng (), sau đó gắn một thẻ vào phần đầu cho mỗi plugin

    // đặt mảng được cập nhật khi chúng tôi thêm hoặc xóa tệp plugin var pluginNames = ["lettering", "fittext", "butterjam", v.v.]; // một thẻ script cho mỗi plugin $ .each (pluginNames, function () { $ ('head'). append (''); });

  3. gọi thủ công chỉ một tệp trong đầu của bạn:
    <script src="js/plugins/plugins.js"></script>

Tôi thấy rằng mặc dù tất cả các plugin đã được đưa vào thẻ head theo cách chúng nên, nhưng chúng không luôn được trình duyệt chạy khi bạn nhấp vào trang hoặc làm mới.

Tôi thấy đáng tin cậy hơn khi chỉ viết các thẻ script trong PHP bao gồm. Bạn chỉ phải viết nó một lần và điều đó cũng tương tự như gọi plugin bằng JavaScript.

9
rgb_life

Tập lệnh này sẽ thêm tệp JavaScript vào đầu bất kỳ thẻ <script> nào khác:

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

Có rất nhiều câu trả lời tiềm năng cho câu hỏi này. Câu trả lời của tôi rõ ràng là dựa trên một số trong số họ. Đây là những gì tôi đã kết thúc sau khi đọc qua tất cả các câu trả lời.

Vấn đề với $.getScript và thực sự là bất kỳ giải pháp nào khác yêu cầu gọi lại khi tải xong là nếu bạn có nhiều tệp sử dụng nó và phụ thuộc vào nhau, bạn không còn cách nào để biết khi nào tất cả các tập lệnh đã được tải (một khi chúng đã được tải lồng trong nhiều tập tin).

Thí dụ:

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

Bạn đã đúng khi nói rằng bạn có thể chỉ định Ajax chạy đồng bộ hoặc sử dụng XMLHttpRequest , nhưng xu hướng hiện tại dường như là không dùng các yêu cầu đồng bộ, do đó bạn có thể không nhận được hỗ trợ trình duyệt đầy đủ ngay bây giờ hoặc trong tương lai.

Bạn có thể thử sử dụng $.when để kiểm tra một mảng các đối tượng bị trì hoãn, nhưng bây giờ bạn đang làm điều này trong mọi tệp và tệp 2 sẽ được xem là được tải ngay khi $.when được thực thi không phải khi thực hiện cuộc gọi lại, vì vậy tệp1 vẫn tiếp tục thực thi trước tệp Nó đã nạp đầy. Điều này thực sự vẫn có cùng một vấn đề.

Tôi quyết định đi lùi thay vì tiến lên. Cảm ơn bạn document.writeln. Tôi biết đó là điều cấm kỵ, nhưng miễn là nó được sử dụng đúng cách thì nó hoạt động tốt. Bạn kết thúc với mã có thể được gỡ lỗi dễ dàng, hiển thị trong DOM chính xác và có thể đảm bảo thứ tự các phụ thuộc được tải chính xác.

Tất nhiên bạn có thể sử dụng $ ("body"). Append (), nhưng sau đó bạn không còn có thể gỡ lỗi chính xác nữa.

LƯU Ý: Bạn phải sử dụng điều này chỉ trong khi trang đang tải, nếu không bạn sẽ có một màn hình trống. Nói cách khác, luôn đặt cái này trước/bên ngoài tài liệu. Đã. Tôi chưa thử nghiệm bằng cách này sau khi trang được tải trong một sự kiện nhấp chuột hoặc bất cứ điều gì tương tự, nhưng tôi chắc chắn rằng nó sẽ thất bại.

Tôi thích ý tưởng mở rộng jQuery, nhưng rõ ràng là bạn không cần.

Trước khi gọi document.writeln, nó sẽ kiểm tra để đảm bảo tập lệnh chưa được tải bằng cách đánh giá tất cả các thành phần tập lệnh.

Tôi giả sử rằng một tập lệnh không được thực thi đầy đủ cho đến khi sự kiện document.ready của nó được thực thi. (Tôi biết sử dụng document.ready là không bắt buộc, nhưng nhiều người sử dụng nó và xử lý việc này là một biện pháp bảo vệ.)

Khi các tệp bổ sung được tải, các cuộc gọi lại document.ready sẽ được thực hiện theo thứ tự sai. Để giải quyết vấn đề này khi tập lệnh thực sự được tải, tập lệnh đã nhập nó được nhập lại chính nó và việc thực thi bị dừng lại. Điều này khiến cho tệp khởi tạo bây giờ có hàm gọi lại document.ready được thực thi sau bất kỳ tập lệnh nào mà nó nhập.

Thay vì cách tiếp cận này, bạn có thể cố gắng sửa đổi jQuery readyList, nhưng đây có vẻ là một giải pháp tồi tệ hơn.

Dung dịch:

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

Sử dụng:

Tệp 3:

var f3obj = "file3";

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

Tệp2:

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

Tệp1:

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

Tôi đã tạo một hàm cho phép bạn sử dụng verbiage tương tự với C #/Java để bao gồm một tệp JavaScript. Tôi đã kiểm tra nó một chút ngay cả từ bên trong tệp khác JavaScript và nó dường như hoạt động. Nó không yêu cầu jQuery mặc dù cho một chút "ma thuật" ở cuối.

Tôi đặt mã này vào một tệp ở thư mục gốc của thư mục tập lệnh của mình (tôi đặt tên là global.js, nhưng bạn có thể sử dụng bất cứ thứ gì bạn muốn. Trừ khi tôi nhầm lẫn điều này và jQuery phải là tập lệnh bắt buộc duy nhất trên một trang nhất định. Hãy ghi nhớ Điều này phần lớn chưa được kiểm chứng ngoài một số cách sử dụng cơ bản, do đó, có thể có hoặc không có bất kỳ vấn đề nào với cách tôi đã thực hiện; sử dụng rủi ro của riêng bạn yadda yadda Tôi không chịu trách nhiệm nếu bạn làm hỏng mọi thứ lên 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

Mặc dù những câu trả lời này rất hay, nhưng có một "giải pháp" đơn giản đã có từ khi tải tập lệnh tồn tại và nó sẽ bao gồm 99,999% trong hầu hết các trường hợp sử dụng của mọi người. Chỉ cần bao gồm tập lệnh bạn cần trước tập lệnh yêu cầu. Đối với hầu hết các dự án, không mất nhiều thời gian để xác định tập lệnh nào là cần thiết và theo thứ tự nào.

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

Nếu script2 yêu cầu script1, đây thực sự là cách dễ nhất tuyệt đối để làm một cái gì đó như thế này. Tôi rất ngạc nhiên không ai đưa ra điều này, vì đó là câu trả lời rõ ràng và đơn giản nhất sẽ được áp dụng trong gần như mọi trường hợp.

6
KthProg

Có một số cách để triển khai các mô-đun trong Javascript, Dưới đây là 2 cách phổ biến nhất:

Mô-đun ES6

Các trình duyệt chưa hỗ trợ hệ thống sửa đổi này, vì vậy để bạn sử dụng cú pháp này, bạn phải sử dụng một gói như webpack. Dù sao, sử dụng một gói là tốt hơn bởi vì điều này có thể kết hợp tất cả các tệp khác nhau của bạn thành một tệp (hoặc liên quan đến cặp đôi). Điều này sẽ phục vụ các tệp từ máy chủ đến máy khách nhanh hơn vì mỗi yêu cầu HTTP có một số chi phí liên quan đi kèm với nó. Do đó, bằng cách giảm yêu cầu HTTP quá mức, chúng tôi cải thiện hiệu suất. Dưới đây là một ví dụ về các mô-đun 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 (được sử dụng trong NodeJS)

Hệ thống điều chỉnh này được sử dụng trong NodeJS. Về cơ bản, bạn thêm xuất khẩu của mình vào một đối tượng được gọi là module.exports. Sau đó, bạn có thể truy cập đối tượng này thông qua một require('modulePath'). Điều quan trọng ở đây là nhận ra rằng các mô-đun này đang được lưu trữ, vì vậy nếu bạn require() một mô-đun nhất định hai lần, nó sẽ trả về mô-đun đã được tạo.

// 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
6
Willem van der Veen

Đây là một cách giải quyết cho các trình duyệt (không phải Node.js) bằng cách nhập HTML.

Đầu tiên, tất cả các lớp và tập lệnh JavaScript không nằm trong các tệp .js, mà trong các tệp .js.html (.js .html chỉ để nhận ra giữa các trang HTML và các tập lệnh/lớp JavaScript hoàn chỉnh), bên trong các thẻ <script>, như sau:

MyClass.js.html:

<script>
   class MyClass {

      // Your code here..

   }

</script>

Sau đó, nếu bạn muốn nhập lớp của mình, bạn chỉ cần sử dụng nhập HTML:

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

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

EDIT: Nhập HTML sẽ bị loại bỏ

Nhập khẩu HTML và mô-đun ES6 đều đã được triển khai tốt trong hầu hết các trình duyệt trên toàn thế giới . Nhưng vì nhập HTML chắc chắn sẽ không phải là một phần của tiêu chuẩn, không giống như các mô-đun ES6, sự phát triển của nó sẽ bị hủy bỏ, sau đó bạn chắc chắn nên bắt đầu sử dụng các mô-đun ES6.

6
Yairopro

Đây là plugin Grunt cho phép bạn sử dụng cú pháp @import "path/to/file.js"; trong bất kỳ tệp nào kể cả các tệp JavaScript. Nó có thể được ghép nối với uglify hoặc xem hoặc bất kỳ plugin nào khác.

Nó có thể được cài đặt với cài đặt npm: https://npmjs.org/package/grunt-import

6
Marcin

Sử dụng tốt hơn jQuery way. Để trì hoãn sự kiện đã sẵn sàng, trước tiên hãy gọi $.holdReady(true). Ví dụ ( nguồn ):

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

Giữ cho nó đẹp, ngắn, đơn giản và có thể bảo trì! :]

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

Mã này chỉ đơn giản là một ví dụ chức năng ngắn mà có thể yêu cầu chức năng tính năng bổ sung để hỗ trợ đầy đủ trên bất kỳ nền tảng (hoặc đã cho) nào.

5
tfont

Về cơ bản tôi làm như sau, tạo một phần tử mới và gắn nó vào phần đầu:

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

Trong jQuery :

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

Chỉ dành cho NodeJS, Điều này làm việc cho tôi tốt nhất!

Tôi đã thử hầu hết các giải pháp ở đây, nhưng không có giải pháp nào giúp tôi về việc có thể tải một tệp khác mà không thay đổi phạm vi. Cuối cùng tôi đã sử dụng cái này. Mà bảo tồn phạm vi và tất cả mọi thứ. Nó là tốt như mã của bạn là ở điểm đó.

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

Nó rất đơn giản. Giả sử bạn muốn nhập tệp A.js trong tệp B.js.

Bây giờ chắc chắn bạn đã liên kết B.js trong tệp HTML, sau đó chỉ liên kết A.js trước B.js trong tệp HTML đó. Sau đó, các biến công khai của A.js sẽ có sẵn bên trong B.js

Điều này không đòi hỏi một câu trả lời phức tạp.

4
Akshay Vijay Jain

Tôi có yêu cầu tải không đồng bộ một mảng các tệp JavaScript và cuối cùng thực hiện gọi lại. Về cơ bản cách tiếp cận tốt nhất của tôi là như sau:

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

Thí dụ:

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

Tập lệnh thứ hai sẽ không tải cho đến khi tập lệnh đầu tiên được tải hoàn toàn, và vì vậy ...

Các kết quả:

 Result

4
MiBol

Nếu bạn sử dụng Angular, thì một mô-đun plugin $ ocLazyLoad có thể giúp bạn làm điều đó. 

Dưới đây là một số trích dẫn từ tài liệu của nó:

Tải một hoặc nhiều mô-đun & thành phần với nhiều tệp:

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

Tải một hoặc nhiều mô-đun với nhiều tệp và chỉ định loại khi cần thiết: Lưu ý: Khi sử dụng định dạng kiểu Yêu cầu (ví dụ với js! Ở đầu), không chỉ định phần mở rộng tệp. Sử dụng cái này hay cái khác.

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

Bạn có thể tải libs bên ngoài (không phải góc cạnh):

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

Bạn cũng có thể tải tập tin css và mẫu:

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

Nhập và xuất các mô-đun bằng ES6 hoạt động với Node.js

Đặt tên tệp với phần mở rộng .mjs thay vì .js

Tạo tập tin

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
}

Chạy

node --experimental-modules main.js
3
jasonleonhard

Bây giờ, tôi có thể hoàn toàn sai lầm, nhưng đây là những gì gần đây tôi đã bắt đầu làm ... Bắt đầu và kết thúc các tệp JavaScript của bạn bằng trả về vận chuyển, đặt vào tập lệnh PHP, tiếp theo là thêm một lần quay lại vận chuyển . Nhận xét JavaScript "//" bị bỏ qua bởi PHP vì vậy việc bao gồm vẫn xảy ra. Mục đích cho việc trả lại vận chuyển là để dòng đầu tiên của JavaScript được bao gồm của bạn không được nhận xét.

Về mặt kỹ thuật, bạn không cần bình luận, nhưng nó đăng lỗi trong Dreamweaver điều đó làm tôi khó chịu. Nếu bạn đang viết kịch bản trong IDE không đăng lỗi, bạn không cần nhận xét hoặc trả lại vận chuyển.

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

function myFunction(){
    // stuff
}
\n
3
Duncan
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)
};
3
Robert A

Đừng quên kiểm tra LAB.js !

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

Trong một dự án trước đây, tôi đã có khá nhiều thành công khi sử dụng ajile để thực hiện nhập các tệp JavaScript có thể sử dụng lại. Tôi luôn mong muốn có một tính năng cho chính điều này được tích hợp vào JavaScript.

3
jpierson

Một cách tiếp cận khác là sử dụng nhập HTML. Chúng có thể chứa các tham chiếu tập lệnh cũng như các tham chiếu biểu định kiểu.

Bạn chỉ có thể liên kết một tệp HTML như

<link rel="import" href="vendorScripts.html"/>

Trong tệp vendorScripts.html, bạn có thể bao gồm các tham chiếu tập lệnh của mình như:

<script src="scripts/vendors/jquery.js"></script>
<script src="scripts/vendors/bootstrap.js"></script>
<script src="scripts/vendors/angular.js"></script>
<script src="scripts/vendors/angular-route.js"></script>

Nhìn vào Nhập khẩu HTML để biết thêm chi tiết.

Thật không may, điều này chỉ hoạt động trong Chrome.

2
gabriel211

Bạn không thể nhập, nhưng bạn có thể tham khảo.

PhpShtorm IDE. Để tham chiếu, trong một tệp .js cho một .js khác, chỉ cần thêm tệp này vào đầu tệp:

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

Tất nhiên, bạn nên sử dụng PATH của riêng mình cho tệp JavaScript.

Tôi không biết nếu nó sẽ hoạt động trong các IDE khác. Có lẽ là có, chỉ cần cố gắng. Nó cũng hoạt động trong Visual Studio.

2

Có, có ...

Hãy tiếp tục đọc, trong ES6, chúng ta có thể exportimport một phần hoặc toàn bộ tệp javascript vào một tệp khác ...

Nhưng chờ đã, ES6 không được hỗ trợ trong tất cả các trình duyệt, vì vậy điều bạn cần là dịch mã bằng cách sử dụng babel.js chẳng hạn ...

Vì vậy, bạn tạo một lớp như dưới đây:

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

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

module.exports = Person;

trong tệp JavaScript khác, thực hiện nhập như sau:

import { Person } from 'Person';

Bạn cũng có thể yêu cầu tệp như:

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

Nếu bạn đang sử dụng phiên bản JavaScript cũ hơn, bạn có thể sử dụng quiries:

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

Nếu bạn muốn sử dụng phiên bản cũ hơn của các công cụ, như jQuery, bạn cũng có thể sử dụng một cái gì đó như getScript:

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

Cuối cùng nhưng không kém phần quan trọng, đừng quên bạn có thể thực hiện cách đặt tập lệnh truyền thống với nhau bằng cách sử dụng thẻ <script> ...

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

Ngoài ra còn có thuộc tính asyncdefer mà tôi nên đề cập đến ở đây ...

Lưu ý: Có một số cách mà tập lệnh bên ngoài có thể được thực thi:

  • Nếu không đồng bộ: Tập lệnh được thực thi không đồng bộ với phần còn lại của trang (tập lệnh sẽ được thực thi trong khi trang tiếp tục phân tích cú pháp)
  • Nếu async không có và defer là hiện tại: Kịch bản được thực thi khi trang kết thúc phân tích cú pháp
  • Nếu không có async hoặc defer nào xuất hiện: Kịch bản là đã tải xuống và thực thi ngay lập tức, trước khi trình duyệt tiếp tục phân tích trang
2
Alireza

Đây có thể là một cách khác! Trong Node.js bạn làm điều đó giống như sau! 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();
2
xgqfrms

Tôi đã thử vấn đề này với một cách tiếp cận khác,

Đặt hàng nhập kịch bản, không có hiệu lực ở đây.

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

kết quả

From    AAAAA
From    BBBBB
Hello
1
Milton Ain

ES6: CÓ sử dụng loại = "mô-đun" trong thẻ tập lệnh ( hỗ trợ )

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

Và trong tệp script.js bao gồm một tệp khác như thế:

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

Trong 'module.js', bạn phải xuất hàm/lớp mà bạn sẽ nhập

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

Làm việc ví dụ ở đây .

1
Kamil Kiełczewski

Nếu bạn thấy có 2 hoặc nhiều tập lệnh chiếm cùng chức năng khi chúng được gọi, thì chúng ta không thể đưa chúng vào cùng một lúc, chúng ta cần thực hiện động bằng cách chọn người dùng.

Bao gồm các tệp khác trong jQuery bằng cách sử dụng $.getScript hoạt động do tập lệnh sẽ không được lưu trong bộ đệm theo mặc định . Vì vậy, chúng tôi đang lưu để gọi các kịch bản khác. Các cuộc gọi có thể được sắp xếp như thế này:

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

Little Extend to lib từ answer @Dan Dascalescu lấy từ ý tưởng facebook.

(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';
}));
0
Kamil Dąbrowski

Xin lưu ý rằng chúng tôi thường sử dụng tập lệnh tĩnh . Vì vậy, chúng tôi muốn được lấy từ cache càng nhiều càng tốt . Điều này giúp tiết kiệm lưu lượng mạng và tăng tốc độ hạ cánh.

Sử dụng

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

cache: true tùy chọn đã được thêm vào phương thức ajax

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

hoặc là

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
0
Mesut Yiğit

Bạn có thể sử dụng mô đun ES loadScript ES của tôi để tải các tệp javaScript.

Sử dụng:

Trong thẻ đầu của bạn, bao gồm mã sau đây:

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

hoặc là

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

Bây giờ bạn có thể sử dụng window.loadScript để tải các tệp JavaScript của mình.

loadScript.async (src, [tùy chọn])

Tải tệp JavaScript không đồng bộ.

src: URL của tệp tập lệnh bên ngoài hoặc mảng của tên tệp tập lệnh.

tùy chọn: tùy chọn theo sau có sẵn

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.

Ví dụ

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

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

            },
            onerror: function ( str, e ) {

                console.error( str );

            },

        } );

Ví dụ về cách sử dụng

0
Andrej

Tự động tải nhiều tập lệnh theo thứ tự

Hàm trên hoạt động tốt nếu bạn chỉ tải một tập lệnh hoặc bạn không quan tâm đến thứ tự tải của nhiều tập lệnh. Nếu bạn có một số tập lệnh phụ thuộc vào người khác, bạn cần sử dụng Promise để chỉ định thứ tự tải. Lý do đằng sau điều này là Javascript tải các tài nguyên như tập lệnh và hình ảnh không đồng bộ. Trình tự tải không phụ thuộc vào chuỗi các cuộc gọi không đồng bộ, có nghĩa là script1 sẽ không được đảm bảo tải trước script2 ngay cả khi bạn gọi dynamicallyLoadScript("scrip1") trước khi gọi dynamicallyLoadScript("scrip2")

Vì vậy, đây là một phiên bản khác của DynamicivelyLoadScript đảm bảo thứ tự tải:

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

Để biết thêm về Lời hứa, hãy xem trang tuyệt vời này .

Việc sử dụng tính năng động mớiLoadScript này rất đơn giản:

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

Bây giờ các tập lệnh được tải theo thứ tự script1.js, script2.js, script3.js, v.v.

Chạy mã phụ thuộc sau khi tải tập lệnh

Ngoài ra, bạn có thể chạy ngay mã sử dụng các tập lệnh sau khi chúng được tải. Chỉ cần thêm .then khác sau khi tải tập lệnh:

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

Xử lý lỗi tải

Để hiển thị các từ chối lời hứa chưa được xử lý (lỗi tải tập lệnh, v.v.), hãy đặt trình nghe sự kiện unhandledrejection này ở đầu mã của bạn:

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

Bây giờ bạn sẽ được thông báo về bất kỳ lỗi tải tập lệnh.


Chức năng phím tắt

Nếu bạn đang tải rất nhiều tập lệnh mà không thực thi mã ngay sau khi tải, chức năng tốc ký này có thể có ích:

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

Để sử dụng nó, chỉ cần chuyển vào một mảng các url script như thế này:

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

Các tập lệnh sẽ được tải theo thứ tự chúng xuất hiện trong mảng.

0
AlienKevin