defineComponent和setup-script都能用来定义组件,除了写法的复杂程度的区别比较大之外,主要就是props和emit写法的区别:
defineComponent的porps和emits写法与vue2时一样
emits: {},
props: {},
<script setup>
需要用defineProps 和 defineEmits
<script setup>
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
</script>
如果是使用typeScript开发,porps还需要用到withDefaults
interface Props {
menu: string;
isRunning?: boolean;
}
const props = withDefaults(defineProps<Props>(), { menu: '' });
defineComponent
从实现上看,defineComponent
只返回传递给它的对象。但是,就类型而言,返回的值有一个合成类型的构造函数,用于手动渲染函数、TSX 和 IDE 工具支持。
#参数
具有组件选项的对象
import { defineComponent } from 'vue'
export default defineComponent({
name:'Component',
components: {},
emits: {},
props: {
goback: Boolean,
showTitle: {
type: Boolean,
default: true,
},
header: {
type: Object,
default: () => ({}),
},
},
data() {
return { count: 1 }
},
methods: {
increment() {
this.count++
}
}
})
和vue2的option api的写法差不多
写setup 函数的时候
import { defineComponent } from 'vue'
export default defineComponent({
name:'Component',
components: {},
emits: {},
props: {
goback: Boolean,
showTitle: {
type: Boolean,
default: true,
},
header: {
type: Object,
default: () => ({}),
},
},
setup(props,context) {
const count = 1
increment() {
this.count++
}
return {count,increment}
}
})
<script setup>
<script setup>
是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。相比于普通的 <script>
语法,它具有更多优势:
- 更少的样板内容,更简洁的代码。
- 能够使用纯 TypeScript 声明 props 和抛出事件。
- 更好的运行时性能 (其模板会被编译成与其同一作用域的渲染函数,没有任何的中间代理)。
- 更好的 IDE 类型推断性能 (减少语言服务器从代码中抽离类型的工作)。
当使用 <script setup>
的时候,任何在 <script setup>
声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用,也不需要和defineComponent一样必须return出去
defineProps 和 defineEmits
在 <script setup>
中必须使用 defineProps
和 defineEmits
API 来声明 props
和 emits
,它们具备完整的类型推断并且在 <script setup>
中是直接可用的,在使用ts时,搭配withDefaults
使用更佳
<script setup lang="ts">
import { useRouter } from 'vue-router';
const emit = defineEmits(['change', 'delete'])
interface Props {
menu: string;
isRunning?: boolean;
}
const props = withDefaults(defineProps<Props>(), { menu: '' });
const route = useRouter();
const onMenuClick = () => {
route.push('/');
};
</script>
defineExpose
使用 <script setup>
的组件是默认关闭的,也即通过模板 ref 或者 $parent
链获取到的组件的公开实例,不会暴露任何在 <script setup>
中声明的绑定。
为了在 <script setup>
组件中明确要暴露出去的属性,使用 defineExpose
编译器宏:
<script setup>
import { ref } from 'vue'
const a = 1
const b = ref(2)
defineExpose({
a,
b
})
</script>
useSlots 和 useAttrs
在 <script setup>
使用 slots
和 attrs
的情况应该是很罕见的,因为可以在模板中通过 $slots
和 $attrs
来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlots
和 useAttrs
两个辅助函数:
<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
动态组件
由于组件被引用为变量而不是作为字符串键来注册的,在 <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>