iT邦幫忙

2022 iThome 鐵人賽

DAY 7
2
Modern Web

真的好想離開 Vue 3 新手村 feat. CompositionAPI系列 第 7

真的好想離開 Vue 3 新手村 - Day 7: 深入了解 <script setup> 語法糖

  • 分享至 

  • xImage
  •  

誰適合看這篇

  • 想知道 <script setup> 的優點
    • 跟我一樣很好奇為什麼 <script setup> 效能比較好
  • <script setup>太好用,不知道什麼時候需要用 <script>

前言

在 Vue 3 Composition API 的中,寫法上主要分成 <script>(+setup()) 和 <script setup> 兩種,核心概念相同,後者是前者的語法糖,相當好吃,只能說...「曾經滄海難為水」(?),連官方也推推。

既然如此,那...為什麼還需要 <script>

今天就一起來了解。

Outline:

  • 理解 <script setup> 的優點
    • 程式碼更簡潔
    • 運行性能比較好
  • 什麼時候需要 <script>

註:不包含兩者基礎語法的完整比較

理解 <script setup> 的優點

官方推薦使用這個語法,提到他比起一般的 script 寫法多了以下優點:

  1. 更少的样板内容,更简洁的代码。
  2. 能够使用纯 TypeScript 声明 props 和自定义事件。
  3. 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
  4. 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。

文件出處

今天的內容會著重在第一點和第四點。

更簡潔的程式碼

在能使用 <script setup> 正式推出之前,在 <script> 必須這樣寫。
setup() 裡定義會用到的變數、函式、計算屬性 (computed) 等等,並將模板上要用到的變數 return 出來。

Before: <script>

<script>
    import { ref } from 'vue'

    export default {
      setup() {
        const count = ref(1)
        const increaseCount = () => {
          count.value++
        }

        return {
            count,
            increase
        }
      }
    }
</script>

After: <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>具有「更好的运行时性能」(其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)
/images/emoticon/emoticon19.gif嗯...這到底是什麼意思,讓我們在下一個小節來深入了解。

更好的運行效能

其實這個也不算很重要,但因為我很好奇 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.jsbuild.minify 設為 false 即可。

// 在 `vite.config.js` 中加入這段
build: {
    minify: false,
}

什麼情境會需要一般的 script?

<scrip setup> 語法糖這麼好用,我們還需要一般的 <script> 嗎?

要!

官方就有提到某些特定情境,只能使用一般 script 才能做到:

  • 具名輸出 (Named Export)
  • 宣告其他 Options,如:nameinheritAttrs或其他插件需要的指定 Option
  • 只要執行一次的 Side Effect
    • 一般 <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>

參考資料


上一篇
真的好想離開 Vue 3 新手村 - Day 6: 什麼是 Vue SFC 檔?如何被編譯?feat. Vite
下一篇
真的好想離開 Vue 3 新手村 - Day 8: 認識 Vue directive 和 v-if v.s v-show
系列文
真的好想離開 Vue 3 新手村 feat. CompositionAPI31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Wolke
iT邦研究生 5 級 ‧ 2023-01-10 16:31:09

@click
v-show
的參數 寫在 script setup 不會動

我要留言

立即登入留言