ES6 modül ithalatına geçiş seçenekleri


144

Seçenekleri ES6 ithalatına geçirmek mümkün müdür?

Bunu nasıl çevirirsiniz:

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

ES6


Yapabileceğinizden emin değilsiniz, bir modül yükleyici API'si var veya en azından bir zamanlar böyle bir şey kullandı System.import(module), bunun argümanlara izin verip vermediğinden emin değilim, ES6 hakkında daha fazla bilgi sahibi biri muhtemelen yapar mı?
adeneo

Bunun için önerilen bir çözüm var, bunun için zaten node.js (bir eklenti aracılığıyla) ve webpack'te uygulamalar var: 2ality.com/2017/01/import-operator.html
Matt Browne

Yanıtlar:


104

Bunu tek bir importifadeyle yapmanın bir yolu yoktur , istilalara izin vermez.

Bu yüzden doğrudan aramazsınız, ancak temelde ortak ihracatların varsayılan dışa aktarma işlemleriyle aynı şeyi yapabilirsiniz:

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

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

Alternatif olarak, monadik vaatleri destekleyen bir modül yükleyici kullanıyorsanız, aşağıdaki gibi bir şey yapabilirsiniz.

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

Yeni sayesinde importoperatör o hale gelebilir

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

veya

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

ancak muhtemelen dinamik bir içe aktarma istemez, statik bir içe aktarma istemezsiniz.


7
Teşekkür ederim ben import x from 'module' use someoptions;sözdizimi tür gibi bir şey olsaydı
Fabrizio Giordano

1
@Fabrizio: Eğer daha fazla düşünürseniz, bu gerçekten yararlı olmaz. Yalnızca modül bir işlevi dışa aktarırsa işe yarar ve içe aktarmayı (yani import {x, y} from 'module') isimlendirirsek büyük olasılıkla izin verilmemelidir . Birden fazla argüman iletmek istersem sözdizimi ne olmalı? Veya bir dizi argümanı yaymak mı? Bu dar bir kullanım durumu ve temel olarak bir işlev çağrısı için farklı bir sözdizimi eklemeye çalışıyorsunuz, ancak zaten diğer tüm durumlarla başa çıkmamızı sağlayan işlev çağrılarımız var.
Felix Kling

3
@FelixKling Size tamamen katılıyorum. Eski bir ekspres web uygulamasını dönüştürüyordum ve var session = require('express-session'); var RedisStore = require('connect-redis')(session);sadece tek satırlık bir çözüm olup olmadığını merak ediyordum. Tamamen 2 satırda RedisStore ödevi ile hayatta kalabilir :)
Fabrizio Giordano

@FabrizioGiordano: import {default(someoptions) as x} from 'module'Buna gerçekten ihtiyaç varsa ES7'de olduğu gibi bir şey hayal edebiliyorum .
Bergi

2
İçin session/ connect-redisÖrneğin, böyle sözdizimi hayal edilmiştir: import session from 'express-session'); import RedisStore(session) from 'connect-redis'.
Jeff Handley

24

kavram

İşte ES6 kullanarak çözümüm

@ Bergi'nin cevabı ile çok fazla satır içi, bu classbildirimler için geçirilen parametrelere ihtiyaç duyulan ithalatı oluştururken kullandığım "şablon" . Bu, yazdığım izomorfik bir çerçeve üzerinde kullanılır, bu yüzden tarayıcıda ve node.js'de bir transpiler ile çalışacağım ( Babelile kullanıyorum 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();

Yukarıdaki foobir konsolda çıktı

DÜZENLE

Gerçek Dünya Örneği

Gerçek bir dünya örneği için, bunu bir çerçevedeki diğer sınıflara ve örneklere erişmek için bir ad alanına geçirmek için kullanıyorum. Basitçe bir fonksiyon yaratıyoruz ve nesneyi bir argüman olarak aktarıyoruz, onu sınıf beyanı beğenilerimizle kullanabiliriz:

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

İthalat biraz daha karmaşıktır ve automagicalbenim durumumda bunun tüm bir çerçeve olduğu göz önüne alındığında, esasen olan şey budur:

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

Umarım bu yardımcı olur!


İçe aktarılan tüm modülleriniz sınıf olduğundan, sınıfı başlatırken parametreyi neden geçmiyorsunuz?
jasonszhao

1
@jasonszhao Burada dikkat edilmesi gereken en önemli şey, sınıfın MyViewçerçevenin ad alanında bulunan belirli öğeleri genişletmesidir. Sınıfa bir parametre olarak iletmek kesinlikle mümkün olsa da, aynı zamanda sınıfın ne zaman ve nerede başlatıldığına da bağlıdır; taşınabilirlik bundan sonra etkilenir. Uygulamada, bu sınıflar, onları farklı şekilde başlatabilecek diğer çerçevelere (örneğin, özel React bileşenleri) verilebilir. Sınıf kendisini çerçeve kapsamı dışında bulduğunda, bu metodoloji nedeniyle somutlaştırıldığında çerçeveye erişmeye devam edebilir.
Döner

@Swivel Lütfen yardım edin Benzer sorun konusunda yardıma ihtiyacım var: stackoverflow.com/questions/55214957/…
TSR

12

@ Bergi'nin hata ayıklama modülünü es6 kullanarak kullanma cevabı üzerine inşa etmek aşağıdaki gibi olacaktır:

// 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

Es6 modül yükleyicileri kullanabileceğinize inanıyorum. http://babeljs.io/docs/learn-es6/

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

3
Fakat sonuç nerede ortaya m(youroptionshere)çıkıyor? Sanırım yazabilirsiniz System.import('lib/math').then(m => m(options)).then(module => { /* code using module here */})... ama çok net değil.
Stijn de Witt

2
Vay canına, E6'da bunu yapmanın zarif bir yolu olmadığına inanamıyorum. Ben çoğunlukla modül yazıyorum.
Robert Moskal

3

Bu 2 satırı eklemeniz yeterlidir.

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

1
Bu sadece parametreleri içe aktardığınız ve çağırdığınız bir işleve geçirir. İçe aktardığınız modüle herhangi bir seçenek aktarmıyor . xModuleburada yanıltıcı. Aslında sahip olduğunuz şey import func from 'module'; func('someOptions');.
Dan Dascalescu

1

Ben biraz benzer ararken bu konuya indi ve en azından bazı durumlarda bir tür çözüm önermek istiyorum (ama aşağıdaki Açıklama).

Kullanım örneği

Yüklemeden hemen sonra bazı örnekleme mantığını çalıştıran bir modülüm var. Yapmam değil çağrısı aynıdır modül dışında bu init mantığı (çağırmak gibinew SomeClass(p1, p2) yanew ((p1, p2) => class SomeClass { ... p1 ... p2 ... }) ve benzeri).

Bu init mantığının bir kez, tek bir örnekleme akışının çalışmasını seviyorum, ama belirli parametreli bağlamlarda .

Misal

service.js çok temel kapsamına sahiptir:

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

Modül A şunları yapar:

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

Modül B şunları yapar:

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

Şimdiye kadar iyi: hizmet her iki modül için de mevcut ancak sadece bir kez başlatıldı.

Sorun

Modül C'de başka bir örnek olarak nasıl çalıştırılır ve başka bir bağlamda yeniden başlatılır?

Çözüm?

Ben de öyle düşünüyorum: sorgu parametrelerini kullan. Hizmette aşağıdakileri ekleriz:

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

Modül C şunları yapar:

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

modül yeniden içe aktarılacak, temel init mantığı çalışacak ve konsolda göreceğiz:

initialized in context special

Not: Bu yaklaşımı çok fazla uygulamamayı tavsiye ederim, ancak son çare olarak bırakın. Neden? Bir kereden fazla içe aktarılan modül bir kuraldan çok bir istisnadır, bu yüzden beklenmedik bir davranıştır ve bu nedenle tüketicileri şaşırtabilir veya hatta kendi 'singleton' paradigmalarını kırabilir.


0

Örnek olarak hata ayıklama modülünü kullanarak bu soruyu ele alacağım;

Bu modülün npm sayfasında:

var debug = requir ('debug') ('http')

Yukarıdaki satırda, oluşturmak için içe aktarılan modüle bir dize iletilir. ES6'da da aynısını nasıl yapacağınız aşağıda açıklanmıştır


'debug' dan {debug olarak Debug} içe aktar const debug = Debug ('http');


Umarım bu birisine yardım eder.


Neden zaten gönderilmiş bir cevabı çoğaltan bir cevap göndermelisiniz ?
Dan Dascalescu

1
Benim hatam. Söz konusu yazıyı hiç görmedim. Sadece soruya baktım ve bir bıçak attım. Dikkatime sunduğunuz için teşekkürler.
Akinwale Folorunsho Habib

Rica ederim. İsterseniz yinelenen yanıtı da silebilirsiniz.
Dan Dascalescu
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.