单文件组件
1. 简介
单文件组件
<script setup>是在单文件组件(SFC)中使用[组合式 API(v3.cn.vuejs.org/api/composi…
- script-setup 模式中的代码会被编译成组件 setup() 函数的内容,且会在每次组件实例被创建的时候执行;
- script-setup 模式中声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用
- script-setup 模式一共提供了 4 个宏,包括:defineProps、defineEmits、defineExpose、withDefaults;且使用宏时无需 import可以直接使用
2. defineProps
- TS纯声明方式, 不能设置默认值
type Props = { content: string bgColor: string }
const props = defineProps<Props>()
- 设置默认值、类型、是否可选
const props = defineProps({
content: { type: String, required: true },
bgColor: { type: String, default: '#aac8e4' }
})
- withDefaults() 设置默认值
type Props = { content: string bgColor: string }
const props = withDefaults(defineProps<Props>(),{
content: 'button',
bgColor: 'green'
})
3. defineEmits
- 作用:子组件派发事件给父组件
- 使用方式:
// 方式1
const emit = defineEmits<{
(e: 'btn-self', arg: string): void
}>()
interface EmitEvent {
(e: 'selection-change', params: any): void
(e: 'row-click', row: any, column: TableColumnCtx<any>, event: Event): void
...
}
const emit = defineEmits<EmitEvent>()
// 方式2
const emit = defineEmits(['btn-self'])
// 调用
const onChange = () => {
emit('btn-self', '123') // 第一个参数是自定义事件,第二个参数是传的值
}
const handleSelectionChange = (val: any) => {
emit('selection-change', val)
}
3. defineExpose
- 作用:明确子组件暴露出去的属性或方法;
<script setup>
import { capitalize } from './helpers'
import { ref } from 'vue'
defineProps({ msg: String })
const emit = defineEmits(['change', 'delete'])
const count = ref(0)
defineExpose({ count })
</script>
<template>
<h1 @click="log">{{ msg }}</h1>
<div>{{ capitalize('my name is zhangsan')}}</div>
<button type="button" @click="count++">count is: {{ count }}</button>
</template>
- 父组件通过模版 ref 方式获取子组件实例
<Menu ref="menu"></Menu>
const menu = ref(null)
console.log(menu.value)
setup中如何定义组件的 name 属性?
方式1: 新增一个script标签
在这个script标签定义一个name属性(注意多个script使用时 lang的值要一致)
<script lang="ts">
export default { name: 'Layout' }
</script>
<script setup lang="ts"> </script>
方式2:使用unplugin-vue-define-options插件
- 安装插件
yarn add unplugin-vue-define-options -D - 集成插件 在vite.config.ts文件引入插件unplugin-vue-define-options
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import DefineOptions from 'unplugin-vue-define-options/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), DefineOptions()]
})
- 使用
<script setup lang="ts">
defineOptions({ name: 'Layout' })
</script>
方式3: 使用 vite-plugin-vue-setup-extend 插件
- 安装插件 yarn add vite-plugin-vue-setup-extend -D
- 集成插件 在vite.config.ts文件引入vite-plugin-vue-setup-extend
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueSetupExtend from 'vite-plugin-vue-setup-extend'
export default defineConfig({
plugins: [vue(), vueSetupExtend()]
})
- .vue文件的setup中直接使用name属性
<script setup lang="ts" name="Layout">
</script>