前端JavaScript模塊化解析之ESModule用法示例
基本介紹
- JavaScript沒有模塊化一直是它的痛點,所以才會產(chǎn)生我們前面學習的社區(qū)規(guī)范:
CommonJS
、AMD
、CMD
等
所以在ES推出自己的模塊化系統(tǒng)時,大家也是興奮異常。 - ES Module和CommonJS的模塊化有一些不同之處
- 一方面它使用了import和export關鍵字:
- 另一方面它采用編譯期的靜態(tài)分析,并且也加入了動態(tài)引用的方式
- ES Module模塊采用export和import關鍵字來實現(xiàn)模塊化
- export負責將模塊內(nèi)的內(nèi)容導出,
- import負責從其他模塊導入內(nèi)容;
- 了解:采用ES Module將自動采用嚴格模式:use strict
基本使用
// foo.js export const name = "why" export const age = "18"
// main.js import {name,age} from "./foo.js" console.log(name) console.log(age)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <!--這里必須設置 type="module" 否則瀏覽是無法識別的--> <script src="main.js" type="module"></script> </body> </html>
讓模塊化生效的兩個前提條件
- script標簽要加上 type=“module”
- index.html的訪問必須是以服務器的方式訪問。也就是訪問協(xié)議必須是
http
或者https
直接本地文件打開file://
這個協(xié)議是不支持的
導入導出方式3種
// foo.js // 導出方式 // 1. 第一種方式: export 聲明語句 export const name = "why" export const age = "18" export function foo(){ console.log("foo function") } export class Person {}
// 2. 第二種: export 導出 和 聲明分開 const name = "why" const age = "18" function foo(){ console.log("foo function") } export { name, age, foo }
// 3. 第三種方式:第二種導出時起別名 const name = "why" const age = "18" function foo(){ console.log("foo function") } export { name as fName, age as fAge, foo as fFoo }
導入方式
// 導入方式 // 1.導入方式1:普通導入 import {name,age,foo,Person} from "./foo.js" // 2.導入方式二:起別名 import {name as fName,age as fAge,foo as fFoo} from "./foo.js" // 3.導入方式三:將所有哦的內(nèi)容放到一個標識符中 import * as foo from "./foo.js" console.log(foo.name) console.log(foo.age) console.log(name) console.log(age)
結合使用
當我們某個目錄下有很多js文件,導出了很多工具方法如下
// utils/math.js function add(a,b){ return a+b; } function sub(a,b){ return a-b } export { add, sub }
// utils/format.js function timeFormat(){ return "2222-12-12" } function priceFormat(){ return "222.22" } export { timeFormat, priceFormat }
然后在main.js中引入這些模塊的函數(shù),代碼會變的很麻煩如下
// main.js import {add,sub} from "./utils/math.js" import {timeFormat,priceFormat} from './format.js'
因此一般在utils
目錄下會統(tǒng)一定義一個index.js
用來將該目錄下的所有需要導出的變量進行一個統(tǒng)一導出。如下
這樣mian.js
就可以只導入utils/index.js
即可
// utils/index.js // 導出方式一 import {add,sub} from './math.js' import {timeFormat,priceFormat} from './format.js' export { add, sub, timeFormat, priceFormat }
導出方式一還是顯得太復雜,可以結合使用
// utils/index.js // 導出方式二: export {add,sub} from './math.js' export {timeFormat,priceFormat} from './format.js' // 如果要全部導出可如下寫法 // 導出方式三: export * from './math.js' export * from './format.js'
default用法
當寫的某一個變量,是非常常用的時候,可以使用默認導出。默認導出的方式如下
// foo.js const name = "zxh" const age = 18 const foo = 'foo value' // 1.默認導出的方式一: export { name, age, foo as default } // 2.默認導出的方式二:常見 export default foo // 注意默認導出只能有一個
main.js
在導入默認導出的變量時 如下使用
// 不用進行結構,可自定義接收的變量名 實際上是將 foo.js中的 foo賦值到aaa上 import aaa from './foo.js' console.log(aaa)
import函數(shù)
如下代碼,在執(zhí)行的時候是同步執(zhí)行的,
首先瀏覽會先將要導入的文件下載下來,進行解析,然后才會執(zhí)行后續(xù)的代碼。
import {name,age,foo} from './foo.js' console.log("導入的代碼沒有解析完之前,后續(xù)的代碼是不會運行的")
如果希望異步執(zhí)行:比如頁面初始化的時候并不需要用到導出的函數(shù),只是在特定時候才需要使用。那么就可以使用import函數(shù)來進行異步執(zhí)行
import("./foo.js").then(res=>{ console.log("res:",res.name) }) console.log("main.js 執(zhí)行成功")
// 查看控制臺輸出,可以看出是異步執(zhí)行 main.js 執(zhí)行成功 res:zxh
ES Module的解析流程
具體流程省略
導入的變量無法,導入方無法修改
需要重點提醒一下:導出的變量,是不允許在導入端被修改的
如下
// foo.js export let name = "zifeiyu"
import {name} from "./foo.js" // 這里修改是會報錯的 name = 333
// 控制臺報錯 Uncaught TypeError: Assignment to constant variable. at main.js:3:6
導出的變量,只能由導出方進行修改
// foo.js export let name = "zifeiyu" setTimeout(() => { name = "Kobe" },100)
// main.js import {name} from "./foo.js" console.log(name) setTimeout(()=>{ console.log(name) },2000)
可以看到控制臺輸出,說明導出方可以修改這個值
zifeiyu Kobe
如果確實想在導入這邊對導出的值進行修改,可以自定義set回調(diào)函數(shù)
// foo.js export let name = "zxh" export function setName(a){ name = a }
import {name,setName} from "./foo.js" console.log(name) setName(3333333) console.log(name)
CommonJS和ESModule相互引用
解釋一下:
- 模塊A通過commonJS進行導出,然后模塊B通過ESModule的方式進行導入。
- 模塊C通過ESModule的方式進行導出,然后模塊B通過commonJS的方式進行導入。
能否實現(xiàn)呢?
得分情況
- 瀏覽器:不能實現(xiàn),因為默認不支持
CommonJS
- node環(huán)境下:分情況
- 之前的node版本,只支持
CommonJS
- 現(xiàn)在node版本逐漸在轉(zhuǎn)用
ESModule
- 之前的node版本,只支持
- 正常開發(fā)環(huán)境
webpack
: 可以使用
實驗一下
# 在一個干凈的目錄下 # 1.通過npm幫我們初始化一下項目,也就是生成 package.json npm init # 2.要使用webpack 需要安裝 webpack 和 webpack-cli npm install webpack webpack-cli -D # 3.新建目錄src,因為webpack默認的打包入庫是 src/index.js
編寫幾個js進行互相引用
這邊案例是打算
- foo.js 通過commonjs導出
- bar.js 通過ESmodule導出
- index.js
- 通過ESmodule 導入
foo.js
- 通過commonjs導入
bar.js
- 通過ESmodule 導入
代碼如下
// src/foo.js const fooName = "foo" const fooAge = 18 // commonjs導出 module.exports = { fooName, fooAge }
// src/bar.js const barName = "foo" const barAge = 18 // esmodule導出 export{ barName, barAge }
// src/index.js es module import { fooName, fooAge } from "./foo" console.log(fooName, fooAge) // commonjs 導入 const {barName,barAge} = require('./bar') console.log(barName, barAge)
# 打包 會在當前命令所在目錄下 創(chuàng)建一個dist文件夾 dist文件夾下會有一個main.js npx webpack
在當前目錄下創(chuàng)建index.js
對打包后的js進行引用即可
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <script src="dist/main.js"></script> </body> </html>
瀏覽器訪問可以看到正常輸出,說明互相引用是可以的。
具體原理還得看main.js
webpack打包出來的文件
總結
到此這篇關于前端JavaScript模塊化解析之ESModule用法示例的文章就介紹到這了,更多相關JS模塊化ESModule內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Bootstrap 設置datetimepicker在屏幕上面彈出設置方法
datetimepicker默認是在輸入框下面彈出的,但是遇到輸入框在屏幕下面時,日期選擇框會有一部分在屏幕下面,顯示不了,因此需要能夠從上面彈出,下面小編給大家介紹下Bootstrap 設置datetimepicker在屏幕上面彈出的設置方法2017-03-03使用JavaScript實現(xiàn)點擊循環(huán)切換圖片效果
本文通過實例代碼給大家介紹了通過js實現(xiàn)點擊循環(huán)切換圖片效果,需要的朋友參考下2017-09-09IE的事件傳遞-event.cancelBubble示例介紹
關于event.cancelBubble,Bubble就是一個事件可以從子節(jié)點向父節(jié)點傳遞,下面有個不錯的示例,大家可以感受下2014-01-01js解析xml字符串和xml文檔實現(xiàn)原理及代碼(針對ie與火狐)
分別針對ie和火狐分別作了對xml文檔和xml字符串的解析,考慮到了瀏覽器的兼容性,至于在ajax環(huán)境下解析xml,其實原理是一樣的,只不過放在了ajax里,還是要對返回的xml進行解析,感興趣的朋友可以了解下,或許對你學習js解析xml有所幫助2013-02-02