vue3中單文件組件<script setup>實例詳解
一、相比普通script語法的優勢
<script setup>是在單文件組件 (SFC) 中使用組合式 API的編譯時語法糖。相比於普通的 <script> 語法,它具有更多優勢
- 更少的樣板內容,更簡潔的代碼
- 能夠使用純 Typescript 聲明 props 和拋出事件。
- 更好的運行時性能 (其模板會被編譯成與其同一作用域的渲染函數,沒有任何的中間代理)。
- 更好的 IDE 類型推斷性能 (減少語言服務器從代碼中抽離類型的工作)。
二、基本語法
要使用這個語法,需要將 setup attribute 添加到 <script> 代碼塊上
<script setup> console.log('hello script setup') </script>
裡面的代碼會被編譯成組件 setup() 函數的內容。這意味著與普通的 <script> 隻在組件被首次引入的時候執行一次不同,<script setup>中的代碼會在每次組件實例被創建的時候執行。
頂層的綁定會被暴露給模板
當使用 <script setup> 的時候,任何在 <script setup> 聲明的頂層的綁定 (包括變量,函數聲明,以及 import 引入的內容) 都能在模板中直接使用
<script setup> // 變量 const msg = 'Hello!' // 函數 function log() { console.log(msg) } </script> <template> <div @click="log">{{ msg }}</div> </template>
import 導入的內容也會以同樣的方式暴露。意味著可以在模板表達式中直接使用導入的 helper 函數,並不需要通過 methods 選項來暴露它:
<script setup> import { capitalize } from './helpers' </script> <template> <div>{{ capitalize('hello') }}</div> </template>
三、響應式
響應式狀態需要明確使用響應式 APIs 來創建。和從 setup() 函數中返回值一樣,ref 值在模板中使用的時候會自動解包:
<script setup> import { ref } from 'vue' const count = ref(0) </script> <template> <button @click="count++">{{ count }}</button> </template>
四、使用組件
<script setup>范圍裡的值也能被直接作為自定義組件的標簽名使用:
<script setup> import MyComponent from './MyComponent.vue' </script> <template> <MyComponent /> </template>
動態組件
由於組件被引用為變量而不是作為字符串鍵來註冊的,在 <script setup> 中要使用動態組件的時候,就應該使用動態的:is來綁定
<script setup> import Foo from './Foo.vue' import Bar from './Bar.vue' </script> <template> <component :is="Foo" /> <component :is="someCondition ? Foo : Bar" /> </template>
遞歸組件
- 一個單文件組件可以通過它的文件名被其自己所引用。例如:名為 FooBar.vue 的組件可以在其模板中用 <FooBar/> 引用它自己。
- 請註意這種方式相比於 import 導入的組件優先級更低。如果有命名的 import 導入和組件的推斷名沖突瞭,可以使用 import 別名導入:
import { FooBar as FooBarChild } from './components'
命名空間組件
- 可以使用帶點的組件標記,例如 <Foo.Bar>來引用嵌套在對象屬性中的組件。這在需要從單個文件中導入多個組件的時候非常有用:
<script setup> import * as Form from './form-components' </script> <template> <Form.Input> <Form.Label>label</Form.Label> </Form.Input> </template>
五、使用自定義指令
- 全局註冊的自定義指令將以符合預期的方式工作,且本地註冊的指令可以直接在模板中使用,就像上文所提及的組件一樣。
- 但這裡有一個需要註意的限制:必須以 vNameOfDirective 的形式來命名本地自定義指令,以使得它們可以直接在模板中使用
<script setup> const vMyDirective = { beforeMount: (el) => { // 在元素上做些操作 } } </script> <template> <h1 v-my-directive>This is a Heading</h1> </template>
<script setup> // 導入的指令同樣能夠工作,並且能夠通過重命名來使其符合命名規范 import { myDirective as vMyDirective } from './MyDirective.js' </script>
六、defineProps 和 defineEmits
在 <script setup> 中必須使用 defineProps 和 defineEmits API 來聲明 props 和 emits ,它們具備完整的類型推斷並且在 <script setup> 中是直接可用的
<script setup> const props = defineProps({ foo: String }) const emit = defineEmits(['change', 'delete']) // setup code </script>
- defineProps 和 defineEmits 都是隻在 <script setup> 中才能使用的編譯器宏。他們不需要導入且會隨著 <script setup> 處理過程一同被編譯掉。
- defineProps 接收與 props 選項相同的值,defineEmits 也接收 emits 選項相同的值
- defineProps 和 defineEmits 在選項傳入後,會提供恰當的類型推斷
- 傳入到 defineProps 和 defineEmits 的選項會從 setup 中提升到模塊的范圍。因此,傳入的選項不能引用在 setup 范圍中聲明的局部變量。這樣做會引起編譯錯誤。但是,它可以引用導入的綁定,因為它們也在模塊范圍內
七、defineExpose
- 使用 <script setup> 的組件是默認關閉的,也即通過模板 ref 或者 $parent 鏈獲取到的組件的公開實例,不會暴露任何在 <script setup> 中聲明的綁定。
- 為瞭在 <script setup> 組件中明確要暴露出去的屬性,使用 defineExpose 編譯器宏
<script setup> import { ref } from 'vue' const a = 1 const b = ref(2) defineExpose({ a, b }) </script>
- 當父組件通過模板 ref 的方式獲取到當前組件的實例,獲取到的實例會像這樣 { a: number, b: number } (ref 會和在普通實例中一樣被自動解包)
八、useSlots 和 useAttrs
- 在 <script setup> 使用 slots 和 attrs 的情況應該是很罕見的,因為可以在模板中通過 $slots 和 $attrs 來訪問它們。在你的確需要使用它們的罕見場景中,可以分別用 useSlots 和 useAttrs 兩個輔助函數
<script setup> import { useSlots, useAttrs } from 'vue' const slots = useSlots() const attrs = useAttrs() </script>
- useSlots 和 useAttrs 是真實的運行時函數,它會返回與 setupContext.slots 和 setupContext.attrs 等價的值,同樣也能在普通的組合式 API 中使用。
九、頂層 await
<script setup> 中可以使用頂層 await。結果代碼會被編譯成 async setup()
<script setup> const post = await fetch(`/api/post/1`).then(r => r.json()) </script>
- 另外,await 的表達式會自動編譯成在 await 之後保留當前組件實例上下文的格式
- 註意,async setup() 必須與 Suspense 組合使用,Suspense 目前還是處於實驗階段的特性
附:<script setup>和 <script>之間的主要區別
- 性能
<script setup>具有更好的運行時性能,因為它將模板編譯為具有相同作用域且沒有中間代理的呈現方法。<script>使用中間代理編譯模板。 - 代碼語法
在<script>塊中,我們需要導出帶有樣板代碼的模塊。<script setup>允許我們定義組件,而無需導出任何內容。在<script setup>塊中,我們可以使用更少的樣板文件獲得更簡潔的代碼。 - 執行流程
<script>塊在我們首次導入組件時執行。<script setup>塊將在每次創建組件實例時執行。 - 組織代碼
我們可以根據<script setup>塊中的業務邏輯來組織代碼。使用<script>塊是不可能的,因為我們必須遵循Vue的選項API或組合API的編碼結構。
總結
到此這篇關於vue3中單文件組件<script setup>詳解的文章就介紹到這瞭,更多相關vue3單文件組件<script setup>內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Vue3編程流暢技巧使用setup語法糖拒絕寫return
- vue3:setup語法糖使用教程
- 詳解vue3.2中setup語法糖<script lang="ts" setup>
- Vue3的7種種組件通信詳情
- Slots Emit和Props穿透組件封裝實現摸魚加鐘