Chuyển các tùy chọn để nhập mô-đun ES6


144

Có thể vượt qua các tùy chọn để nhập ES6?

Làm thế nào để bạn dịch này:

var x = require('module')(someoptions);

đến ES6?


Không chắc chắn bạn có thể, có một API trình tải mô-đun, hoặc ít nhất là đã có lúc, nó sử dụng một cái gì đó như System.import(module), không chắc điều đó có cho phép đối số hay không, ai đó biết nhiều hơn về ES6 có thể không?
adeneo

Có một giải pháp được đề xuất cho vấn đề này, trong đó đã có các triển khai trong node.js (thông qua plugin) và webpack: 2ality.com/2017/01/import-operator.html
Matt Browne

Câu trả lời:


104

Không có cách nào để làm điều này với một importtuyên bố duy nhất , nó không cho phép các yêu cầu.

Vì vậy, bạn sẽ không gọi nó trực tiếp, nhưng về cơ bản bạn có thể làm giống như những gì thường gặp với xuất khẩu mặc định:

// module.js
export default function(options) {
    return {
        // actual module
    }
}

// main.js
import m from 'module';
var x = m(someoptions);

Ngoài ra, nếu bạn sử dụng trình tải mô-đun hỗ trợ các lời hứa đơn điệu , bạn có thể thực hiện một số việc như

System.import('module').ap(someoptions).then(function(x) {
    
});

Với importtoán tử mới, nó có thể trở thành

const promise = import('module').then(m => m(someoptions));

hoặc là

const x = (await import('module'))(someoptions)

tuy nhiên, bạn có thể không muốn nhập động mà là nhập tĩnh.


7
Cảm ơn bạn, tôi ước có một cái gì đó giống như import x from 'module' use someoptions;cú pháp
Fabrizio Giordano

1
@Fabrizio: Nếu bạn nghĩ về nó xa hơn, nó sẽ không thực sự hữu ích. Nó sẽ chỉ hoạt động nếu mô-đun xuất một hàm và có lẽ không được phép nếu chúng ta đã đặt tên nhập khẩu (nghĩa là import {x, y} from 'module'). Vậy thì cú pháp nên là gì nếu tôi muốn truyền nhiều đối số? Hoặc lan truyền một loạt các đối số? Đó là một trường hợp sử dụng hẹp và về cơ bản, bạn đang cố gắng thêm một cú pháp khác cho một lệnh gọi hàm, nhưng chúng tôi đã có các lệnh gọi hàm cho phép chúng tôi xử lý tất cả các trường hợp khác.
Felix Kling

3
@FelixKling Tôi hoàn toàn đồng ý với bạn. Tôi đã chuyển đổi một ứng dụng web nhanh cũ và tôi gặp phải var session = require('express-session'); var RedisStore = require('connect-redis')(session);tôi chỉ tự hỏi liệu có một giải pháp một dòng. Tôi hoàn toàn có thể sống sót với việc phân chia nhiệm vụ RedisStore thành 2 dòng :)
Fabrizio Giordano

@FabrizioGiordano: Tôi có thể tưởng tượng một cái gì đó giống như import {default(someoptions) as x} from 'module'trong ES7, nếu thực sự cần thiết cho việc này.
Bergi

2
Đối với session/ connect-redisví dụ, tôi đã tưởng tượng cú pháp như thế này : import session from 'express-session'); import RedisStore(session) from 'connect-redis'.
Jeff Handley

24

Ý tưởng

Đây là giải pháp của tôi bằng ES6

Rất nhiều nội tuyến với phản hồi của @ Bergi's, đây là "mẫu" tôi sử dụng khi tạo các mục nhập cần tham số được truyền cho classkhai báo. Cái này được sử dụng trên một khung đẳng cấu mà tôi đang viết, vì vậy sẽ hoạt động với một bộ chuyển mã trong trình duyệt và trong node.js (tôi sử dụng Babelvới Webpack):

./MyClass.js

export default (Param1, Param2) => class MyClass {
    constructor(){
        console.log( Param1 );
    }
}

./main.js

import MyClassFactory from './MyClass.js';

let MyClass = MyClassFactory('foo', 'bar');

let myInstance = new MyClass();

Ở trên sẽ xuất ra footrong một giao diện điều khiển

BIÊN TẬP

Ví dụ thế giới thực

Đối với một ví dụ trong thế giới thực, tôi đang sử dụng điều này để vượt qua trong một không gian tên để truy cập các lớp và thể hiện khác trong một khung. Bởi vì chúng ta chỉ đơn giản là tạo một hàm và truyền đối tượng vào làm đối số, nên chúng ta có thể sử dụng nó với khai báo lớp thích của chúng ta:

export default (UIFramework) => class MyView extends UIFramework.Type.View {
    getModels() {
        // ...
        UIFramework.Models.getModelsForView( this._models );
        // ...
    }
}

Việc nhập khẩu phức tạp hơn một chút và automagicaltrong trường hợp của tôi cho rằng đó là toàn bộ khung, nhưng về cơ bản đây là những gì đang xảy ra:

// ...
getView( viewName ){
    //...
    const ViewFactory = require(viewFileLoc);
    const View = ViewFactory(this);
    return new View();
}
// ...

Tôi hi vọng cái này giúp được!


Vì tất cả các mô-đun đã nhập của bạn là các lớp, tại sao không truyền tham số khi khởi tạo lớp?
jasonszhao

1
@jasonszhao Điều quan trọng nhất cần lưu ý ở đây là lớp MyViewmở rộng các mục nhất định có sẵn trong không gian tên của khung. Mặc dù hoàn toàn có thể chuyển nó thành một tham số cho lớp, nhưng nó cũng phụ thuộc vào thời điểm và nơi lớp được khởi tạo; tính di động sau đó bị ảnh hưởng. Trong thực tế, các lớp này có thể được chuyển giao cho các khung công tác khác có thể khởi tạo chúng theo cách khác nhau (ví dụ: các thành phần React tùy chỉnh). Khi lớp tìm thấy chính nó bên ngoài phạm vi khung, nó vẫn có thể duy trì quyền truy cập vào khung khi được khởi tạo vì phương thức này.
Xoay

@Sw Xoay Vui lòng hỗ trợ Tôi cần trợ giúp về vấn đề tương tự: stackoverflow.com/questions/55214957/NH
TSR

12

Dựa trên câu trả lời của @ Bergi để sử dụng mô-đun gỡ lỗi bằng es6 sẽ là như sau

// original
var debug = require('debug')('http');

// ES6
import * as Debug from 'debug';
const debug = Debug('http');

// Use in your code as normal
debug('Hello World!');

4

Tôi tin rằng bạn có thể sử dụng bộ tải mô-đun es6. http://babeljs.io/docs/learn-es6/

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});

3
Nhưng kết quả m(youroptionshere)cuối cùng ở đâu? Tôi cho rằng bạn có thể viết System.import('lib/math').then(m => m(options)).then(module => { /* code using module here */})... nhưng nó không rõ ràng lắm.
Stijn de Witt

2
Ồ, tôi không thể tin rằng không có cách nào thanh lịch để làm điều này trong E6. Đó là cách tôi chủ yếu viết các mô-đun.
Robert Moskal

3

Bạn chỉ cần thêm 2 dòng này.

import xModule from 'module';
const x = xModule('someOptions');

1
Điều đó chỉ đơn giản là truyền tham số cho một chức năng bạn đã nhập và đang gọi. Nó không chuyển bất kỳ tùy chọn nào cho mô-đun bạn nhập từ đó . xModulelà sai lệch ở đây. Những gì bạn thực sự có là import func from 'module'; func('someOptions');.
Dan Dascalescu

1

Tôi đã tìm đến chủ đề này để tìm kiếm một chút tương tự và muốn đề xuất một loại giải pháp, ít nhất là đối với một số trường hợp (nhưng xem Ghi chú bên dưới).

Ca sử dụng

Tôi có một mô-đun, đang chạy một số logic khởi tạo ngay khi tải. Tôi không thích gọi logic init này bên ngoài mô-đun (giống như cuộc gọi new SomeClass(p1, p2)hoặc new ((p1, p2) => class SomeClass { ... p1 ... p2 ... })tương tự).

Tôi làm như vậy logic logic này sẽ chạy một lần, một loại luồng khởi tạo đơn lẻ, nhưng một lần trên một bối cảnh tham số cụ thể.

Thí dụ

service.js có phạm vi rất cơ bản của nó:

let context = null;                  // meanwhile i'm just leaving this as is
console.log('initialized in context ' + (context ? context : 'root'));

Mô-đun A có:

import * as S from 'service.js';     // console has now "initialized in context root"

Mô-đun B thực hiện:

import * as S from 'service.js';     // console stays unchanged! module's script runs only once

Cho đến nay rất tốt: dịch vụ có sẵn cho cả hai mô-đun nhưng chỉ được khởi tạo một lần.

Vấn đề

Làm thế nào để làm cho nó chạy như một thể hiện khác và tự khởi tạo lại một lần nữa trong ngữ cảnh khác, nói trong Mô-đun C?

Giải pháp?

Đây là những gì tôi nghĩ về: sử dụng các tham số truy vấn. Trong dịch vụ, chúng tôi sẽ thêm vào như sau:

let context = new URL(import.meta.url).searchParams.get('context');

Mô-đun C sẽ làm:

import * as S from 'service.js?context=special';

mô-đun sẽ được nhập lại, logic cơ bản của nó sẽ chạy và chúng ta sẽ thấy trong bảng điều khiển:

initialized in context special

Lưu ý: Bản thân tôi khuyên bạn KHÔNG nên thực hành phương pháp này nhiều, nhưng hãy để nó như là phương sách cuối cùng. Tại sao? Mô-đun được nhập nhiều hơn một lần là ngoại lệ so với quy tắc, do đó, đây là hành vi hơi bất ngờ và do đó có thể gây nhầm lẫn cho người tiêu dùng hoặc thậm chí phá vỡ mô hình 'đơn lẻ' của chính nó, nếu có.


0

Đây là câu hỏi của tôi về câu hỏi này bằng cách sử dụng mô-đun gỡ lỗi làm ví dụ;

Trên trang npm của mô-đun này, bạn có:

var debug = Yêu cầu ('gỡ lỗi') ('http')

Trong dòng trên, một chuỗi được truyền đến mô-đun được nhập, để xây dựng. Đây là cách bạn sẽ làm tương tự trong ES6


nhập {gỡ lỗi dưới dạng gỡ lỗi} từ 'gỡ lỗi' const debug = Debug ('http');


Hy vọng điều này sẽ giúp ai đó ngoài kia.


Tại sao đăng một câu trả lời trùng lặp với một câu trả lời đã được đăng ?
Dan Dascalescu

1
Lỗi của tôi. Không bao giờ nhìn thấy bài viết được đề cập. Chỉ cần nhìn vào câu hỏi và đâm vào nó. Cảm ơn đã mang nó đến thông báo của tôi.
Akinwale Folorunsho Habib

Không có gì. Bạn cũng có thể xóa câu trả lời trùng lặp nếu bạn muốn.
Dan Dascalescu
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.