vue3.0 script setup基本使用
在单文件组件(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
}>()
- 使用 ts 语法来声明 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/111').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> -->