npm package: @stardev/fn-component-gen
Description: 便捷的函数式调用组件，类似vue-router的实现。
Author: ranxin
Latest version: 0.2.4

# 函数式组件生成器 (Fn Component Gen)

本模块提供了一组用于在 Vue 应用中以函数式方式调用组件的工具，支持两种主要使用模式：直接创建 App 实例和通过组件继承。

## 功能特性

### 弹窗可见性控制

- `usePopupVisible()` - 获取当前弹窗组件的可见状态（`Ref<boolean>`）
- `usePopupMethods()` - 获取弹窗的确认和关闭方法
- `usePopupAll()` - 获取弹窗的所有状态和方法（可见性 + 操作方法）

### 函数式组件处理

- `useFunctionComponent()` - 用于函数式调用组件的核心工具

### 渲染容器

- `FunctionGenView` - 用于在模板中渲染函数式组件的容器组件

### 插件管理

- `setPlugin()` - 设置需要应用到函数式组件的 Vue 插件

## 两种使用模式

本库提供两种不同的使用模式，适用于不同的场景需求：

### 1. 直接创建 App 模式（默认）

**特点**：

- 自动创建新的 Vue App 实例
- 自动挂载到动态创建的 DOM 元素
- 支持通过 `setPlugin` 配置全局插件
- 适合需要隔离上下文的独立组件

**使用方式**：

```vue
<template>
  <div>
    <button @click="openPopup">打开弹窗</button>
  </div>
</template>

<script setup lang="ts">
import { useFunctionComponent, setPlugin } from "@stardev/fn-component-gen";
import { SomePlugin } from "some-plugin";

// 设置需要应用到函数式组件的插件
setPlugin(SomePlugin);

const openPopup = async () => {
  useFunctionComponent({
    component: await import("./Popup.vue").default,
    props: {},
  }).then((result) => {
    // 弹窗调用confirm返回的结果
    console.log(result);
  });
};
</script>
```

### 2. FunctionGenView 组件继承模式（推荐）

**特点**：

- 不创建新的 Vue App 实例，复用当前应用上下文
- 可以直接继承当前应用的 Vue 实例，无需额外配置
- 通过组件继承方式渲染，性能更好
- 适合在同一应用内频繁调用的组件
- 可在模板中直接放置，自动管理渲染

**使用方式**：

```vue
<!-- 主应用 App.vue -->
<template>
  <div id="app">
    <!-- 将 FunctionGenView 放置在应用的适当位置 -->
    <FunctionGenView />
    <!-- 其他应用内容 -->
    <SomeComponent />
  </div>
</template>

<script setup lang="ts">
import { FunctionGenView } from "@stardev/fn-component-gen";
</script>
```

```vue
<!-- 调用组件 SomeComponent.vue -->
<template>
  <div>
    <button @click="openPopup">打开弹窗</button>
  </div>
</template>

<script setup lang="ts">
import { useFunctionComponent } from "@stardev/fn-component-gen";

const openPopup = async () => {
  useFunctionComponent({
    component: await import("./Popup.vue").default,
    props: {},
  }).then((result) => {
    // 弹窗调用confirm返回的结果
    console.log(result);
  });
};
</script>
```

## 弹窗组件开发

无论使用哪种模式，弹窗组件的开发方式相同：

```vue
<!-- 弹框组件 Popup.vue -->
<template>
  <div v-if="visible">
    <div>弹窗内容</div>
    <button @click="onFormSubmit">确认</button>
    <button @click="close">取消</button>
  </div>
</template>
<script setup lang="ts">
import { usePopupVisible, usePopupMethods } from "@stardev/fn-component-gen";

const visible = usePopupVisible();
const { close, confirm } = usePopupMethods();

function onFormSubmit() {
  confirm({ data: "提交的数据" });
}
</script>
```

## 两种模式的区别

| 特性       | 直接创建 App 模式        | FunctionGenView 组件继承模式 |
| ---------- | ------------------------ | ---------------------------- |
| Vue 实例   | 新建独立实例             | 复用当前应用实例             |
| DOM 挂载   | 动态创建 DOM 元素        | 使用组件模板渲染             |
| 插件支持   | 通过 setPlugin 配置      | 继承当前应用的插件           |
| 上下文隔离 | 完全隔离                 | 共享当前应用上下文           |
| 性能       | 略低（创建新实例）       | 更高（复用现有实例）         |
| 适用场景   | 独立组件、需要隔离上下文 | 应用内部组件、频繁调用       |

## 注意事项

1. 当应用中包含 `FunctionGenView` 组件时，库会自动切换到组件继承模式
2. 路由变化时，所有打开的弹窗会自动关闭
3. 使用 `usePopupVisible()`、`usePopupMethods()` 和 `usePopupAll()` 时，必须在通过 `useFunctionComponent()` 调用的组件内部使用
4. 为了避免内存泄漏，确保在不需要弹窗时正确调用 `close()` 或 `confirm()` 方法
5. 在组件继承模式下，`setPlugin` 不会生效，插件需要在主应用中通过 `app.use()` 安装

## Q&A

1. 如何获取弹窗组件的 Props 类型？

   > 弹窗组件的 Props 类型可以通过 `FnComponentProps` 工具类型获取

   ```ts
   import type { FnComponentProps } from "@stardev/fn-component-gen";

   type PopupProps = FnComponentProps<typeof import("./Popup.vue").default>;
   ```

2. 能否在组件继承模式下使用 `setPlugin` 配置插件？
   > 不能
3. 能否同时使用直接创建 App 模式和 FunctionGenView 组件继承模式？
   > 不能，当应用中包含 `FunctionGenView` 组件时，会自动切换到组件继承模式，不能同时使用两种模式