ES6: Koşullu ve Dinamik Alma İfadeleri


86

Koşullu

Aşağıdaki gibi koşullu ithalat ifadelerine sahip olmak mümkün mü?

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

Yukarıdakileri denedim ancak derleme sırasında aşağıdaki hatayı (Babel'den) alıyorum.

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

Dinamik

Aşağıdaki gibi dinamik içe aktarma ifadelerine sahip olmak mümkün mü?

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

Yukarıdakiler derleme sırasında Babel'den aynı hatayı alır.

Bunu yapmak mümkün mü yoksa kaçırdığım bir şey var mı?

Muhakeme

Bunu yapmaya çalışmamın nedeni, bir dizi "sayfa" için çok fazla ithalatım olması ve benzer bir modeli izlemeleri. Bu dosyaları dinamik bir for döngüsü ile içe aktararak kod tabanımı temizlemek istiyorum.

Bu mümkün değilse, ES6'da çok sayıda ithalatın üstesinden gelmenin daha iyi bir yolu var mı?


1
Böyle bir durumda miras kullanılamaz mı? superözel aramak için kullanın .
Jai

Zaten kalıtım kullanıyorum, ancak bu "sayfalar" içlerinde "sayfaya" özel bir mantık içeriyor. Tamamen genişleyen bir temel "sayfa" sınıfım var, ancak bu, sahip olduğum çok sayıda ithalatı temizlemek için yeterli değil.
Enijar

1
@zerkms: Bloklardan kaldırılmıyorlar - sözdizimi hataları.
Bergi


Yanıtlar:


54

Şimdi ECMA ile dinamik ithalat teklifimiz var. Bu 2. aşamadadır. Bu, babel ön ayarı olarak da mevcuttur .

Aşağıda, durumunuza göre koşullu oluşturma yapmanın bir yolu vardır.

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

Bu temelde bir söz verir. Sözün çözümlenmesi modülüne sahip olması bekleniyor. Teklifte ayrıca birden çok dinamik içe aktarma, varsayılan içe aktarma, js dosyası içe aktarma vb. Gibi şeyler vardır. Dinamik içe aktarmalar hakkında daha fazla bilgiyi burada bulabilirsiniz .


3
Bu. Dinamik içe aktarmalar gitmenin yoludur. Bir modül yerine söz vermeleri dışında, tıpkı bir require () gibi çalışırlar.
superluminary

25

importsStatik analizde olduğu gibi bağımlılıklarınızı dinamik olarak çözemezsiniz . Ancak, muhtemelen bazılarını requireburada kullanabilirsiniz , örneğin:

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

8
"ithalatlar statik analiz içindir." --- bu ifade belirsizdir. import'ler analiz için değil içe aktarmak üzere tasarlanmıştır.
zerkms

13
@zerkms - Bence importifadelerin statik analiz için uygun olması gerektiğini kastediyorlar - çünkü hiçbir zaman koşullu değiller, araçlar bağımlılık ağaçlarını daha kolay analiz edebilir.
Joe Clay

4
"Foo" "baz" ve "bar" ile anlaşılması zor - peki ya gerçek hayattan bir örnek?
TetraDev

1
Bu artık doğru değil. Dinamik içe aktarmalar artık önemli. Buraya bakın: stackoverflow.com/a/46543949/687677
superluminary

7

Bu soru Google tarafından üst sıralarda yer aldığından, eski yanıtların gönderilmesinden bu yana bazı şeylerin değiştiğini belirtmekte fayda var.

MDN'de Dinamik İçe Aktarımlar altında şu giriş vardır :

İmport anahtar sözcüğü, bir modülü dinamik olarak içe aktarmak için bir işlev olarak çağrılabilir. Bu şekilde kullanıldığında bir söz verir.

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

Konuyla ilgili faydalı bir makale Medium'da bulunabilir .


2

2016'dan beri JavaScript dünyasında çok şey geçti, bu yüzden bu konuyla ilgili en güncel bilgileri sunmanın zamanının geldiğine inanıyorum. Şu anda Dinamik ithalatı bir gerçeklik vardır hem Düğümünde ve tarayıcılarda (IE umurumda değil doğal halinde ya ile @ babel / eklenti-sözdizimi-dinamik-ithalat Umurunda varsa).

Bu nedenle, something.jsiki adlandırılmış dışa aktarma ve bir varsayılan dışa aktarma içeren örnek bir modül düşünün :

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

import()Koşullu olarak kolayca ve temiz bir şekilde yüklemek için sözdizimini kullanabiliriz :

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

Ancak dönüş a Promiseolduğu için async/ awaitsözdizimsel şeker de mümkündür:

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

Şimdi Nesne Yok Etme Ödevi ile birlikte olasılıkları düşünün ! Örneğin, posterior kullanım için bu adlandırılmış dışa aktarmalardan yalnızca birini belleğe kolayca koyabiliyoruz:

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

Ya da belki dışa aktarma adı verilenlerden birini alıp, istediğimiz başka bir şeyle yeniden adlandırın:

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

Veya varsayılan olarak dışa aktarılan işlevi daha mantıklı bir şekilde yeniden adlandırın:

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

Son (ama en önemlisi) not: import() bir işlev çağrısı gibi görünebilir, ancak bir Function. Parantezlerin kullanıldığı özel bir sözdizimidir (ne olduğuna benzer super()). Dolayısıyla import, bir değişkene atamak veya Functionprototipin call/ gibi şeyleri kullanmak mümkün değildir apply.


1

Eşzamanlı bir çağrı olduğu için Require sorununuzu çözmez. Birkaç seçenek var ve hepsi şunları içeriyor:

  1. İhtiyacınız olan modülü sormak
  2. Modülü iade etme sözünü bekliyorum

ECMA Script'te SystemJS kullanılarak geç yükleme modülleri için destek vardır. Bu elbette tüm tarayıcılarda desteklenmez, bu nedenle bu arada JSPM veya SystemJS shim kullanabilirsiniz.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.