这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
在单文件组件(SFC)中引入一个新的 <script>
类型 setup。它向模板公开了所有的顶层绑定。
组件
组件直接引入即可使用,无需注册
引入的组件可以直接用作自定义组件标签名,类似于 JSX 中的工作方式。
<template>
<div>
<Foo />
</div>
</template>
<!-- 在script标签上添加setup属性,以使用 script setup 语法 -->
<script setup>
import Foo from './components/Foo.vue'
</script>
复制代码
属性和方法
属性和方法无需挂载到对象上后再次返回
<template>
<div>
<Foo />
<h2 @click="increment">{{ count }}</h2>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Foo from './components/Foo.vue'
const count = ref(0)
const increment = () => count.value++
</script>
复制代码
上述案例会被编译为
// 导入的模块会被抽离到模块级别
import { ref } from 'vue'
import Foo from './components/Foo.vue'
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
// 这是一个返回h函数的render函数
// 因为被编译到了setup函数中,所以可以直接访问顶层定义的属性和方法
return () => ([
h(Foo, null, ''),
h('h2', {
count,
onClick: increment
}, count)
])
}
}
复制代码
props 和 emits
子组件
<template>
<div>
<h2>{{ count }}</h2>
<button @click="$emit('increment')">+1</button>
<button @click="decrement">-1</button>
</div>
</template>
<script setup>
// 接收props,并返回一个对象,可以在js中使用props来获取传入的数据
const props = defineProps({
count: {
type: Number,
default: 0
}
})
// 声明需要触发的事件,返回一个emit函数,作用和this.$emit函数的作用是一致的
const emit = defineEmits(['increment', 'decrement'])
const decrement = () => emit('decrement')
</script>
复制代码
父组件
<template>
<div>
<Foo :count="count" @increment="increment" @decrement="decrement" />
</div>
</template>
<script setup>
import { ref } from 'vue'
import Foo from './components/Foo.vue'
const count = ref(0)
const increment = () => count.value++
const decrement = () => count.value--
</script>
复制代码
-
defineProps 和 defineEmits 是编译器宏(compiler macros )
只能在
<script setup>
中使用。它们不需要被导入,并且在处理<script setup>
时被编译掉。 -
传递给 defineProps 和 defineEmits 的选项将被从 setup 中提升到模块范围。
因此,这些选项不能引用在 setup 作用域内声明的局部变量。这样做会导致一个编译错误。
然而,它可以引用导入的绑定,因为它们也在模块范围内
export default {
props: {
foo: String,
},
emits: ['change', 'delete'],
// setup中定义的props和emits会被抽取到模块作用域中
setup(props, { emit }) {
//setup code
},
}
复制代码
- props 和 emits 也可以使用 TypeScript 语法来声明,方法是向 defineProps 或 defineEmits 传递一个字面类型参数。
const props = defineProps<{
foo: string
bar?: number
}>()
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
复制代码
-
使用 TypeScript 语法来声明props 和 emits,没有办法为 props 提供默认值。
为了解决这个问题,提供了一个 withDefaults 编译器宏(compiler macros )。
interface Props {
msg?: string
}
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
})
复制代码
slots 和 attrs
在 <script setup>
中使用 slots 和 attrs 应该是比较少的
如果你确实需要它们,请分别使用 useSlots 和 useAttrs 帮助函数(helpers)
useSlots 和 useAttrs 是实际的运行时函数,其返回值等价于 setupContext.slots
和 setupContext.attrs
。它们也可以在 Composition API 函数中使用。
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
复制代码
顶层await
顶层的 await 可以直接在 <script setup>
里面使用。由此产生的 setup ()
函数将自动添加 async
<script setup>
const post = await fetch('/api/post/1810166').then(res => res.json())
</script>
复制代码
与普通 script 一起使用
<script setup>
语法提供了表达大多数现有 Options API 选项同等功能的能力,只有少数选项除外。
- name
- inheritAttrs
- 模块导出
如果你需要声明这些选项,请使用单独的普通 <script>
块,并使用导出默认值。
<script>
export default {
name: 'CustomName',
inheritAttrs: false
}
</script>
<script setup>
//script setup logic
</script>
复制代码