单文件组件

169 阅读1分钟

单文件组件

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

  1. TS纯声明方式, 不能设置默认值
type Props = { content: string bgColor: string }
const props = defineProps<Props>()
  1. 设置默认值、类型、是否可选
const props = defineProps({
  content: { type: String, required: true },
  bgColor: { type: String, default: '#aac8e4' }
})
  1. withDefaults() 设置默认值
type Props = { content: string bgColor: string }
const props = withDefaults(defineProps<Props>(),{
    content: 'button',
    bgColor: 'green'
})

3. defineEmits

  1. 作用:子组件派发事件给父组件
  2. 使用方式:
// 方式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插件

  1. 安装插件 yarn add unplugin-vue-define-options -D
  2. 集成插件 在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()]
})
  1. 使用
<script setup lang="ts">
  defineOptions({ name: 'Layout' })
</script>

方式3: 使用 vite-plugin-vue-setup-extend 插件

  1. 安装插件 yarn add vite-plugin-vue-setup-extend -D
  2. 集成插件 在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()]
})
  1. .vue文件的setup中直接使用name属性
<script setup lang="ts" name="Layout">
</script>