<script setup>
的優點
<script setup>
效能比較好<script setup>
太好用,不知道什麼時候需要用 <script>
在 Vue 3 Composition API 的中,寫法上主要分成 <script>
(+setup()
) 和 <script setup>
兩種,核心概念相同,後者是前者的語法糖,相當好吃,只能說...「曾經滄海難為水」(?),連官方也推推。
既然如此,那...為什麼還需要 <script>
?
今天就一起來了解。
<script setup>
的優點
<script>
註:不包含兩者基礎語法的完整比較
<script setup>
的優點官方推薦使用這個語法,提到他比起一般的 script 寫法多了以下優點:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 TypeScript 声明 props 和自定义事件。
- 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
- 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。
今天的內容會著重在第一點和第四點。
在能使用 <script setup>
正式推出之前,在 <script>
必須這樣寫。
在 setup()
裡定義會用到的變數、函式、計算屬性 (computed) 等等,並將模板上要用到的變數 return
出來。
<script>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(1)
const increaseCount = () => {
count.value++
}
return {
count,
increase
}
}
}
</script>
<script setup>
透過在 <script>
加上 setup
的屬性,Vue 會幫開發者將裡面的邏輯,包到 setup()
內,並將所有 top-level binding 自動暴露給模板。
<script setup>
import { ref } from 'vue'
const count = ref(1)
const increaseCount = () => {
count.value++
}
</script>
直接省略了 6+n 行程式碼,不用一直重複寫:
export default {
setup(){
return {
//暴露屬性給模板使用 +n 行
}
}
}
根據官方文件,<script setup>
具有「更好的运行时性能」(其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)
嗯...這到底是什麼意思,讓我們在下一個小節來深入了解。
其實這個也不算很重要,但因為我很好奇 again
在上一篇有提到,SFC 檔會從 <template>
和 <script>
中取得內容,編譯出元件的渲染函式。
而 <script>
和 <script setup>
在效能上的差異,就在於渲染函式從 <script>
中取得 <template>
所需變數的方式不同。
<script>
+ setup()
setup()
函式和渲染函式會分開宣告,各自形成自己的閉包。
所以,宣告在 setup()
內的變數需要 return
出去,才能傳給渲染函式,在渲染 template 的時候才能取用到所有變數。
<script setup>
:不需要經過中間代理,運行時效能比較好。
元件的渲染函式會存在在 setup()
的 scope 內,也就是將渲染函式寫在 setup
的閉包內,最後才回傳出去。
所以,渲染函式可以透過閉包拿到外層 setup
函式 (<script setup>
) 內,所有 top-level 變數(包含:變數、函式和 imports
),也不用擔心洩漏過多變數或邏輯。
官方文件中有提到,在開發過程中,基於開發工具檢查和模板熱重載的原因,使用 <script setup>
建立的元件,還是會被編譯成回傳物件,而不是直接回傳渲染函式。
也就是說,想看到 <script setup>
和 <script>
差別,要看正式編譯打包後的版本(npm run build
)。
「打包出來的程式碼那麼難看,是要看個毛線?」
到 vite.config.js
將 build.minify
設為 false
即可。
// 在 `vite.config.js` 中加入這段
build: {
minify: false,
}
<scrip setup>
語法糖這麼好用,我們還需要一般的 <script>
嗎?
官方就有提到某些特定情境,只能使用一般 script 才能做到:
name
、inheritAttrs
或其他插件需要的指定 Option<script>
會在初次載入元件時執行一次,但每次載入元件都會呼叫 setup()
hook<script setup>
將所有邏輯都放到 setup()
內,所有每次渲染時都會執行所有程式碼,只想執行一次的程式碼要放在 <script>
在以上情境下,可以在元件內同時使用 <script setup>
和 <script>
,如下:
<script>
// normal <script>, executed in module scope (only once)
runSideEffectOnce()
// declare additional options
export default {
inheritAttrs: false,
customOptions: {}
}
</script>
<script setup>
// executed in setup() scope (for each instance)
</script>