Skip to content

插件开发

本章节介绍如何开发和使用速构平台插件。

什么是插件

插件是一种扩展框架功能的方式,可以:

  • 添加全局组件
  • 添加全局方法或属性
  • 添加全局指令
  • 配置全局选项
  • 注入组件选项

创建插件

插件结构

一个插件可以是一个对象,包含 install 方法:

ts
const myPlugin = {
  install(app, options) {
    // 插件逻辑
  }
}

也可以是一个函数(该函数会被当作 install 方法):

ts
function myPlugin(app, options) {
  // 插件逻辑
}

插件示例

示例 1:全局组件插件

ts
// plugins/global-components.ts
import Button from '../components/Button'
import Input from '../components/Input'

export default {
  install(app) {
    app.component('MyButton', Button)
    app.component('MyInput', Input)
  }
}

示例 2:全局方法插件

ts
// plugins/notify.ts
export default {
  install(app) {
    app.config.globalProperties.$notify = (message: string, type = 'info') => {
      // 通知逻辑
      console.log(`[${type}] ${message}`)
    }
  }
}

示例 3:带配置的插件

ts
// plugins/i18n.ts
export interface I18nOptions {
  locale: string
  messages: Record<string, Record<string, string>>
}

export default {
  install(app, options: I18nOptions) {
    const { locale, messages } = options

    app.config.globalProperties.$t = (key: string) => {
      return messages[locale]?.[key] || key
    }

    app.provide('i18n', {
      locale,
      messages,
      setLocale(newLocale: string) {
        // 切换语言
      }
    })
  }
}

示例 4:指令插件

ts
// plugins/directives.ts
export default {
  install(app) {
    // 自动聚焦指令
    app.directive('focus', {
      mounted(el) {
        el.focus()
      }
    })

    // 点击外部指令
    app.directive('click-outside', {
      mounted(el, binding) {
        el._clickOutside = (event: Event) => {
          if (!(el === event.target || el.contains(event.target))) {
            binding.value(event)
          }
        }
        document.addEventListener('click', el._clickOutside)
      },
      unmounted(el) {
        document.removeEventListener('click', el._clickOutside)
      }
    })
  }
}

使用插件

全局注册

ts
// main.ts
import { createApp } from 'your-framework'
import App from './App'
import globalComponents from './plugins/global-components'
import notify from './plugins/notify'
import i18n from './plugins/i18n'

const app = createApp(App)

// 使用插件(带配置)
app.use(i18n, {
  locale: 'zh-CN',
  messages: {
    'zh-CN': {
      hello: '你好',
      world: '世界'
    },
    'en-US': {
      hello: 'Hello',
      world: 'World'
    }
  }
})

// 使用插件(无配置)
app.use(globalComponents)
app.use(notify)

app.mount('#app')

在组件中使用插件功能

vue
<template>
  <div>
    <MyButton @click="showNotify">点击我</MyButton>
    <p>{{ $t('hello') }}</p>
    <input v-focus type="text" />
  </div>
</template>

<script setup lang="ts">
import { inject, getCurrentInstance } from 'your-framework'

const instance = getCurrentInstance()

const showNotify = () => {
  instance?.proxy?.$notify('操作成功!', 'success')
}

// 使用 inject 获取插件提供的数据
const i18n = inject('i18n')
</script>

插件开发最佳实践

1. 提供 TypeScript 类型支持

ts
// plugins/notify.ts
import type { App } from 'your-framework'

declare module 'your-framework' {
  interface ComponentCustomProperties {
    $notify: (message: string, type?: string) => void
  }
}

export default {
  install(app: App) {
    // 实现
  }
}

2. 避免重复安装

ts
export default {
  install(app) {
    if (this.installed) return
    this.installed = true
    // 插件逻辑
  }
}

3. 提供插件版本信息

ts
export const PLUGIN_VERSION = '1.0.0'

export default {
  install(app) {
    app.config.globalProperties.$pluginVersion = PLUGIN_VERSION
  }
}

4. 合理使用 Provide / Inject

ts
// 插件中 provide 数据
export default {
  install(app, options) {
    app.provide('plugin-options', options)
  }
}

// 组件中 inject 使用
import { inject } from 'your-framework'

const options = inject('plugin-options')

发布插件

准备 package.json

json
{
  "name": "your-plugin-name",
  "version": "1.0.0",
  "description": "插件描述",
  "main": "dist/index.js",
  "module": "dist/index.esm.js",
  "types": "dist/index.d.ts",
  "files": ["dist"],
  "peerDependencies": {
    "your-framework": "^1.0.0"
  }
}

构建输出

确保输出以下格式:

  • CommonJS: 用于 Node.js 环境
  • ES Module: 用于现代打包工具(支持 Tree Shaking)
  • TypeScript 类型声明: 提供类型支持

下一步

  • 查看更多开发建议:最佳实践
  • 解决开发中遇到的问题:常见问题

基于 MIT 许可发布