詳解vue3.2中setup語法糖<script lang="ts" setup>

前言

介紹 Vue 3 引入瞭 Composition API 作為一種在 Vue 應用程序中處理反應狀態的新方法。您可以按功能(用戶、API、表單)對代碼進行分組,而不是按功能(數據、計算、方法、監視等)組織代碼。這在構建 Vue 應用程序時允許更大的靈活性。我們已經在其他文章中討論過 Composition(如果您還沒有閱讀,請查看它們!),但是隨著 Vue 3.2 的發佈,另一個與 Composition 相關的功能已經穩定發佈 – <script setup>

簡而言之,<script setup>允許開發人員定義組件而無需從 JavaScript 塊中導出任何內容 – 隻需定義變量並在模板中使用它們!這種編寫組件的風格在很多方面都類似於 Svelte,對於第一次接觸 Vue 的人來說,這是一個巨大的改進。

<script lang=“ts“ setup>

<script setup>是一種編譯時語法糖,用於在單文件組件 (SFC) 中使用組合 API。如果同時使用 SFC 和組合 API,則這是建議的語法。與正常語法相比,它提供瞭許多優點:

  • 更簡潔的代碼,更少的樣板
  • 能夠使用純 TypeScript 聲明 props 和發出的事件
  • 更好的運行時性能(模板編譯為同一作用域中的渲染函數,無需中間代理)
  • 更好的 IDE 類型推斷性能(語言服務器從代碼中提取類型的工作量更少)

<script setup>基本

讓我們看一個例子。如果您使用的是 Options API(Vue 2 的標準),那麼您的所有單文件組件將如下所示:

<template>
  <div>Hello, {{ name }}!</div>
  <input v-model="name" />
  <button :disabled="!isNamePresent" @click="submitName">Submit</button>
</template>
 
<script>
export default {
  data() {
    return {
      name: ''
    }
  },
  computed: {
    isNamePresent() {
      return this.name.length > 0
    }
  },
  methods: {
    submitName() {
      console.log(this.name)
    }
  }
}
</script>

我們有我們的模板(一個簡單的表單)和我們的腳本塊。在腳本塊中,我們導出一個具有三個鍵的對象:名稱、計算和方法。如果你熟悉 Vue,這對你來說應該很熟悉。現在,讓我們切換此代碼以使用 Composition API。

<template>
  <div>Hello, {{ name }}!</div>
  <input v-model="name" />
  <button :disabled="!isNamePresent" @click="submitName">Submit</button>
</template>
 
<script>
import { ref, computed } from 'vue'
 
export default {
  setup() {
    const name = ref('')
    const isNamePresent = computed(() => name.value.length > 0)
 
    function submitName() {
      console.log(name.value)
    }
 
    return {
      name,
      isNamePresent,
      submitName
    }
  }
}
</script>

我們的組件做的事情和以前完全一樣。我們定義瞭狀態(名稱)、計算屬性(isNamePresent)和提交函數。如果其中任何一個不熟悉,請查看我之前關於 Vue Composition API 的文章。我們不必在要導出的對象中搭建我們的應用程序,而是可以根據需要自由定義變量。這種靈活性還允許我們根據需要從組件中提取重復的邏輯,但在這種情況下,我們的組件非常簡單。

但是,我們仍然有那個尷尬的export default說法。我們的代碼都存在於 setup 函數中,而其餘的實際上隻是樣板文件。我們不能直接刪除它嗎?事實上,我們現在可以!這就是

<template>
  <div>Hello, {{ name }}!</div>
  <input v-model="name" />
  <button :disabled="!isNamePresent" @click="submitName">Submit</button>
</template>
 
<script setup>
import { ref, computed } from 'vue'
 
const name = ref('')
const isNamePresent = computed(() => name.value.length > 0)
 
function submitName() {
  console.log(name.value)
}
</script>

讓我們來看看這裡發生瞭什麼變化。首先,我們在腳本標簽中添加瞭“setup”這個詞,這為編寫 Vue 組件啟用瞭這種新模式。其次,我們從setup函數中獲取我們的代碼,並僅用我們的代碼替換我們現有的導出對象。一切都按預期工作!

請註意,在腳本標簽中聲明的所有內容都在組件的模板中可用。這包括非反應性變量或常量,以及實用函數或其他庫。這樣做的主要好處是您不需要手動將外部文件(例如,Constants.js)綁定為組件的值 – Vue 現在會為您處理這個問題。

基本語法

要選擇加入語法,請將該屬性添加到塊中:setup``<script>

<script setup>
      console.log('hello script setup')
</script>

內部代碼被編譯為組件函數的內容。這意味著與正常不同,普通僅在首次導入組件時執行一次,每次創建組件的實例時,內部代碼都會執行。setup()

頂級綁定向模板公開# 使用 時,其中聲明的任何頂級綁定(包括變量、函數聲明和導入)都可以直接在模板中使用:<script setup><script setup>

<script setup>
// variable
const msg = 'Hello!'
 
// functions
function log() {
  console.log(msg)
}
</script>
 
<template>
  <div @click="log">{{ msg }}</div>
</template>

進口以同樣的方式公開。這意味著您可以在模板表達式中直接使用導入的幫助程序函數,而不必通過以下選項公開它:methods

<script setup>
  import { capitalize } from './helpers'
</script>
 
<template>
  <div>{{ capitalize('hello') }}</div>
</template>

Reactivity

需要使用Reactivity API 顯式創建響應式狀態。與從函數返回的值類似,在模板中引用 ref 時會自動解開包裝:setup()

<script setup>
import { ref } from 'vue'
 
const count = ref(0)
</script>
 
<template>
  <button @click="count++">{{ count }}</button>
</template>

定義組件

使用時<script setup>,我們不必再手動定義我們導入的組件瞭。通過將組件導入文件,編譯器能夠自動將其添加到我們的應用程序中。讓我們通過將表單抽象為它自己的組件來更新我們的組件。我們將它命名為 Form.vue。現在,它隻是模板,我們稍後會討論邏輯。

<!-- Form.vue -->
<template>
  <form @submit.prevent="submitHandler">
    <label>Name
      <input type="text" />
    </label>
    <button>Submit</button>
  </form>
</template>
 
<script setup>
function submitHandler() {
  // Do something
}
</script>
 
<!-- App.vue -->
<template>
  <div>Hello, {{ name }}!</div>
  <Form />
</template>
 
<script setup>
import { ref } from 'vue'
import Form from './components/Form.vue'
 
const name = ref('')
 
function submitForm() {
  console.log(name.value)
}
</script>

而已!我們的組件現在必須導入到我們的 Vue 文件中,並且它會自動在我們的模板中可用。不再有components塊占用我們文件中的空間!

現在,我們需要將name子組件作為道具傳遞給我們。但是等等,我們不能定義道具!我們沒有要添加 props 選項的對象!此外,我們需要發出表單已提交,以便我們可以觸發我們的提交。我們如何定義子組件發出的內容?

defineProps和defineEmits 我們仍然可以使用新的輔助方法defineProps和defineEmits. 來自 Vue 文檔,“defineProps並且defineEmits是編譯器宏,隻能在內部使用<script setup>。它們不需要導入,在<script setup>處理時會被編譯掉。” 這些編譯時函數采用與標準鍵與完整導出對象一起使用的相同參數。讓我們更新我們的應用程序以使用defineProps和defineEmits。

<!-- Form.vue -->
<template>
  <form @submit.prevent="submitHandler">
    <label>Name
      <input v-model="name" type="text" />
    </label>
    <button>Submit</button>
  </form>
</template>
 
<script setup>
import { computed } from 'vue'
const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  }
})
const emit = defineEmits(['update:modelValue', 'submit']);
 
const name = computed({
  get () {
    return props.modelValue
  },
  set(val) {
    emit('update:modelValue', val);
  }
})
 
function submitHandler() {
  emit('submit')
}
</script>
 
<!-- App.vue -->
<template>
  <div>Hello, {{ name }}!</div>
  <Form v-model="name" @submit="submitForm" />
</template>
 
<script setup>
import { ref } from 'vue'
import Form from './components/Form.vue'
 
const name = ref('')
 
function submitForm() {
  console.log(name.value)
}
</script>

讓我們來看看這裡發生瞭什麼變化。

首先,我們曾經defineProps期望一個 modelValue(在 Vue 3 中與 v-model 一起使用的預期道具)。 然後我們用 定義瞭我們的發射defineEmits,這樣我們既可以報告這個組件發射的內容,也可以訪問該emit函數(以前在 `this.$emit 上可用)。 接下來,我們創建一個使用自定義 getter 和設置的計算屬性。我們這樣做是為瞭可以輕松地在表單輸入中使用 v-model,但這不是必需的。getter 返回我們的 prop,setter 將更新事件發送到我們的父組件。 最後,我們連接瞭 submitHandler 函數來發出一個提交事件。 我們的 App.vue 組件或多或少與我們離開它時一樣,添加v-model="name"瞭@submit="submitForm"Form 子組件。這樣,我們的應用程序再次按預期工作!

其它功能 這裡有更多功能可供我們使用,但它們在典型應用程序中的用例較少。

動態組件- 由於我們的組件在模板中立即可用,我們可以在編寫動態組件時使用它們(例如)。 命名空間組件- 如果您有許多從同一文件導入的組件,則可以使用import * as Form語法對這些組件進行命名空間。然後,您無需任何額外工作即可訪問<Form.Input>或。<Form.Submit> Top-Level Await – 如果您需要將 API 請求作為組件設置的一部分,您可以在組件的頂層自由使用 async/await 語法 – 無需包裝在 async 函數中!請記住,使用它的組件必須由組件在外部包裹

要記住的另一點是,您並沒有被鎖定在使用<script setup>. 如果您將這種新語法用於組件並遇到無法完成某事的情況,或者隻是想對特定情況使用 Options 語法,您可以通過添加一個額外的. 有關這方面的一個很好的例子,請參閱 Vue 文檔。

結論

這是 Vue 和 Composition API 向前邁出的一大步。事實上,Evan You 已經公開表示,這是為瞭成為 Vue 單文件組件未來的標準語法。來自Github 上的討論: 這有一些歷史,因為關於 Composition API 的最初提案表明打算用它完全取代 Options API,但遭到瞭強烈反對。盡管我們確實相信Composition API 從長遠來看有潛力成為“前進的道路”,但我們意識到(1)仍有人機工程學/工具/設計問題需要解決,(2)范式轉變不能一天之內完成。在我們可以自信地向所有 Vue 用戶推薦新的東西之前,我們需要時間和早期采用者來驗證、嘗試、采用和試驗新范式。

這實質上導致瞭一個“過渡期”,在此期間我們有意避免將 Composition API 聲明為“新方式”,以便我們可以執行驗證過程並與主動采用它的用戶子集一起構建周圍的工具/生態系統。

現在<script setup>,隨著 IDE 工具支持的改進,我們相信 Composition API 已達到為大多數用戶提供卓越 DX 和可擴展性的狀態。但我們需要時間來達到這一點。

在同一線程的早些時候,Evan 表達瞭他對 Vue 未來發展的看法:

目前推薦的方法是:

使用 SFC <script setup>++ 組合 API 使用 VSCode + Volar(或 WebStorm,一旦它支持<script setup>即將發佈) TS 沒有嚴格要求,但如果適用,請使用 Vite 構建工具。

到此這篇關於vue3.2中setup語法糖&lt;script lang="ts" setup&gt;的文章就介紹到這瞭,更多相關vue3.2中setup語法糖內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: