ES6: условные и динамические отчеты об импорте

условный

Можно ли иметь условные операторы импорта, как показано ниже?

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

Я пробовал выше, но получаю следующую ошибку (от Babel) при компиляции.

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

динамический

Возможно ли иметь динамические операторы импорта как ниже?

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

Вышесказанное получает ту же ошибку от Babel во время компиляции.

Это возможно сделать или мне чего-то не хватает?

аргументация

Причина, по которой я пытаюсь это сделать, заключается в том, что у меня много импортов для нескольких "страниц", и они следуют аналогичной схеме. Я хотел бы очистить базу кода, импортировав эти файлы с динамическим циклом for.

Если это невозможно, то есть ли лучший способ справиться с большим количеством импорта в ES6?

3 ответа

Решение

Вы не можете динамически разрешать ваши зависимости, так как imports предназначены для статического анализа. Тем не менее, вы, вероятно, можете использовать некоторые require здесь что-то вроде:

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

У нас есть предложение по динамическому импорту с ECMA. Это на этапе 2. Это также доступно как предустановка babel.

Ниже приведен способ сделать условный рендеринг согласно вашему случаю.

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

Это в основном возвращает обещание. Ожидается, что разрешение обещание будет иметь модуль. В предложении также есть такие вещи, как множественный динамический импорт, импорт по умолчанию, импорт файлов js и т. Д. Более подробную информацию о динамическом импорте можно найти здесь.

Поскольку этот вопрос высоко оценен Google, стоит отметить, что с момента публикации более старых ответов все изменилось.

В MDN есть эта запись в разделе Динамический импорт:

Ключевое слово import может быть вызвано как функция для динамического импорта модуля. При таком использовании возвращает обещание.

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

Полезную статью по этой теме можно найти на Medium.

С 2016 года в мире JavaScript многое изменилось, поэтому я считаю, что пришло время предложить самую последнюю информацию по этой теме. В настоящее время динамический импорт возможен как в Node, так и в браузерах (изначально, если вам не нужен IE, или с помощью https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import, если вам все равно).

Итак, рассмотрим образец модуля something.js с двумя именованными экспортами и одним экспортом по умолчанию:

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

Мы можем использовать import() синтаксис, чтобы легко и чисто загрузить его по условию:

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

Но так как возвращение Promise, то async/await синтаксический сахар также возможен:

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

А теперь подумайте о возможностях, связанных с назначением разрушения объекта! Например, мы можем легко поместить в память только один из названных экспортов для последующего использования:

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

Или, может быть, возьмите один из названных экспортов и переименуйте его как угодно:

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

Или даже переименуйте экспортируемую функцию по умолчанию во что-нибудь более понятное:

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

И последнее (но не менее важное) замечание: import() может выглядеть как вызов функции, но это не Function. Это особый синтаксис, в котором просто используются круглые скобки (аналогично тому, что происходит с super()). Поэтому назначить import к переменной или использовать вещи из Function прототип, вроде call/apply.

Require не решит вашу проблему, так как это синхронный вызов. Есть несколько вариантов, и все они включают

  1. Запрашиваемый модуль вам нужен
  2. В ожидании обещания вернуть модуль

В ECMA Script есть поддержка отложенной загрузки модулей с использованием SystemJS. Конечно, это поддерживается не во всех браузерах, поэтому вы можете использовать JSPM или SystemJS shim.

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

Другие вопросы по тегам