天天看點

script setup 文法使用

vue3.2正式版已經釋出,script setup文法已經由實驗性質改為了正式文法,可以放心大膽的在項目中用了。

官方文檔:https://v3.cn.vuejs.org/api/sfc-script-setup.html#basic-syntax

相比于正常的composition api文法,script setup文法更加簡練友善,不過它本身隻是個文法糖,最終還是轉換為composition api文法運作。官方文檔純英文且不夠詳細,下面分享一下個人整理的文法使用方式。

  • 看這篇文章之前需先提前熟悉vue3新文法變化
  • vue版本:v3.2.3
  • 使用ts

1、基礎用法

<template>
  <Foo :count="count" @click="inc" />
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import Foo from './Foo.vue'

const count = ref(0)
const inc = () => {
  count.value++
}
</script>
           
  • 不需要return任何東西,所有定義的變量和方法會自動導出,template模闆可以直接使用
  • import引入的元件也會自動導出,模闆裡可以直接引用。
  • 引入的元件命名需要首字母大寫。
  • 确切的說是:所有的變量方法和import導入都可以在模闆中直接使用。

2、定義props、emit

<template>
  <div @click="onClick">{{foo}}</div>
</template>

<script lang="ts" setup>
import { defineProps, defineEmits } from 'vue'
// 定義props屬性
const props = defineProps({
  foo: {
    type: String,
    default: '',
  }
})
// 定義emit事件
const emit = defineEmits({
  'onSubmit': null,
})

function onClick () {
  emit('onSubmit', { val: props.foo })
}
</script>
           
  • 定義的props裡的屬性可以直接在template模闆中使用。

3、自定義指令 directives

<template>
  <div v-click-outside />
</template>

<script lang="ts" setup>
import { directive as vClickOutside } from 'v-click-outside'
</script>
           
  • 特殊點就是命名方式,script中使用駝峰命名,template中使用短橫線命名。

4、defineExpose

這個defineExpose是幹什麼的呢,因為script setup預設是不對外界暴露元件執行個體的,是以在其他元件中通過諸如

$refs

$parent

都預設無法擷取目前元件執行個體,但是通過defineExpose暴露的可以擷取。(這個設計非常好,對于防止代碼耦合很有用)

  • 子元件

    Child.vue

<script lang="ts" setup>
import { ref } from 'vue'

const aaa = 1
const bbb = ref(2)
const ccc = ref(3)

defineExpose({
  aaa,
  bbb
})
</script>
           
  • 父元件:
<template>
  <Child ref="refChild" />
  <div @click="onClick">123</div>
</template>

<script lang="ts" setup>
import Child from './Child.vue'

const refChild = ref<any>(null) // 定義同名ref,和template模闆中Child的ref屬性同名,即可代表Child元件執行個體

function onClick () {
  console.log(refChild.value) // { aaa: 1, bbb: 2 }
}
</script>
           
  • onClick方法中列印了Child元件執行個體,隻會存在defineExpose暴露出的變量。

5、使用 slots 和 attrs

<script lang="ts" setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>
           
  • 通過useSlots和useAttrs來定義,達到類似

    $slots

    $attrs

    的效果。
  • 在進階元件封裝中,

    $slots

    主要用于擷取作用域插槽,典型應用場景:base基礎元件的封裝;

    $attrs

    主要用于擷取父元件綁定屬性,典型應用場景:第三方元件的二次封裝。具體使用方式比較複雜,這裡不再贅述。

6、結合普通script

有些setup()之外的配置項在script setup中不适用,可以結合普通script一起使用。

<script lang="ts">
// 普通<script>, 隻會執行一次
runSideEffectOnce()

// 聲明一些額外的配置選項
export default {
  name: 'CompName',
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script lang="ts" setup>
// script setup文法區域
</script>
           

7、頂層作用域下使用await

在script setup下的頂層作用域下可以直接使用await,

<script setup>
const post = await fetch(`/api/post/1`).then(r => r.json())
</script>
           
  • 這個功能必須結合

    <suspense>

    使用,目前

    <suspense>

    還在試驗階段,未來應該會成為vue正式功能,官方文檔:https://v3.cn.vuejs.org/guide/migration/suspense.html#%E4%BB%8B%E7%BB%8D

8、vscode插件:Volar

script setup文法推薦使用Volar擴充插件配合使用,效果和Vetur類似,但是對script setup文法的相容性更好。

需要注意Volar和Vetur兩個是互斥的,使用Volar時要記得禁用Vetur。