ES6: Báo cáo nhập khẩu có điều kiện & động


85

Có điều kiện

Có thể có câu lệnh nhập khẩu có điều kiện như dưới đây không?

if (foo === bar) {
    import Baz from './Baz';
}

Tôi đã thử cách trên nhưng gặp lỗi sau (từ Babel) khi biên dịch.

'import' and 'export' may only appear at the top level

Động

Có thể có các câu lệnh nhập động như dưới đây không?

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        import Baz from `./${foo}`;
    }
}

Ở trên nhận được cùng một lỗi từ Babel trong khi biên dịch.

Điều này có thể làm được hay là có điều gì đó tôi đang thiếu?

Lý luận

Lý do tôi đang cố gắng làm điều này là tôi có rất nhiều nhập khẩu cho một số "trang" và chúng theo một mô hình tương tự. Tôi muốn xóa cơ sở mã của mình bằng cách nhập các tệp này với vòng lặp động cho.

Nếu điều này là không thể thì có cách nào tốt hơn để xử lý số lượng lớn hàng nhập khẩu trong ES6 không?


1
kế thừa không được sử dụng trong trường hợp như vậy? sử dụng superđể gọi cụ thể.
Jai

Tôi đã sử dụng tính năng kế thừa, nhưng những "trang" này chứa logic cụ thể của "trang" trong chúng. Tôi có một lớp "trang" cơ sở mà tất cả đều mở rộng nhưng điều này không đủ để làm sạch số lượng lớn các mục nhập mà tôi có.
Enijar

1
@zerkms: Chúng không được đưa ra khỏi khối - chúng là lỗi cú pháp.
Bergi

có thể trùng lặp tên nhập biến ES6 trong node.js ?
Bergi

Câu trả lời:


54

Chúng tôi hiện có đề xuất nhập khẩu động với ECMA. Đây là giai đoạn 2. Điều này cũng có sẵn dưới dạng cài đặt sẵn babel .

Sau đây là cách để thực hiện kết xuất có điều kiện tùy theo trường hợp của bạn.

if (foo === bar) {
    import('./Baz')
    .then((Baz) => {
       console.log(Baz.Baz);
    });
}

Điều này về cơ bản trả lại một lời hứa. Phân giải lời hứa dự kiến ​​sẽ có mô-đun. Đề xuất cũng có những thứ như nhập nhiều động, nhập mặc định, nhập tệp js, v.v. Bạn có thể tìm thêm thông tin về nhập động tại đây .


3
Điều này. Nhập khẩu động là con đường để đi. Chúng hoạt động giống như một request (), ngoại trừ chúng cung cấp cho bạn một lời hứa hơn là một mô-đun.
siêu thường

24

Bạn không thể giải quyết động các phụ thuộc của mình, như importsđối với phân tích tĩnh. Tuy nhiên, bạn có thể sử dụng một số requireở đây, chẳng hạn như:

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        const Baz = require(foo).Baz;
    }
}

8
"vì nhập khẩu có nghĩa là để phân tích tĩnh." --- tuyên bố này là mơ hồ. imports được thiết kế để nhập khẩu, không phải để phân tích.
zerkms

12
@zerkms - Tôi nghĩ ý của họ là các importcâu lệnh phù hợp với phân tích tĩnh - bởi vì chúng không bao giờ có điều kiện, các công cụ có thể phân tích cây phụ thuộc dễ dàng hơn.
Joe Clay

4
Khó hiểu với "foo" "baz" và "bar" - còn ví dụ trong cuộc sống thực thì sao?
TetraDev

1
Điều này không còn đúng nữa. Nhập khẩu động bây giờ là một điều. Xem tại đây: stackoverflow.com/a/46543949/687677
superluminary

7

Vì câu hỏi này được Google xếp hạng cao, điều đáng chú ý là mọi thứ đã thay đổi kể từ khi các câu trả lời cũ được đăng.

MDN có mục nhập này trong Nhập động :

Từ khóa nhập có thể được gọi là một hàm để nhập động một mô-đun. Khi được sử dụng theo cách này, nó sẽ trả về một lời hứa.

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

// This form also supports the await keyword.
let module = await import('/modules/my-module.js');

Một bài viết hữu ích về chủ đề này có thể được tìm thấy trên Medium .


1

Yêu cầu sẽ không giải quyết được vấn đề của bạn vì nó là một cuộc gọi đồng bộ. Có một số tùy chọn và tất cả đều liên quan đến

  1. Yêu cầu mô-đun bạn cần
  2. Chờ lời hứa trả lại mô-đun

Trong ECMA Script có hỗ trợ các mô-đun tải lười sử dụng SystemJS. Tất nhiên, điều này không được hỗ trợ trong tất cả các trình duyệt, vì vậy trong thời gian chờ đợi, bạn có thể sử dụng JSPM hoặc miếng đệm SystemJS.

https://github.com/ModuleLoader/es6-module-loader


1

Kể từ năm 2016, rất nhiều thứ đã trôi qua trong thế giới JavaScript, vì vậy tôi tin rằng đã đến lúc cung cấp thông tin cập nhật nhất về chủ đề này. Hiện tại, nhập động là một thực tế cả trên Nodetrên các trình duyệt (nguyên bản nếu bạn không quan tâm đến IE hoặc với @ babel / plugin-cú pháp-động-nhập nếu bạn quan tâm).

Vì vậy, hãy xem xét một mô-đun mẫu something.jscó hai xuất được đặt tên và một xuất mặc định:

export const hi = (name) => console.log(`Hi, ${name}!`)
export const bye = (name) => console.log(`Bye, ${name}!`)
export default () => console.log('Hello World!')

Chúng ta có thể sử dụng import()cú pháp để tải nó một cách dễ dàng và rõ ràng có điều kiện:

if (somethingIsTrue) {
  import('./something.js').then((module) => {
    // Use the module the way you want, as:
    module.hi('Erick') // Named export
    module.bye('Erick') // Named export
    module.default() // Default export
  })
}

Nhưng vì kết quả trả về là a Promise, nên đường async/ awaitcú pháp cũng có thể:

async imAsyncFunction () {
  if (somethingIsTrue) {
    const module = await import('./something.js')
    module.hi('Erick')
  }
}

Bây giờ hãy nghĩ về các khả năng cùng với Phân công cấu trúc đối tượng ! Ví dụ: chúng tôi có thể dễ dàng đặt chỉ một trong những bản xuất đã đặt tên vào bộ nhớ để sử dụng sau:

const { bye } = await import('./something.js')
bye('Erick')

Hoặc có thể lấy một trong những bản xuất có tên đó và đổi tên nó thành bất kỳ thứ gì khác mà chúng tôi muốn:

const { hi: hello } = await import('./something.js')
hello('Erick')

Hoặc thậm chí đổi tên hàm được xuất mặc định thành một cái gì đó có ý nghĩa hơn:

const { default: helloWorld } = await import('./something.js')
helloWorld()

Lưu ý cuối cùng (nhưng không kém phần quan trọng): import() có thể trông giống như một lệnh gọi hàm, nhưng nó không phải là một Function. Đó là một cú pháp đặc biệt chỉ sử dụng dấu ngoặc đơn (tương tự như những gì xảy ra với super()). Vì vậy, không thể gán importcho một biến hoặc sử dụng những thứ của Functionnguyên mẫu, như call/ apply.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.