UNPKG

@realsee/five

Version:

Realsee Renderer SDK

211 lines (157 loc) • 5.71 kB
# 插件系统 (Plugin System) - **Summary**: Five 插件系统基于 `BasePlugin` 命名空间构建,提供了一套标准化的状态管理、生命周期控制和事件通信机制。 - **Schema**: 核心类型定义位于 `BasePlugin` 命名空间。 - **Concepts**: BasePlugin, State, Lifecycle, Controller. - **Configuration**: 插件特定的参数配置。 - **Examples**: 标准插件开发示例。 ## Schema > **Definition**: [BasePlugin](../../plugins/BasePlugin/index.d.ts) `BasePlugin` 是一个命名空间,包含 `Controller` (抽象基类), `State` (状态接口), `EventMap` (事件映射) 等核心定义。 ```typescript export namespace BasePlugin { export interface State { enabled: boolean visible?: boolean config?: unknown } export abstract class Controller<PluginState, PluginEventMap, PluginServerData, PluginData> { public five: Five public abstract state: PluginState public hooks: Subscribe<PluginEventMap> // ... } } ``` ## Concepts ### Directory Structure (目录结构) 一个标准的插件通常包含以下文件: ```text PluginName/ ├── index.ts # 插件入口,导出工厂函数和类型 ├── Controller.ts # 插件控制器,核心逻辑实现 └── typing.ts # 类型定义 ``` ### BasePlugin 所有插件推荐继承 `BasePlugin.Controller`。它定义了规范的泛型接口: - `PluginState`: 插件状态类型,继承自 `BasePlugin.State`。 - `PluginEventMap`: 插件事件类型,继承自 `BasePlugin.EventMap`。 - `PluginServerData`: 服务端原始数据类型。 - `PluginData`: 解析后的插件数据类型。 ### State (状态) 插件的状态驱动其行为。`BasePlugin.State` 定义了最基本的状态: - `enabled`: 是否启用。 - `visible`: UI 是否可见。 - `config`: 配置项。 ### Lifecycle (生命周期) 插件的主要生命周期方法: - **constructor**: 初始化配置和初始状态。 - **load**: 加载和解析数据。 - **enable**: 启用插件,注册事件监听,添加副作用。 - **disable**: 禁用插件,移除事件监听,清理副作用。 - **dispose**: 销毁插件,彻底清理资源。 ## Configuration ### BasePlugin Configuration `BasePlugin` 控制器构造函数接受可选的配置对象: | Parameter | Type | Default | Description | | :--- | :--- | :--- | :--- | | `staticPrefix` | `string` | `'//vr-image-4.realsee-cdn.cn'` | 静态资源前缀。 | | `i18n` | `(key: string) => string` | `undefined` | 国际化转换函数。 | ## Examples ### Plugin Development Walkthrough (插件开发指南) 以创建一个 `MyPlugin` 为例。 #### 1. 定义类型 (typing.ts) 定义插件所需的参数、状态、数据和事件类型。 ```typescript import { BasePlugin } from '../BasePlugin' // 1. 定义参数 export interface Params extends BasePlugin.Config { initialState?: Partial<State> config?: Config } // 2. 定义配置 export interface Config { color?: string } // 3. 定义状态 (继承 BasePlugin.State) export interface State extends BasePlugin.State { activeId?: string } // 4. 定义数据类型 export interface ServerData { /* 服务端数据结构 */ } export interface PluginData { /* 解析后的数据结构 */ } // 5. 定义事件 (继承 BasePlugin.EventMap) export interface EventMap extends BasePlugin.EventMap<State, PluginData> { click: (id: string) => void } ``` #### 2. 实现控制器 (Controller.ts) 继承 `BasePlugin.Controller` 并实现核心逻辑。 ```typescript import { Five } from '@realsee/five' import { BasePlugin } from '../BasePlugin' import * as MyPluginType from './typing' export class Controller extends BasePlugin.Controller< MyPluginType.State, MyPluginType.EventMap, MyPluginType.ServerData, MyPluginType.PluginData > { public state: MyPluginType.State constructor(five: Five, params?: MyPluginType.Params) { super(five) this.state = { enabled: true, visible: true, ...params?.initialState } if (this.state.enabled) { this._enable() } } public async load(serverData: MyPluginType.ServerData) { // 解析数据 } public enable() { if (this.state.enabled) return this.state.enabled = true this._enable() this.hooks.emit('stateChange', { state: this.state, userAction: true }) } public disable() { if (!this.state.enabled) return this.state.enabled = false this._disable() this.hooks.emit('stateChange', { state: this.state, userAction: true }) } public dispose = () => { this.disable() this.hooks.emit('dispose') } private _enable() { // five.scene.add(...) // five.on('tap', this.onTap) } private _disable() { // five.scene.remove(...) // five.off('tap', this.onTap) } } ``` #### 3. 导出插件 (index.ts) 提供一个工厂函数。 ```typescript import { Five } from '@realsee/five' import { Controller } from './Controller' import * as MyPluginType from './typing' export const MyPlugin = (five: Five, params?: MyPluginType.Params) => new Controller(five, params) export type { MyPluginType, Controller as MyPluginController } ``` ## Common Pitfalls (最佳实践) 1. **状态驱动**: 始终通过修改 `state` 来驱动插件行为,而不是直接操作 DOM 或 3D 对象。 2. **清理资源**: 在 `disable` 和 `dispose` 中务必清理所有事件监听和副作用,防止内存泄漏。 3. **类型安全**: 充分利用 TypeScript 泛型,确保事件和状态的类型安全。 --- ```yaml tags: [插件, 插件开发, 扩展, 自定义功能, 状态管理, plugin, baseplugin, development, guide, extension, lifecycle] ```