เป็นไปได้หรือไม่ที่จะนำเข้าบางสิ่งบางอย่างไปยังโมดูลที่ให้ชื่อตัวแปรในขณะที่ใช้การนำเข้า ES6
คือฉันต้องการนำเข้าโมดูลบางส่วนที่รันไทม์ขึ้นอยู่กับค่าที่ระบุใน config:
import something from './utils/' + variableName;
เป็นไปได้หรือไม่ที่จะนำเข้าบางสิ่งบางอย่างไปยังโมดูลที่ให้ชื่อตัวแปรในขณะที่ใช้การนำเข้า ES6
คือฉันต้องการนำเข้าโมดูลบางส่วนที่รันไทม์ขึ้นอยู่กับค่าที่ระบุใน config:
import something from './utils/' + variableName;
คำตอบ:
ไม่ใช่ด้วยimport
คำสั่ง import
และexport
ถูกกำหนดในลักษณะที่วิเคราะห์ได้แบบคงที่ดังนั้นจึงไม่สามารถขึ้นอยู่กับข้อมูลรันไทม์ได้
คุณกำลังมองหาloader API (polyfill)แต่ฉันไม่ชัดเจนเกี่ยวกับสถานะของข้อกำหนด:
System.import('./utils/' + variableName).then(function(m) {
console.log(m);
});
นอกจากคำตอบของเฟลิกซ์แล้วฉันจะสังเกตอย่างชัดเจนว่าตอนนี้ไวยากรณ์ ECMAScript 6ยังไม่ได้รับอนุญาต:
ImportDeclaration :
นำเข้า ImportClause FromClause;
นำเข้า ModuleSpecifier;
FromClause :
- จาก ModuleSpecifier
ModuleSpecifier :
- StringLiteral
ModuleSpecifierสามารถเป็นStringLiteralไม่ได้ชนิดอื่น ๆ ของการแสดงออกเช่นAdditiveExpression
const
string literal
s ไว้ด้วย พวกมันวิเคราะห์ได้แบบคงที่ใช่หรือไม่? มันจะทำให้การนำตำแหน่งของการพึ่งพากลับมาใช้ใหม่เป็นไปได้ (เช่นนำเข้าเทมเพลตและมีทั้งเทมเพลตและตำแหน่งของเทมเพลตที่พร้อมใช้งาน)
ในขณะที่นี่ไม่ใช่การนำเข้าแบบไดนามิก (เช่นในสถานการณ์ของฉันไฟล์ทั้งหมดที่ฉันนำเข้าด้านล่างจะถูกนำเข้าและรวมกลุ่มโดย webpack ไม่ได้เลือกในรันไทม์) รูปแบบที่ฉันใช้ซึ่งอาจช่วยได้ในบางสถานการณ์คือ :
import Template1 from './Template1.js';
import Template2 from './Template2.js';
const templates = {
Template1,
Template2
};
export function getTemplate (name) {
return templates[name];
}
หรืออีกทางหนึ่ง:
// index.js
export { default as Template1 } from './Template1';
export { default as Template2 } from './Template2';
// OtherComponent.js
import * as templates from './index.js'
...
// handy to be able to fall back to a default!
return templates[name] || templates.Template1;
ฉันไม่คิดว่าฉันจะถอยกลับไปใช้ค่าเริ่มต้นได้อย่างง่ายดายrequire()
ซึ่งจะทำให้เกิดข้อผิดพลาดหากฉันพยายามนำเข้าเส้นทางเทมเพลตที่สร้างขึ้นซึ่งไม่มีอยู่
สามารถดูตัวอย่างและการเปรียบเทียบที่ดีระหว่างความต้องการและการนำเข้าได้ที่นี่: http://www.2ality.com/2014/09/es6-modules-final.html
เอกสารที่ยอดเยี่ยมเกี่ยวกับการส่งออกซ้ำจาก @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles
ฉันสนใจที่จะรับฟังความคิดเห็นเกี่ยวกับแนวทางนี้ :)
Object.values(templates)
หากคุณต้องการให้พวกเขาเป็นรายการอีกครั้งเพียงแค่ทำ
มีข้อกำหนดใหม่ซึ่งเรียกว่าการนำเข้าแบบไดนามิกสำหรับโมดูล ES โดยพื้นฐานแล้วคุณแค่โทรหาimport('./path/file.js')
คุณก็พร้อมแล้ว ฟังก์ชันจะส่งคืนคำสัญญาซึ่งแก้ไขด้วยโมดูลหากการนำเข้าสำเร็จ
async function importModule() {
try {
const module = await import('./path/module.js');
} catch (error) {
console.error('import failed');
}
}
กรณีการใช้งานรวมถึงการนำเข้าส่วนประกอบตามเส้นทางสำหรับ React, Vueและอื่น ๆ และความสามารถในการโหลดโมดูลแบบขี้เกียจเมื่อจำเป็นต้องใช้ระหว่างรันไทม์
นี่คือคำอธิบายเกี่ยวกับGoogle Developers
ตามMDNได้รับการสนับสนุนโดยเบราว์เซอร์หลักทุกตัวในปัจจุบัน (ยกเว้น IE) และcaniuse.comแสดงการสนับสนุน 87% ในส่วนแบ่งการตลาดทั่วโลก อีกครั้งไม่รองรับ IE หรือขอบที่ไม่ใช่โครเมียม
ฉันเข้าใจคำถามที่ถามโดยเฉพาะสำหรับ ES6 import
ใน Node.js แต่สิ่งต่อไปนี้อาจช่วยให้ผู้อื่นมองหาวิธีแก้ปัญหาทั่วไปมากขึ้น:
let variableName = "es5.js";
const something = require(`./utils/${variableName}`);
โปรดทราบว่าหากคุณกำลังนำเข้าโมดูล ES6และต้องการเข้าถึงการdefault
ส่งออกคุณจะต้องใช้สิ่งใดสิ่งหนึ่งต่อไปนี้:
let variableName = "es6.js";
// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;
// Accessing
const something = require(`./utils/${variableName}`);
something.default();
คุณยังสามารถใช้การทำลายโครงสร้างด้วยวิธีนี้ซึ่งอาจเพิ่มความคุ้นเคยทางไวยากรณ์มากขึ้นกับการนำเข้าอื่น ๆ ของคุณ:
// Destructuring
const { someMethod } = require(`./utils/${variableName}`);
someMethod();
ขออภัยหากคุณต้องการเข้าถึงdefault
และทำลายโครงสร้างคุณจะต้องดำเนินการในหลายขั้นตอน:
// ES6 Syntax
Import defaultMethod, { someMethod } from "const-path.js";
// Destructuring + default assignment
const something = require(`./utils/${variableName}`);
const defaultMethod = something.default;
const { someMethod, someOtherMethod } = something;
คุณสามารถใช้สัญกรณ์ที่ไม่ใช่ ES6 เพื่อทำเช่นนั้น นี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน:
let myModule = null;
if (needsToLoadModule) {
myModule = require('my-module').default;
}
ฉันไม่ชอบไวยากรณ์นี้ แต่มันใช้งานได้:
แทนที่จะเขียน
import memberName from "path" + "fileName";
// this will not work!, since "path" + "fileName" need to be string literal
ใช้ไวยากรณ์นี้:
let memberName = require("path" + "fileName");
require()
เป็นวิธีการ Node.JS สำหรับการโหลดไฟล์ซึ่งเป็นเวอร์ชันแรก ๆ import
คำสั่งเป็นเวอร์ชันที่ใหม่กว่าซึ่งตอนนี้เป็นส่วนหนึ่งของไวยากรณ์ภาษาทางการ อย่างไรก็ตามในหลาย ๆ กรณีเบราว์เซอร์จะใช้เบราว์เซอร์ก่อนหน้านี้ (อยู่เบื้องหลังวิทยาศาสตร์) คำสั่งที่ต้องการจะทำให้ไฟล์ของคุณเป็นเงินสดด้วยดังนั้นหากไฟล์ถูกโหลดครั้งที่ 2 ไฟล์จะถูกโหลดจากหน่วยความจำ (ประสิทธิภาพดีกว่า) วิธีการนำเข้ามีประโยชน์ในตัวเอง - หากคุณใช้ WebPack จากนั้น webpack สามารถลบการอ้างอิงที่ตายแล้ว (สคริปต์เหล่านี้จะไม่ถูกดาวน์โหลดไปยังไคลเอนต์)
การนำเข้าแบบไดนามิก () (พร้อมใช้งานใน Chrome 63+) จะทำงานของคุณ วิธีการมีดังนี้
let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });
ฉันจะทำแบบนี้
function load(filePath) {
return () => System.import(`${filePath}.js`);
// Note: Change .js to your file extension
}
let A = load('./utils/' + variableName)
// Now you can use A in your module
./utils/test.js
export default () => {
doSomething...
}
โทรจากไฟล์
const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();