Vue3 自定义组件
Vue3 自定义组件通过 veaury 来完成 vue3 和 react 的互交互,最终暴露出一个 React 组件来跟现有的 React 自定义源码组件兼容。
数据
数据(props)层面与 React 自定义组件一致。
事件
在 Vue3 中,需要使用 defineEmit
来触发自定义事件,并在 Vue 组件标签上传入 onXXXEvent
来设置事件监听函数,详见后续示例。
插槽
在 Vue3 中可以使用 <slot><slot/>
标签来声明插槽,可以用 <slot name="xxx"><slot/>
来定义具名插槽。在使用时通过向 Vue 组件传递 vSlot
属性将组件嵌入到对应的插槽上,详见后续示例。
模版
使用 tcb lowcode create
可以创建 Vue3模版。
下面以模版中的示例组件 counter
展示如何使用 Vue3 编写微搭自定义组件。
React 组件
使用 Vue3 编写自定义组件时,最终导出的组件也是一个 React 组件。我们首先编写一个 React 组件作为承载真正 Vue3 组件的容器,并在这个组件中做一些参数的转换:
// index.tsx
import React from "react";
import { WedaVue3Wrapper } from '../../util';
import counter from "./counter.vue";
export default function CounterWithWrapper({ header, footer, ...props }) {
const vSlot = { header, footer };
return <WedaVue3Wrapper component={counter} vSlot={vSlot} {...props} />;
}
我们在项目模版中提供了 WedaVue3Wrapper
组件,帮助开发者更方便地开发 Vue3 自定义组件。在上面的 React 组件中,我们把导入的 Vue3 组件传入到 WedaVue3Wrapper
中的 component
属性。
除此之外,我们需要把插槽定义成一个对象,并将它传入到 vSlot
属性。vSlot
对象中的 key 对应的就是在 Vue 组件中的具名插槽的 name,比如 vSlot = { keyA: <div>i am a slot</div> }
这个对象就对应着在 Vue 组件中的 <slot name="keyA"></slot>
。
对于匿名插槽,即不含 name 属性的插槽 <slot></slot>
,请使用default
作为该对象中的 key,如 vSlot = { default: <div>i am a default slot</div> }
。
Vue 组件
// counter.vue
<script setup>
import { ref, onUnmounted } from "vue";
const emit = defineEmits(["add", "minus"]);
const props = defineProps(["initialCount"]);
const count = ref(props.initialCount ?? 0);
function dec() {
count.value--;
emit("minus", { value: count.value });
}
function add() {
count.value++;
emit("add", { value: count.value });
}
</script>
<template>
<div>
<slot name="header"></slot>
<button @click="dec">minus</button>
<span>{{ count }}</span>
<button @click="add">add</button>
<slot name="footer"></slot>
</div>
</template>
使用 Vue3 构建微搭自定义组件和构建一个普通 Vue3 组件的写法没有什么差别。使用 defineProps
声明组件接收的函数。使用 defineEmits
声明自定义事件并使用返回的 emit
函数触发自定义事件。
需要注意的是,Vue 组件的 template 中需要有一个根节点,平台会传入一些除定义之外 props,用于注入自定义样式、class 等场景,它们会被 Vue 透传到根节点上,详见Vue 官方文档——透传 Attributes。