背景
目前我們常見的有兩種引入
react
的方法:
import React from 'react';
// vs
import * as React from 'react';
這兩種寫法目前都可以運作,但是同一個目的出現兩種寫法就容易産生分歧,本文主要闡述這兩種寫法的不同并給出我建議的寫法。
便捷性
從便捷性角度來講,無疑第一種方式要少打好多字元。另外如果我們要引用
react
包内的其它導出項時,第一種方式的有點更明顯:
import React, { useState } from 'react';
export default function MyComponent() {
const [foo, setFoo] = useState();
return <div>{foo}</div>;
}
對比後一種寫法:
import * as React from 'react';
export default function MyComponent() {
const [foo, setFoo] = React.useState();
return <div>{foo}</div>;
}
這裡隻能通過
React
命名空間來引用内部導出項。
或者也可以單獨再導出一遍内部項:
import * as React from 'react';
import { useState } from 'react';
無論怎麼寫,都很難達到第一種寫法的便捷性。
文法和語義
ES 文法裡并沒有命名空間的文法,
export
關鍵字是作用于目前檔案的,是以隻有檔案是在 ES Module 語義下的命名空間。
export default
隻是
export
的一個特例,用于導出一個特殊的名字,并不能用來導出一個命名空間.有人還是習慣于用一個對象來模拟一個命名空間:
export default {foo, bar};
這種寫法并不符合 ES Module 的方式,建構工具是無法進行靜态分析,也無法進行
Tree Shaking。
更多關于
export default
的解釋可以參考
《export default 真的有害嗎?》從語義的角度來講,第一種寫法就是錯誤的,
React
僅僅是作為一個命名空間存在的,我們并不會像使用一個值一樣來使用
React
。從 React 16.13.0 開始,React 的導出方式也已經更正為
export {xxx, ...}
的形式了(
commit)。
之是以第一種導入方式還可以使用,是因為目前 React 的建構産物是 Commonjs 規範的,webpack 等建構工具做了相容。
自動導入
相對于語義的正确性,我覺得這一點便捷性是應該犧牲一下的,但是有沒有在不犧牲語義的情況下獲得便捷的方法?下面我們來聊聊自動導入。
正常情況,我們不需要使用
import * as
文法來導入一個包,但是 JSX 檔案的編譯需要
React
命名空間。既然 JSX 是文法層面的擴充,那麼把這個命名空間的導入也放到文法層面去解決也是理所當然的。
babel-plugin-transform-react-jsx 的自動導入模式目前隻在 React 17 中可用,針對之前的版本,我們可以使用非官方的
babel-plugin-auto-import插件。
總結
如何導出決定如何導入。
按順序簡要列一下可選的導入方案:
- 【最佳方案】自動導入
- 【相容性好】
import * as React from 'react';
- 【不再推薦】
import React from 'react';
思考題
下面兩種導入樣式的寫法有什麼差別?應該選擇哪種?
-
import * as styles from './index.module.scss
-
import styles from './index.module.scss
提示:
https://webpack.js.org/loaders/style-loader/#esmodule