script setup 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖;当同时使用单文件组件与组合式 API 时该语法是默认推荐;
基本特性
-
自动暴露顶层绑定:在 script setup 中声明的所有顶级绑定 (变量、函数、import 导入) 都会自动暴露给模板;
<script setup> const message = 'Hello Vue 3!' const count = ref(0) function increment() { count.value++ } </script> <template> <p>{{ message }}</p> <button @click="increment">Count is: {{ count }}</button> </template>
-
自动组件注册:导入的组件无需显式注册即可直接在模板中使用;
<script setup> import MyComponent from './MyComponent.vue' import { Icon } from 'vant' </script> <template> <MyComponent /> <Icon name="success" /> </template>
使用组件
动态组件
-
由于组件是通过变量引用而不是基于字符串组件名注册的,在 script setup 中要使用动态组件的时候,应该使用动态的 :is 来绑定;
-
示例代码
<script setup> import Foo from './Foo.vue' import Bar from './Bar.vue' </script> <template> <component :is="Foo" /> <component :is="someCondition ? Foo : Bar" /> </template>
递归组件
-
一个单文件组件可以通过它的文件名被其自己所引用;例如:名为 FooBar.vue 的组件可以在其模板中用
<FooBar/>
引用它自己; -
请注意这种方式相比于导入的组件优先级更低;如果有具名的导入和组件自身推导的名字冲突了,可以为导入的组件添加别名;
import { FooBar as FooBarChild } from './components'
命名空间组件
-
可以使用带
.
的组件标签,例如<Foo.Bar>
来引用嵌套在对象属性中的组件; -
这在需要从单个文件中导入多个组件的时候非常有用:
<script setup> import * as Form from './form-components' </script> <template> <Form.Input> <Form.Label>label</Form.Label> </Form.Input> </template>
使用自定义指令
-
全局注册的自定义指令将正常工作;本地的自定义指令在 script setup 中不需要显式注册,但他们必须遵循 vNameOfDirective 这样的命名规范:
<script setup> const vMyDirective = { beforeMount: (el) => { // 在元素上做些操作 } } </script> <template> <h1 v-my-directive>This is a Heading</h1> </template>
-
如果指令是从别处导入的,可以通过重命名来使其符合命名规范:
<script setup> import { myDirective as vMyDirective } from './MyDirective.js' </script>
核心 API
defineProps 和 defineEmits
-
为了在声明 props 和 emits 选项时获得完整的类型推导支持,可以使用 defineProps 和 defineEmits,它们将自动地在 script setup 中可用:
<script setup> const props = defineProps({ foo: String }) const emit = defineEmits(['change', 'delete']) // setup 代码 </script>
-
defineProps 接收与 props 选项相同的值,defineEmits 接收与 emits 选项相同的值;
defineExpose
-
使用 script setup 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例,不会暴露任何在 script setup 中声明的绑定;
-
可以通过 defineExpose 编译器宏来显式指定在script setup 组件中要暴露出去的属性:
<script setup> import { ref } from 'vue' const a = 1 const b = ref(2) defineExpose({ a, b }) </script>
defineModel (v3.4)
-
defineModel() 是 Vue 3.4 中引入的一个新的 Composition API,用于简化组件的双向绑定 (v-model) 实现;它是对 v-model 用法的现代化改进,特别适合在组合式 API 中使用;
-
defineModel() 返回一个 ref,你可以像普通 ref 一样操作它,但它会自动与父组件的 v-model 绑定;它解决了以前需要手动处理 modelValue prop 和 update:modelValue 事件的繁琐问题;
基本用法示例
-
子组件
<script setup> // 定义一个 model,名称为 'modelValue'(默认名称) const model = defineModel() function updateValue() { model.value = 'New Value' } </script> <template> <div> <input v-model="model"> <button @click="updateValue">Update Value</button> </div> </template>
-
父组件
<script setup> import { ref } from 'vue' import ChildComponent from './ChildComponent.vue' const parentValue = ref('Initial Value') </script> <template> <ChildComponent v-model="parentValue" /> <p>Parent value: {{ parentValue }}</p> </template>
带参数的 v-model
-
子组件
<script setup> const firstName = defineModel('firstName') const lastName = defineModel('lastName') </script> <template> <input v-model="firstName" placeholder="First Name"> <input v-model="lastName" placeholder="Last Name"> </template>
-
父组件
<script setup> import { ref } from 'vue' import MultipleModels from './MultipleModels.vue' const first = ref('John') const last = ref('Doe') </script> <template> <MultipleModels v-model:firstName="first" v-model:lastName="last" /> <p>Full Name: {{ first }} {{ last }}</p> </template>
带修饰符的 v-model
-
子组件
<script setup> const model = defineModel({ // 默认值 default: '', // 当父组件使用修饰符时,这里会接收到 set(value) { // 如果使用了 .trim 修饰符 if (model.modifiers.trim) { return value.trim() } return value } }) </script> <template> <input v-model="model"> </template>
-
父组件
<script setup> import { ref } from 'vue' import ModifiersExample from './ModifiersExample.vue' const text = ref('') </script> <template> <ModifiersExample v-model.trim="text" /> <p>Value: "{{ text }}"</p> </template>
vue3🛫 CompositionApi:setup、声明周期钩子
上一篇