跳到主要内容

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