Hướng dẫn should i use modules in javascript? - tôi có nên sử dụng các mô-đun trong javascript không?

  • " Trước

Hướng dẫn này cung cấp cho bạn tất cả những gì bạn cần để bắt đầu với cú pháp mô -đun JavaScript.

Một nền tảng về các mô -đun

Các chương trình JavaScript bắt đầu khá nhỏ - hầu hết việc sử dụng trong những ngày đầu là thực hiện các tác vụ kịch bản bị cô lập, cung cấp một chút tương tác với các trang web của bạn khi cần thiết, vì vậy các tập lệnh lớn thường không cần thiết. Nhanh chóng chuyển tiếp một vài năm và giờ đây chúng tôi có các ứng dụng hoàn chỉnh được chạy trong các trình duyệt với rất nhiều JavaScript, cũng như JavaScript được sử dụng trong các bối cảnh khác (ví dụ Node.js).

Do đó, nó đã có ý nghĩa trong những năm gần đây để bắt đầu suy nghĩ về việc cung cấp các cơ chế để chia các chương trình JavaScript thành các mô -đun riêng biệt có thể được nhập khi cần thiết. Node.js đã có khả năng này trong một thời gian dài, và có một số thư viện và khung JavaScript cho phép sử dụng mô-đun (ví dụ: các hệ thống mô-đun chung và AMD khác như RequestJS, và gần đây là Webpack và Babel).

Tin tốt là các trình duyệt hiện đại đã bắt đầu hỗ trợ chức năng mô -đun tự nhiên, và đây là những gì bài viết này là tất cả về. Đây chỉ có thể là một điều tốt-trình duyệt có thể tối ưu hóa việc tải các mô-đun, làm cho nó hiệu quả hơn so với việc phải sử dụng thư viện và thực hiện tất cả các chuyến đi thêm phía máy khách và các chuyến đi tròn thêm.

Việc sử dụng các mô -đun JavaScript bản địa phụ thuộc vào các câu lệnh

/js-examples/module-examples/basic-modules/modules/square.js
4 và
/js-examples/module-examples/basic-modules/modules/square.js
5; Chúng được hỗ trợ trong các trình duyệt như trong bảng tương thích bên dưới.

Tính tương thích của trình duyệt web

javascript.statements.import

Bảng BCD chỉ tải trong trình duyệt

javascript.statements.export

Bảng BCD chỉ tải trong trình duyệt

Giới thiệu một ví dụ

Để chứng minh việc sử dụng các mô -đun, chúng tôi đã tạo ra một tập hợp các ví dụ đơn giản mà bạn có thể tìm thấy trên GitHub. Các ví dụ này cho thấy một tập hợp các mô -đun đơn giản tạo ra một phần tử

/js-examples/module-examples/basic-modules/modules/square.js
6 trên trang web, sau đó vẽ (và báo cáo thông tin về) các hình dạng khác nhau trên khung vẽ.

Đây là những điều khá tầm thường, nhưng đã được giữ một cách có chủ ý đơn giản để chứng minh các mô -đun rõ ràng.

Lưu ý: Nếu bạn muốn tải xuống các ví dụ và chạy chúng cục bộ, bạn sẽ cần chạy chúng thông qua một máy chủ web cục bộ. If you want to download the examples and run them locally, you'll need to run them through a local web server.

Cấu trúc ví dụ cơ bản

Trong ví dụ đầu tiên của chúng tôi (xem các mô-đun cơ bản), chúng tôi có cấu trúc tệp như sau:

index.html
main.js
modules/
    canvas.js
    square.js

Lưu ý: Tất cả các ví dụ trong hướng dẫn này về cơ bản có cùng một cấu trúc; Trên đây sẽ bắt đầu trở nên khá quen thuộc. All of the examples in this guide have basically the same structure; the above should start getting pretty familiar.

Hai mô -đun của thư mục mô -đun được mô tả dưới đây:

  • /js-examples/module-examples/basic-modules/modules/square.js
    
    7 - Chứa các chức năng liên quan đến việc thiết lập Canvas:
    • /js-examples/module-examples/basic-modules/modules/square.js
      
      8 - Tạo một khung vẽ với một
      /js-examples/module-examples/basic-modules/modules/square.js
      
      9 và
      const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      0 được chỉ định bên trong một trình bao bọc
      const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      1 với một ID được chỉ định, tự nó được thêm vào bên trong một phần tử cha được chỉ định. Trả về một đối tượng chứa bối cảnh 2D của Canvas và ID của trình bao bọc.
    • const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      2 - Tạo một danh sách không được đặt hàng được thêm vào bên trong một phần tử trình bao bọc được chỉ định, có thể được sử dụng để xuất dữ liệu báo cáo vào. Trả về ID của danh sách.
  • const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    3 - chứa:
    • const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      4 - Một hằng số chứa chuỗi 'hình vuông'.
    • const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      5 - Vẽ một hình vuông trên một tấm bạt được chỉ định, với kích thước, vị trí và màu sắc được chỉ định. Trả về một đối tượng chứa kích thước, vị trí và màu của hình vuông.
    • const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      6 - Viết khu vực của một hình vuông vào một danh sách báo cáo cụ thể, với độ dài của nó.
    • const myCanvas = create('myCanvas', document.body, 480, 320);
      const reportList = createReportList(myCanvas.id);
      
      const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
      reportArea(square1.length, reportList);
      reportPerimeter(square1.length, reportList);
      
      7 - Viết chu vi của một hình vuông vào một danh sách báo cáo cụ thể, với độ dài của nó.

Sang một bên - .mjs so với .js

Trong suốt bài viết này, chúng tôi đã sử dụng các tiện ích mở rộng

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8 cho các tệp mô -đun của chúng tôi, nhưng trong các tài nguyên khác, bạn có thể thấy tiện ích mở rộng
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9 được sử dụng thay thế. Tài liệu của V8 khuyến nghị điều này, ví dụ. Những lý do được đưa ra là:

  • Nó tốt cho sự rõ ràng, tức là nó làm rõ các tệp nào là mô -đun và cái nào là JavaScript thông thường.
  • Nó đảm bảo rằng các tệp mô -đun của bạn được phân tích cú pháp như một mô -đun bởi RunTimes như Node.js và các công cụ xây dựng như Babel.

Tuy nhiên, chúng tôi quyết định tiếp tục sử dụng

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8, ít nhất là trong thời điểm này. Để có được các mô -đun hoạt động chính xác trong trình duyệt, bạn cần đảm bảo rằng máy chủ của bạn đang phục vụ chúng với tiêu đề
<script type="module" src="main.js">script>
1 có chứa loại MIME JavaScript như
<script type="module" src="main.js">script>
2. Nếu bạn không, bạn sẽ nhận được lỗi kiểm tra loại mime nghiêm ngặt dọc theo các dòng "máy chủ được trả lời bằng loại MIME không phải là JavaScript" và trình duyệt sẽ không chạy JavaScript của bạn. Hầu hết các máy chủ đã đặt đúng loại cho các tệp
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8, nhưng chưa cho các tệp
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9. Các máy chủ đã phục vụ các tệp
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9 một cách chính xác bao gồm các trang GitHub và
<script type="module" src="main.js">script>
6 cho Node.js.

Điều này là OK nếu bạn đang sử dụng một môi trường như vậy hoặc nếu bạn không nhưng bạn biết bạn đang làm gì và có quyền truy cập (tức là bạn có thể định cấu hình máy chủ của mình để đặt đúng

<script type="module" src="main.js">script>
1 cho các tệp
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9). Tuy nhiên, nó có thể gây ra sự nhầm lẫn nếu bạn không kiểm soát máy chủ mà bạn đang phục vụ các tệp hoặc đang xuất bản các tệp để sử dụng công cộng, như chúng tôi đang ở đây.

Đối với mục đích học tập và tính di động, chúng tôi quyết định giữ

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8.

Nếu bạn thực sự đánh giá sự rõ ràng của việc sử dụng

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9 cho các mô -đun so với sử dụng
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8 cho các tệp JavaScript "bình thường", nhưng không muốn gặp sự cố được mô tả ở trên, bạn luôn có thể sử dụng
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
9 trong quá trình phát triển và chuyển đổi chúng thành
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
8 trong bước xây dựng của bạn .

Nó cũng đáng chú ý rằng:

  • Một số công cụ có thể không bao giờ hỗ trợ
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9.
  • Thuộc tính
    <script type="module">
      /* JavaScript module code here */
    script>
    
    5 được sử dụng để biểu thị khi một mô -đun được chỉ ra, như bạn sẽ thấy bên dưới.

Xuất các tính năng mô -đun

Điều đầu tiên bạn làm để có quyền truy cập vào các tính năng mô -đun là xuất chúng. Điều này được thực hiện bằng cách sử dụng câu lệnh

/js-examples/module-examples/basic-modules/modules/square.js
5.

Cách dễ nhất để sử dụng nó là đặt nó trước bất kỳ mục nào bạn muốn xuất ra khỏi mô -đun, ví dụ:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}

Bạn có thể xuất các chức năng,

<script type="module">
  /* JavaScript module code here */
script>
7,
<script type="module">
  /* JavaScript module code here */
script>
8,
<script type="module">
  /* JavaScript module code here */
script>
9 và - như chúng ta sẽ thấy sau - các lớp. Họ cần phải là các mặt hàng cấp cao nhất; Ví dụ, bạn không thể sử dụng
/js-examples/module-examples/basic-modules/modules/square.js
5 bên trong một hàm.

Một cách thuận tiện hơn để xuất tất cả các mục bạn muốn xuất là sử dụng một tuyên bố xuất duy nhất ở cuối tệp mô-đun của bạn, sau đó là một danh sách được phân tách bằng dấu phẩy các tính năng bạn muốn xuất được gói trong niềng răng xoăn. Ví dụ:

export { name, draw, reportArea, reportPerimeter };

Nhập các tính năng vào tập lệnh của bạn

Khi bạn đã xuất một số tính năng ra khỏi mô -đun của mình, bạn cần nhập chúng vào tập lệnh của mình để có thể sử dụng chúng. Cách đơn giản nhất để làm điều này như sau:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';

Bạn sử dụng câu lệnh

/js-examples/module-examples/basic-modules/modules/square.js
4, theo sau là danh sách phân tách bằng dấu phẩy các tính năng bạn muốn nhập được bọc trong niềng răng xoăn, theo sau là từ khóa
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
2, theo sau là đường dẫn đến tệp mô-đun-một đường dẫn liên quan đến root trang web, cho Ví dụ
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
3 của chúng tôi sẽ là
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
4.

Tuy nhiên, chúng tôi đã viết đường dẫn khác một chút - chúng tôi đang sử dụng cú pháp DOT (

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
5) có nghĩa là "vị trí hiện tại", theo sau là đường dẫn vượt ra ngoài tệp mà chúng tôi đang cố gắng tìm. Điều này tốt hơn nhiều so với việc viết ra toàn bộ đường dẫn tương đối mỗi lần, vì nó ngắn hơn và nó làm cho URL di động - ví dụ vẫn sẽ hoạt động nếu bạn di chuyển nó đến một vị trí khác trong hệ thống phân cấp trang web.

Ví dụ:

/js-examples/module-examples/basic-modules/modules/square.js

trở thành

Bạn có thể thấy những dòng như vậy trong hành động trong

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6.

Lưu ý: Trong một số hệ thống mô -đun, bạn có thể bỏ qua phần mở rộng tệp và hàng đầu

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
7,
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
8 hoặc
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
9 (ví dụ:
/* render.js */
document.getElementById("main").innerText = text;
0). Điều này không hoạt động trong môi trường trình duyệt, vì điều đó có thể dẫn đến nhiều vòng tròn mạng.
In some module systems, you can omit the file extension and the leading
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
7,
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
8, or
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
9 (e.g.
/* render.js */
document.getElementById("main").innerText = text;
0). This doesn't work in the browser environment, as that can lead to multiple network roundtrips.

Khi bạn đã nhập các tính năng vào tập lệnh của mình, bạn có thể sử dụng chúng giống như chúng được xác định bên trong cùng một tệp. Sau đây được tìm thấy trong

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, bên dưới các dòng nhập khẩu:

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);

Lưu ý: Mặc dù các tính năng đã nhập có sẵn trong tệp, nhưng chúng chỉ đọc các chế độ xem của tính năng được xuất. Bạn không thể thay đổi biến đã được nhập, nhưng bạn vẫn có thể sửa đổi các thuộc tính tương tự như

<script type="module">
  /* JavaScript module code here */
script>
9. Ngoài ra, các tính năng này được nhập dưới dạng ràng buộc trực tiếp, có nghĩa là chúng có thể thay đổi giá trị ngay cả khi bạn không thể sửa đổi ràng buộc không giống như
<script type="module">
  /* JavaScript module code here */
script>
9.
Although imported features are available in the file, they are read only views of the feature that was exported. You cannot change the variable that was imported, but you can still modify properties similar to
<script type="module">
  /* JavaScript module code here */
script>
9. Additionally, these features are imported as live bindings, meaning that they can change in value even if you cannot modify the binding unlike
<script type="module">
  /* JavaScript module code here */
script>
9.

Áp dụng mô -đun cho HTML của bạn

Bây giờ chúng tôi chỉ cần áp dụng mô -đun

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6 cho trang HTML của chúng tôi. Điều này rất giống với cách chúng tôi áp dụng tập lệnh thông thường vào một trang, với một vài khác biệt đáng chú ý.

Trước hết, bạn cần đưa

/* render.js */
document.getElementById("main").innerText = text;
5 vào phần tử
/* render.js */
document.getElementById("main").innerText = text;
6, để khai báo tập lệnh này dưới dạng mô -đun. Để nhập tập lệnh
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, chúng tôi sử dụng điều này:

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

Bạn cũng có thể nhúng tập lệnh của mô -đun trực tiếp vào tệp HTML bằng cách đặt mã JavaScript trong phần thân của phần tử

/* render.js */
document.getElementById("main").innerText = text;
6:

<script type="module">
  /* JavaScript module code here */
script>

Tập lệnh mà bạn nhập các tính năng mô-đun về cơ bản đóng vai trò là mô-đun cấp cao nhất. Nếu bạn bỏ qua nó, ví dụ, Firefox cung cấp cho bạn một lỗi của "Cú pháp: Nhập khai báo khai chỉ có thể xuất hiện ở cấp cao nhất của một mô -đun".

Bạn chỉ có thể sử dụng các câu lệnh

/js-examples/module-examples/basic-modules/modules/square.js
4 và
/js-examples/module-examples/basic-modules/modules/square.js
5 bên trong các mô -đun, không phải các tập lệnh thông thường.

Sự khác biệt khác giữa các mô -đun và tập lệnh tiêu chuẩn

  • Bạn cần chú ý đến thử nghiệm cục bộ - nếu bạn cố gắng tải tệp HTML cục bộ (tức là với URL
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    01), bạn sẽ gặp lỗi CORS do các yêu cầu bảo mật mô -đun JavaScript. Bạn cần thực hiện thử nghiệm của bạn thông qua một máy chủ.
  • Ngoài ra, lưu ý rằng bạn có thể nhận được các hành vi khác với các phần của tập lệnh được xác định bên trong các mô -đun trái ngược với các tập lệnh tiêu chuẩn. Điều này là do các mô -đun sử dụng chế độ nghiêm ngặt tự động.
  • Không cần phải sử dụng thuộc tính
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    02 (xem
    /* render.js */
    document.getElementById("main").innerText = text;
    
    6 thuộc tính) khi tải tập lệnh mô -đun; Các mô -đun được hoãn lại tự động.
  • Các mô -đun chỉ được thực hiện một lần, ngay cả khi chúng đã được tham chiếu trong nhiều thẻ
    /* render.js */
    document.getElementById("main").innerText = text;
    
    6.
  • Cuối cùng nhưng không kém phần quan trọng, chúng ta hãy làm rõ điều này - các tính năng mô -đun được nhập vào phạm vi của một tập lệnh duy nhất - chúng không có sẵn trong phạm vi toàn cầu. Do đó, bạn sẽ chỉ có thể truy cập các tính năng đã nhập trong tập lệnh mà chúng được nhập vào và bạn sẽ không thể truy cập chúng từ bảng điều khiển JavaScript, chẳng hạn. Bạn vẫn sẽ nhận được các lỗi cú pháp được hiển thị trong DevTools, nhưng bạn sẽ không thể sử dụng một số kỹ thuật gỡ lỗi mà bạn có thể dự kiến ​​sẽ sử dụng.

Các biến được xác định bởi mô-đun được xác định theo mô-đun trừ khi được gắn rõ ràng vào đối tượng toàn cầu. Mặt khác, các biến được xác định trên toàn cầu có sẵn trong mô-đun. Ví dụ: với mã sau:

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>

/* render.js */
document.getElementById("main").innerText = text;

Trang vẫn sẽ hiển thị

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
05, bởi vì các biến toàn cầu
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
06 và
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
07 có sẵn trong mô -đun. .

Xuất xuất mặc định so với xuất khẩu được đặt tên

Chức năng mà chúng tôi đã xuất cho đến nay bao gồm các lần xuất được đặt tên - mỗi mặt hàng (có thể là một hàm,

<script type="module">
  /* JavaScript module code here */
script>
9, v.v.) đã được gọi bằng tên của nó khi xuất khẩu và tên đó đã được sử dụng cũng.named exports — each item (be it a function,
<script type="module">
  /* JavaScript module code here */
script>
9, etc.) has been referred to by its name upon export, and that name has been used to refer to it on import as well.

Ngoài ra còn có một loại xuất khẩu được gọi là xuất khẩu mặc định - điều này được thiết kế để dễ dàng có chức năng mặc định được cung cấp bởi một mô -đun và cũng giúp các mô -đun JavaScript tương tác với các hệ thống mô -đun AMD và AMD hiện có (như được giải thích độc đáo trong ES6 trong Độ sâu: Mô -đun của Jason Orendorff; tìm kiếm "Xuất mặc định").default export — this is designed to make it easy to have a default function provided by a module, and also helps JavaScript modules to interoperate with existing CommonJS and AMD module systems (as explained nicely in ES6 In Depth: Modules by Jason Orendorff; search for "Default exports").

Hãy xem xét một ví dụ khi chúng tôi giải thích cách thức hoạt động của nó. Trong các mô-đun cơ bản của chúng tôi

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
3, bạn có thể tìm thấy một hàm gọi là
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
11 tạo ra một hình vuông với màu, kích thước và vị trí ngẫu nhiên. Chúng tôi muốn xuất cái này dưới dạng mặc định của chúng tôi, vì vậy ở cuối tệp chúng tôi viết này:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
0

Lưu ý việc thiếu niềng răng xoăn.

Thay vào đó, chúng tôi có thể dự phòng

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
12 vào chức năng và định nghĩa nó là một hàm ẩn danh, như thế này:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
1

Trong tệp

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6 của chúng tôi, chúng tôi nhập chức năng mặc định bằng dòng này:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
2

Một lần nữa, lưu ý việc thiếu niềng răng xoăn. Điều này là do chỉ có một xuất khẩu mặc định được phép cho mỗi mô -đun và chúng tôi biết rằng

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
14 là nó. Dòng trên về cơ bản là tốc ký cho:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
3

Tránh đặt tên xung đột

Cho đến nay, các mô -đun vẽ hình dạng vải của chúng tôi dường như đang hoạt động tốt. Nhưng điều gì xảy ra nếu chúng ta cố gắng thêm một mô -đun liên quan đến việc vẽ một hình dạng khác, như một vòng tròn hoặc hình tam giác? Những hình dạng này có thể sẽ có các chức năng liên quan như

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
5,
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
6, v.v. Nếu chúng tôi cố gắng nhập các chức năng khác nhau của cùng một tên vào cùng một tệp mô-đun cấp cao nhất, chúng tôi sẽ kết thúc với các xung đột và lỗi.

May mắn thay, có một số cách để có được xung quanh này. Chúng tôi sẽ xem xét những điều này trong các phần sau.

Đổi tên nhập khẩu và xuất khẩu

Bên trong niềng xoăn

/js-examples/module-examples/basic-modules/modules/square.js
4 và
/js-examples/module-examples/basic-modules/modules/square.js
5 của bạn, bạn có thể sử dụng từ khóa
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
19 cùng với tên tính năng mới, để thay đổi tên nhận dạng bạn sẽ sử dụng cho một tính năng bên trong mô-đun cấp cao nhất.

Vì vậy, ví dụ, cả hai điều sau đây sẽ làm cùng một công việc, mặc dù theo một cách hơi khác:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
4

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
5

Hãy xem xét một ví dụ thực tế. Trong thư mục đổi tên của chúng tôi, bạn sẽ thấy cùng một hệ thống mô -đun như trong ví dụ trước, ngoại trừ việc chúng tôi đã thêm các mô -đun

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
20 và
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
21 để vẽ và báo cáo về các vòng tròn và hình tam giác.

Bên trong mỗi mô -đun này, chúng tôi có các tính năng có cùng tên được xuất, và do đó, mỗi mô -đun có cùng một câu lệnh

/js-examples/module-examples/basic-modules/modules/square.js
5 ở phía dưới:

export { name, draw, reportArea, reportPerimeter };

Khi nhập chúng vào

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, nếu chúng tôi cố gắng sử dụng

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
7

Trình duyệt sẽ đưa ra một lỗi như "Cú pháp: REDECLATION của tên nhập" (Firefox).

Thay vào đó, chúng ta cần đổi tên nhập khẩu để chúng là duy nhất:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
8

Lưu ý rằng bạn có thể giải quyết vấn đề trong các tệp mô -đun thay thế, ví dụ:

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
9

export { name, draw, reportArea, reportPerimeter };
0

Và nó sẽ hoạt động giống nhau. Phong cách bạn sử dụng là tùy thuộc vào bạn, tuy nhiên có thể có ý nghĩa hơn khi để mã mô -đun của bạn một mình và thực hiện các thay đổi trong nhập khẩu. Điều này đặc biệt có ý nghĩa khi bạn đang nhập từ các mô -đun bên thứ ba mà bạn không có quyền kiểm soát.

Tạo một đối tượng mô -đun

Phương pháp trên hoạt động tốt, nhưng nó hơi lộn xộn và dài dòng. Một giải pháp thậm chí còn tốt hơn là nhập các tính năng của mỗi mô -đun bên trong một đối tượng mô -đun. Mẫu cú pháp sau đây làm điều đó:

export { name, draw, reportArea, reportPerimeter };
1

Điều này lấy tất cả các xuất khẩu có sẵn bên trong

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
24 và làm cho chúng có sẵn với tư cách là thành viên của một đối tượng
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
25, thực sự cung cấp cho nó không gian tên của riêng mình. Ví dụ:

export { name, draw, reportArea, reportPerimeter };
2

Một lần nữa, chúng ta hãy nhìn vào một ví dụ thực tế. Nếu bạn truy cập thư mục đối tượng mô-đun của chúng tôi, bạn sẽ thấy một ví dụ tương tự một lần nữa, nhưng viết lại để tận dụng cú pháp mới này. Trong các mô -đun, xuất khẩu đều ở dạng đơn giản sau:

export { name, draw, reportArea, reportPerimeter };

Mặt khác, nhập khẩu trông như thế này:

export { name, draw, reportArea, reportPerimeter };
4

Trong mỗi trường hợp, bây giờ bạn có thể truy cập các bản nhập của mô -đun bên dưới tên đối tượng được chỉ định, ví dụ:

export { name, draw, reportArea, reportPerimeter };
5

Vì vậy, bây giờ bạn có thể viết mã giống như trước đây (miễn là bạn bao gồm các tên đối tượng khi cần) và nhập khẩu là nhiều gọn gàng hơn.

Các mô -đun và các lớp

Như chúng tôi đã gợi ý trước đó, bạn cũng có thể xuất và nhập các lớp; Đây là một tùy chọn khác để tránh xung đột trong mã của bạn và đặc biệt hữu ích nếu bạn đã có mã mô-đun được viết theo kiểu hướng đối tượng.

Bạn có thể thấy một ví dụ về mô -đun vẽ hình dạng của chúng tôi được viết lại với các lớp ES trong thư mục lớp của chúng tôi. Ví dụ, tệp

const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
3 hiện chứa tất cả các chức năng của nó trong một lớp duy nhất:

export { name, draw, reportArea, reportPerimeter };
6

mà sau đó chúng ta xuất khẩu:

Trong

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, chúng tôi nhập nó như thế này:

export { name, draw, reportArea, reportPerimeter };
7

Và sau đó sử dụng lớp để vẽ hình vuông của chúng tôi:

export { name, draw, reportArea, reportPerimeter };
8

Các mô -đun tổng hợp

Sẽ có những lúc bạn sẽ muốn tổng hợp các mô -đun cùng nhau. Bạn có thể có nhiều cấp độ phụ thuộc, nơi bạn muốn đơn giản hóa mọi thứ, kết hợp một số mô -đun con vào một mô -đun cha. Điều này là có thể bằng cách sử dụng cú pháp xuất của các biểu mẫu sau trong mô -đun cha:

export { name, draw, reportArea, reportPerimeter };
9

Ví dụ, xem thư mục tổng hợp mô-đun của chúng tôi. Trong ví dụ này (dựa trên ví dụ về lớp trước của chúng tôi), chúng tôi đã có một mô -đun bổ sung có tên là

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
28, tổng hợp tất cả các chức năng từ
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
20,
const myCanvas = create('myCanvas', document.body, 480, 320);
const reportList = createReportList(myCanvas.id);

const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
reportArea(square1.length, reportList);
reportPerimeter(square1.length, reportList);
3 và
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
21 cùng nhau. Chúng tôi cũng đã di chuyển các mô hình con của chúng tôi bên trong một thư mục con bên trong thư mục
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
32 được gọi là
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
33. Vì vậy, cấu trúc mô -đun trong ví dụ này là:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
0

Trong mỗi mô hình con, xuất khẩu có cùng dạng, ví dụ:

Tiếp theo là phần tổng hợp. Bên trong

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
28, chúng tôi bao gồm các dòng sau:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
1

Chúng lấy các lần xuất từ ​​các mô hình con riêng lẻ và hiệu quả chúng có sẵn từ mô -đun

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
28.

Lưu ý: Các lần xuất được tham chiếu trong

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
28 về cơ bản được chuyển hướng qua tệp và không thực sự tồn tại ở đó, vì vậy bạn sẽ không thể viết bất kỳ mã liên quan hữu ích nào trong cùng một tệp. The exports referenced in
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
28 basically get redirected through the file and don't really exist there, so you won't be able to write any useful related code inside the same file.

Vì vậy, bây giờ trong tệp

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, chúng ta có thể truy cập vào cả ba lớp mô -đun bằng cách thay thế

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
2

với dòng đơn sau:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
3

Tải mô -đun động

Một bổ sung gần đây vào chức năng mô -đun JavaScript là tải mô -đun động. Điều này cho phép bạn tự động tải các mô -đun khi chúng cần thiết, thay vì phải tải mọi thứ lên phía trước. Điều này có một số lợi thế hiệu suất rõ ràng; Hãy đọc tiếp và xem nó hoạt động như thế nào.

Chức năng mới này cho phép bạn gọi

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
38 là một hàm, chuyển nó đường dẫn đến mô -đun dưới dạng tham số. Nó trả về một
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
39, đáp ứng với một đối tượng mô -đun (xem tạo một đối tượng mô -đun) cho phép bạn truy cập vào xuất của đối tượng đó. Ví dụ:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
4

Hãy xem xét một ví dụ. Trong thư mục mô-đun động-mô-đun động, chúng tôi đã có một ví dụ khác dựa trên ví dụ về các lớp của chúng tôi. Tuy nhiên, lần này chúng tôi không vẽ bất cứ thứ gì trên vải khi tải ví dụ. Thay vào đó, chúng tôi bao gồm ba nút - "Circle", "Square" và "Tam giác" - khi được nhấn, tự động tải mô -đun yêu cầu và sau đó sử dụng nó để vẽ hình dạng liên quan.

Trong ví dụ này, chúng tôi chỉ thực hiện các thay đổi đối với các tệp

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
40 và
DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6 của chúng tôi - các mô -đun xuất vẫn giống như trước đây.

Trong

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6, chúng tôi đã lấy một tham chiếu đến mỗi nút bằng cách sử dụng cuộc gọi
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
43, ví dụ:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
5

Sau đó, chúng tôi gắn một trình nghe sự kiện vào mỗi nút để khi nhấn, mô -đun có liên quan được tải động và sử dụng để vẽ hình dạng:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
6

Lưu ý rằng, vì việc thực hiện lời hứa trả về một đối tượng mô -đun, nên lớp sau đó được tạo thành một phân chia của đối tượng, do đó chúng ta cần truy cập vào hàm tạo với

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
44 được chuẩn bị cho nó, ví dụ:
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
45.

Một lợi thế khác của nhập khẩu động là chúng luôn có sẵn, ngay cả trong môi trường tập lệnh. Do đó, nếu bạn có thẻ

/* render.js */
document.getElementById("main").innerText = text;
6 hiện có trong HTML không có
/* render.js */
document.getElementById("main").innerText = text;
5, bạn vẫn có thể sử dụng lại mã được phân phối dưới dạng các mô -đun bằng cách nhập động.

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
7

Cấp cao nhất đang chờ đợi

Cấp cao nhất đang chờ đợi là một tính năng có sẵn trong các mô -đun. Điều này có nghĩa là từ khóa

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
48 có thể được sử dụng. Nó cho phép các mô -đun hoạt động như các hàm không đồng bộ lớn có thể được đánh giá trước khi sử dụng trong các mô -đun cha, nhưng không chặn các mô -đun anh chị em không tải.

Chúng ta hãy xem một ví dụ. Bạn có thể tìm thấy tất cả các tệp và mã được mô tả trong phần này trong thư mục

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
49, mở rộng từ các ví dụ trước.

Đầu tiên chúng tôi sẽ khai báo bảng màu của chúng tôi trong một tệp

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
50 riêng biệt:

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
8

Sau đó, chúng tôi sẽ tạo một mô -đun có tên

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
51 sử dụng yêu cầu tìm nạp để tải tệp
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
50 và trả về dữ liệu dưới dạng đối tượng.

import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
9

Lưu ý dòng xuất khẩu cuối cùng ở đây.

Chúng tôi đang sử dụng từ khóa

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
48 trước khi chỉ định hằng số
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
54 để xuất. Điều này có nghĩa là bất kỳ mô -đun nào khác bao gồm mô -đun này sẽ đợi cho đến khi
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
54 đã được tải xuống và phân tích cú pháp trước khi sử dụng nó.

Hãy đưa mô -đun này vào tệp

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6 của chúng tôi:

/js-examples/module-examples/basic-modules/modules/square.js
0

Chúng tôi sẽ sử dụng

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
54 thay vì các chuỗi được sử dụng trước đó khi gọi các hàm hình dạng của chúng tôi:

/js-examples/module-examples/basic-modules/modules/square.js
1

Điều này rất hữu ích vì mã trong

DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>title>
    <link rel="stylesheet" href="" />
  head>
  <body>
    <div id="main">div>
    <script>
      // A var statement creates a global variable.
      var text = "Hello";
    script>
    <script type="module" src="./render.js">script>
  body>
html>
6 sẽ không thực thi cho đến khi mã trong
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
51 đã chạy. Tuy nhiên, nó sẽ không chặn các mô -đun khác được tải. Chẳng hạn, mô -đun
/js-examples/module-examples/basic-modules/modules/square.js
7 của chúng tôi sẽ tiếp tục tải trong khi
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
54 đang được tìm nạp.

Việc giới thiệu các mô -đun khuyến khích hệ sinh thái JavaScript phân phối và tái sử dụng mã theo kiểu mô -đun. Tuy nhiên, điều đó không nhất thiết có nghĩa là một đoạn mã JavaScript có thể chạy trong mọi môi trường. Giả sử bạn đã phát hiện ra một mô -đun tạo ra các băm SHA của mật khẩu người dùng của bạn. Bạn có thể sử dụng nó ở mặt trước của trình duyệt không? Bạn có thể sử dụng nó trên máy chủ Node.js của bạn không? Câu trả lơi con phụ thuộc vao nhiêu thư.

Các mô -đun vẫn có quyền truy cập vào các biến toàn cầu, như đã được chứng minh trước đây. Nếu mô -đun tham chiếu toàn cầu như

export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
62, nó có thể chạy trong trình duyệt, nhưng sẽ gây ra lỗi trong máy chủ Node.js của bạn, vì
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
62 không có sẵn ở đó. Tương tự, nếu mã yêu cầu quyền truy cập vào
export const name = 'square';

export function draw(ctx, length, x, y, color) {
  ctx.fillStyle = color;
  ctx.fillRect(x, y, length, length);

  return { length, x, y, color };
}
64 là chức năng, thì nó chỉ có thể được sử dụng trong Node.js.

Để tối đa hóa khả năng tái sử dụng của một mô -đun, người ta thường nên tạo mã "đẳng cấu" - nghĩa là thể hiện hành vi tương tự trong mỗi thời gian chạy. Điều này thường đạt được theo ba cách:

  • Tách các mô -đun của bạn thành "lõi" và "ràng buộc". Đối với "Core", tập trung vào logic JavaScript thuần túy như tính toán băm, mà không có bất kỳ DOM, mạng, truy cập hệ thống tập tin và các chức năng tiện ích. Đối với phần "ràng buộc", bạn có thể đọc và ghi vào bối cảnh toàn cầu. Ví dụ: "liên kết trình duyệt" có thể chọn đọc giá trị từ hộp đầu vào, trong khi "liên kết nút" có thể đọc nó từ
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    65, nhưng các giá trị được đọc từ một trong hai nơi sẽ được đưa vào cùng một hàm lõi và được xử lý trong cùng một đường. Lõi có thể được nhập khẩu trong mọi môi trường và được sử dụng theo cùng một cách, trong khi chỉ có ràng buộc, thường nhẹ, cần phải được đặc trưng cho nền tảng.
  • Phát hiện xem một toàn cầu cụ thể có tồn tại trước khi sử dụng nó hay không. Ví dụ: nếu bạn kiểm tra
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    66 đó, bạn sẽ biết rằng bạn có thể ở trong môi trường Node.js và không nên đọc DOM.

    /js-examples/module-examples/basic-modules/modules/square.js
    
    2

    Điều này là thích hợp hơn nếu hai nhánh thực sự kết thúc với cùng một hành vi ("đẳng cấu"). Nếu không thể cung cấp cùng một chức năng hoặc nếu làm như vậy liên quan đến việc tải một lượng mã đáng kể trong khi một phần lớn vẫn không được sử dụng, thay vào đó hãy sử dụng tốt hơn các "ràng buộc" khác nhau.
  • Sử dụng Polyfill để cung cấp dự phòng cho các tính năng bị thiếu. Ví dụ: nếu bạn muốn sử dụng chức năng
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    67, chỉ được hỗ trợ trong Node.js kể từ v18, bạn có thể sử dụng API tương tự, giống như quy mô được cung cấp bởi
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    68. Bạn có thể làm như vậy một cách có điều kiện thông qua nhập khẩu động:

    /js-examples/module-examples/basic-modules/modules/square.js
    
    3

    Biến
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    69 là một đối tượng toàn cầu có sẵn trong mọi môi trường và rất hữu ích nếu bạn muốn đọc hoặc tạo các biến toàn cầu trong các mô -đun.

Những thực hành này không phải là duy nhất cho các mô -đun. Tuy nhiên, với xu hướng tái sử dụng và mô đun hóa mã, bạn được khuyến khích làm cho mã đa nền tảng của bạn để có thể được hưởng bởi càng nhiều người càng tốt. Runtimes như Node.js cũng đang tích cực triển khai API Web khi có thể cải thiện khả năng tương tác với Web.

Xử lý sự cố

Dưới đây là một vài mẹo có thể giúp bạn nếu bạn gặp khó khăn trong việc làm cho các mô -đun của mình hoạt động. Hãy thêm vào danh sách nếu bạn khám phá thêm!

  • Chúng tôi đã đề cập điều này trước đây, nhưng để nhắc lại:
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9 Các tệp cần được tải với loại MIME là
    <script type="module" src="main.js">script>
    
    2 (hoặc một loại khác nhau tương thích với JavaScript, nhưng
    <script type="module" src="main.js">script>
    
    2 được khuyến nghị "Máy chủ phản hồi với loại MIME không phải là JavaScript".
  • Nếu bạn cố gắng tải tệp HTML cục bộ (tức là với URL
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    01), bạn sẽ gặp lỗi CORS do các yêu cầu bảo mật mô -đun JavaScript. Bạn cần thực hiện thử nghiệm của bạn thông qua một máy chủ. Các trang GitHub là lý tưởng vì nó cũng phục vụ các tệp
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9 với loại MIME chính xác.
  • const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9 là một phần mở rộng tệp không chuẩn, một số hệ điều hành có thể không nhận ra nó hoặc cố gắng thay thế nó bằng một thứ khác. Ví dụ: chúng tôi thấy rằng các macOS đã âm thầm thêm vào
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    8 vào cuối các tệp
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9 và sau đó tự động ẩn tiện ích mở rộng tệp. Vì vậy, tất cả các tập tin của chúng tôi đã thực sự xuất hiện dưới dạng
    export const name = 'square';
    
    export function draw(ctx, length, x, y, color) {
      ctx.fillStyle = color;
      ctx.fillRect(x, y, length, length);
    
      return { length, x, y, color };
    }
    
    78. Khi chúng tôi tắt tự động ẩn các phần mở rộng tệp và được đào tạo để chấp nhận
    const myCanvas = create('myCanvas', document.body, 480, 320);
    const reportList = createReportList(myCanvas.id);
    
    const square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
    reportArea(square1.length, reportList);
    reportPerimeter(square1.length, reportList);
    
    9, nó vẫn ổn.

Xem thêm

  • Sử dụng các mô -đun JavaScript trên web, bởi Addy Osmani và Mathias Bynens
  • Mô-đun ES: Một bài đăng trên blog của phim hoạt hình, hacks của Lin Clark
  • ES6 theo chiều sâu: Mô -đun, bài đăng trên blog của Jason Orendorff
  • Cuốn sách của Axel Rauschmayer Khám phá JS: Mô -đun
  • " Trước

Lợi ích của việc sử dụng các mô -đun trong JavaScript là gì?

Lợi ích của việc sử dụng mô -đun Cơ sở mã dễ dàng hơn để duy trì vì mã khác nhau có các chức năng khác nhau trong các tệp khác nhau. Làm cho mã có thể tái sử dụng. Bạn có thể xác định một mô -đun và sử dụng nó nhiều lần theo nhu cầu của bạn.The code base is easier to maintain because different code having different functionalities are in different files. Makes code reusable. You can define a module and use it numerous times as per your needs.

Tại sao chúng ta cần mô -đun?

Chúng tôi sử dụng các mô -đun để chia các chương trình lớn thành các tệp có thể quản lý nhỏ và có tổ chức.Hơn nữa, các mô -đun cung cấp khả năng tái sử dụng mã.Chúng tôi có thể xác định các chức năng được sử dụng nhiều nhất của chúng tôi trong một mô -đun và nhập nó, thay vì sao chép định nghĩa của chúng vào các chương trình khác nhau.to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code. We can define our most used functions in a module and import it, instead of copying their definitions into different programs.

Một mô -đun có giống như một JavaScript thư viện không?

Mô -đun trong Node.js là gì?Hãy coi các mô -đun là giống như các thư viện JavaScript.Một tập hợp các chức năng bạn muốn đưa vào ứng dụng của mình.Consider modules to be the same as JavaScript libraries. A set of functions you want to include in your application.

Các mô -đun JavaScript có giống như các lớp không?

Các lớp được giới thiệu như một cách để mở rộng về kế thừa dựa trên nguyên mẫu bằng cách thêm một số khái niệm định hướng đối tượng.Các mô -đun được giới thiệu như một cách để tổ chức nhiều tệp mã trong JavaScript và mở rộng về khả năng tái sử dụng mã và phạm vi giữa các tệp.Modules were introduced as a way to organize multiple code files in JavaScript and expand on code reusability and scoping among files.