對於重複 HTML 部分,我們可抽出 Component;對於重複 JavaScript 部分,我們可抽出 Module。
Version
Vue 3.2
Page
以最經典的 counter 來看看 Vue 3 如何抽出重複 JavaScript。
App.vue
<template>
<button @click='onClick'>+</button> {{ count }}
</template>
<script setup>
let count = $ref (0)
let onClick = _ => count++
</script>
假設 count
state 與 onClick
為 JavaScript 重複部分。
Module
功能不變,但抽出共用 module。
useCounter.js
import { ref } from 'vue'
export default _ => {
let count = ref (0)
let onClick = _ => count.value++
return {
count,
onClick
}
}
第 3 行
export default _ => {
return {
}
}
Module 基本上架構如下:
- 以 default export 宣告 anonymous function
- 最後以 return object 形式方便 destructure
其實這就是 JavaScript 著名的 Module Pattern,它使用 Closure 讓每個 component 有自己的 state
第 4 行
let count = ref (0)
let onClick = _ => count.value++
將原本 component 內重複的 JavaScript 複製貼上。
Vue 3.2 目前
$ref
只能用在 SFC,還無法用在 module 內
第 8 行
return {
count,
onClick
}
將要給 component 使用的 state 與 function 回傳。
因為可能建立不少 state 與小 function 內部使用,可藉由 Module Pattern 將 state 與 function 封裝在 module 內
App.vue
<template>
<button @click='onClick'>+</button> {{ count }}
</template>
<script setup>
import useCounter from '/src/modules/useCounter'
let { count, onClick } = useCounter ()
</script>
第 7 行
import useCounter from '/src/modules/useCounter'
從 useCounter
module 引用 useCounter
。
第 9 行
let { count, onClick } = useCounter ()
執行 useCounter
,並從回傳 Object 解構出 count
state 與 onClick
。
Component
同時使用兩個 <MyCounter>
component,可發現 count
state 各自爲政,不會互相影響。
MyCounter.vue
<template>
<button @click='onClick'>+</button>
<span>{{ count }}</span>
</template>
<script setup>
import useCounter from '/src/modules/useCounter'
let { count, onClick } = useCounter ()
</script>
建立 MyCounter
component,其內的 count
state 與 onClick
都來自於 useCounter
module。
App.vue
<template>
<MyCounter/>
<MyCounter/>
</template>
<script setup>
import MyCounter from '/src/components/MyCounter.vue'
</script>
從 MyCounter.vue
引用 MyCounter
,並在 HTML template 使用兩個 MyCounter
。
以上並沒有任何黑魔法就可使每個 component 有自己的
count
state 不互相影響,這都是拜 Module Pattern 與 Closure 之賜
Conclusion
- Component 與 Module 都能處理重複部分,唯 Component 是在處理重複 HTML;而 Module 是在處理重複 JavaScript
- Vue 3 的 module 本質就是 Module Pattern 與 Closure 應用,這使得每個 component 都有自己的 state,卻又能共享 JavaScript