<script setup>语法

313 阅读1分钟

setup选项

新的setup选项在组件创建之前执行,一旦props被解析,就将作为组合式API的入口。

setup中你应该避免使用this,因为它不会找到组件实例。setup的调用发生在dataproperty、computedproperty或methods被解析之前,所有它们无法在setup中被获取。 setup选项是一个接收propscontext函数,此外,我们将setup返回的所有内容都暴露给组件的其余部分(计算属性、方法、生命周期钩子等等)以及组件的模板。

<script setup>语法糖

<script setup>是在单文件组件SFC中使用组合式API的语法糖。相比于普通的<script>语法,它具有更多优势:

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯TypeScript声明props和抛出事件。
  • 更好的运行时性能(其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)
  • 更好的IDE类型推断性能(减少语言服务器从代码中抽离类型的工作)。

1.基本用法

要使用这个语法,需要将setup属性添加到<script>代码块上:

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

上面的代码会被编译成组件setup()函数的内容。这意味与普通的<script>只在组件被首次引入的时候执行一次不同,<script setup>中的代码会在 每次组件实例被创建的时候执行

当使用<script setup>的时候,任何在<script setup>声明的顶层的绑定(包括变量、函数声明、以及import引入的内容)无需return都能在模板中直接使用:

<template>
    <div @click="log">{{msg}}</div>
    <button @click="count++">{{count}}</button>
    <!-- 使用组件 -->
    <Child />
</template>
<script setup>
    import { ref } from 'vue'
    import Child from './Child.vue'
    
    // 变量
    const msg = 'hello!'
    // 函数
    function log () {
      console.log(msg)
    }
    // 响应式
    const count = ref(0)
</script>

2.defineProps和defineEmits

<script setup>中必须使用definePropsdefineEmitsAPI来声明propsemits,它们具备完整的类型推断并且在<script setup>是直接可用的:

<script setup>
    import { defineProps, defineEmits } from 'vue'
    
    const props = defineProps({
        msg: String
    })
    const emits = defineEmits(['change', 'delete'])
</script>
  • definePropsdefineEmits都是只在<script setup>中才能使用的 编译器宏
  • defineProps接收与props选项相同的值,defineEmits接收与emits选项相同的值;
  • definePropsdefineEmits在选项传入后,会提供恰当的类型推断;
  • 传入到definePropsdefineEmits的选项会从setup中提升到模块的范围。

3.父子组件传值

  • Father.vue父组件
<template>
  <div>
    我是父组件
    <Child :msg="msg" @change-msg="handleChange" />
  </div>
</template>

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

    const msg = ref('abcdef')
    const handleChange = () => {
      msg.value = 'aaaaaa'
    }
</script>
  • Child.vue子组件
<template>
  <div>
    <p>我是子组件,msg: {{props.msg}}</p>
    <button @click="changeMsg">修改msg</button>
  </div>
</template>

<script setup lang="ts">
    import { defineProps, defineEmits } from 'vue'

    const props = defineProps({
      msg: String
    })
    const emits = defineEmits(['changeMsg'])
    const changeMsg = () => {
      emits('changeMsg', params)
    }
</script>

4.useSlots和useAttrs

<script setup>使用slotsattrs的情况应该是很罕见的,因为可以在模板中通过$slots$attrs来访问它们。如果要使用,可以分别用useSlotsuseAttrs两个辅助函数:

<template>
  <div>
    <p>msg: {{attrs.msg}}</p>
  </div>
</template>

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

    const attrs = useAttrs()
</script>