在 Composable 中返回 Vue 组件的几种方式
方式 1: 返回组件定义
typescript
import { h, ref, defineComponent, type Component } from "vue";
import type { Viewer } from "cesium";
import MeasureDistanceTool from "@/components/CesiumView/MeasureDistanceTool.vue";
export function useMeasureDistance(viewer: Viewer) {
const isActive = ref(false);
const distance = ref(0);
// 使用 defineComponent 创建响应式包装组件(最可靠的方式)
// 这样当 ref 变化时,组件会自动重新渲染,保持响应式
const MeasureDistanceComponent: Component = defineComponent({
setup() {
return () =>
h(MeasureDistanceTool, {
isActive: isActive, // 传递 ref 对象,Vue 会自动解包为 isActive.value
// Vue 3 中,v-model
"onUpdate:isActive": (value: boolean) => {
isActive.value = value;
},
// 如果需要传递其他事件处理函数
// onStart: startMeasure,
// onStop: stopMeasure,
});
},
});
function startMeasure() {
isActive.value = true;
}
function stopMeasure() {
isActive.value = false;
}
return {
MeasureDistanceComponent, // 返回已绑定 props 的组件,使用时无需再传 props
startMeasure,
stopMeasure,
};
}方式 2: 动态导入组件(按需加载)
typescript
export function useMeasureDistance() {
const state = reactive({
isActive: false,
});
// 动态导入组件(懒加载)
const MeasureDistanceComponent: Component = () => {
return import("@/components/measure/MeasureDistanceTool.vue").then(
(module) => module.default
);
};
return {
state,
MeasureDistanceComponent,
};
}方式 3: 返回渲染函数(使用 h 函数)
typescript
import { h, reactive } from "vue";
export function useMeasureDistance() {
const state = reactive({
distance: 0,
});
// 返回渲染函数
const MeasureDistanceRender = () => {
return h("div", { class: "measure-tool" }, [
h("p", `距离: ${state.distance}m`),
h("button", { onClick: () => (state.distance = 0) }, "重置"),
]);
};
return {
state,
MeasureDistanceRender,
};
}vue
<template>
<component :is="MeasureDistanceRender" />
</template>方式 4: 返回组件引用(适用于需要传递 props 的情况)
typescript
import { reactive, type Component } from "vue";
import MeasureDistanceTool from "@/components/measure/MeasureDistanceTool.vue";
export function useMeasureDistance(viewer: Ref<Viewer | null>) {
const state = reactive({
isActive: false,
});
// 返回组件引用,可以在模板中传递 props
const MeasureDistanceComponent: Component = MeasureDistanceTool;
return {
state,
MeasureDistanceComponent,
};
}vue
<template>
<component
:is="MeasureDistanceComponent"
:viewer="viewer"
v-if="state.isActive"
/>
</template>注意事项
- 组件必须正确导入或动态导入
- 使用
component :is时,组件会被正确渲染 - 返回的组件可以接收 props 和 emit 事件
- 组件的生命周期会正常执行