123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- ---
- description: module | plugins 模块、插件
- globs:
- ---
- # 模块/插件开发
- ## 目录结构
- 在 `src/modules` 或 `src/plugins` 下添加一个目录 `demo`:
- ```js
- demo
- ├──pages // 页面路由
- ├──views // 视图路由
- ├──hooks // 常用函数
- ├──components // 常用组件
- ├──directives // 指令
- ├──static // 静态文件目录
- ├──store // 状态管理
- ├──... // 其他自定义文件
- ├──config.ts // 配置文件
- └──index.ts // 入口文件
- ```
- ::: warning
- 约定的目录名称不可修改,但可自行添加或者删除。
- :::
- ## pages、views
- 1. 页面参与权限控制,所以不主动注册目录下的路由,通过 `菜单列表` 中配置注册。或者在 `config.ts` 中手动配置:
- ```js
- import { type ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- views: [
- {
- path: "/demo",
- meta: {
- label: "测试",
- },
- component: () => import("./views/demo.vue"),
- },
- ],
- pages: [
- {
- path: "/demo2",
- meta: {
- label: "测试",
- },
- component: () => import("./pages/demo.vue"),
- },
- ],
- };
- };
- ```
- 2. 使页面参与路由缓存,配置 `name` 参数
- :::warning
- `path` 与 `name` 的匹配规则:
- - /demo/t1 = demo-t1
- - /demo/t1-det = demo-t1-det
- :::
- 方式 1:
- ```html
- <script lang="ts" setup>
- defineOptions({
- name: "demo",
- });
- </script>
- ```
- 方式 2:
- ```html
- <script lang="ts">
- export default defineComponent({
- name: "demo",
- });
- </script>
- ```
- ## components
- 目录下的组件,全局注册配置方法如下:
- ```js
- import { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- components: [
- import("./components/demo.vue"),
- import("./components/demo1.vue"),
- ],
- };
- };
- ```
- ## directives
- `directives` 会以目录下的文件名分别注册指令
- ```ts
- // demo/directives/test.ts
- export default {
- created(el, binding) {},
- mounted() {},
- ...
- };
- ```
- 使用
- ```html
- <div v-test></div>
- ```
- ## store
- 使用 `pinia` 的推荐写法:
- ```ts
- import { defineStore } from "pinia";
- import { ref } from "vue";
- export const useTestStore = defineStore("test", function () {
- const count = ref(0);
- function add() {
- count.value += 1;
- }
- return {
- count,
- add,
- };
- });
- ```
- 使用
- ```ts
- import { useTestStore } from "/$/demo/store";
- const test = useTestStore();
- test.add();
- console.log(test.count); // 1
- ```
- ::: tip
- 参考 `base` 模块下 `store` 的导出方式
- :::
- ## config.ts
- 模块的配置,程序运行时会读取该文件。
- - 全局组件、路由的导入
- - 事件钩子
- 输入 `module-config` 关键字,`vscode` 中会自动生成:
- ```ts
- import { ModuleConfig } from "/@/cool";
- import { Vue } from "vue";
- export default (): ModuleConfig => {
- return {
- // 是否启用
- enable: true,
- // 插件名称
- label: "插件名称",
- // 插件描述
- description: "插件描述",
- // 作者
- author: "作者",
- version: "1.0.0",
- updateTime: "2024-02-02",
- logo: "",
- // 忽略
- ignore: {
- // 忽略进度条的请求
- NProgress: [
- "/base/open/eps",
- "/base/comm/person",
- "/base/comm/permmenu",
- "/base/comm/upload",
- "/base/comm/uploadMode",
- ],
- // 忽略 token 的路由
- token: ["/login", "/401", "/403", "/404", "/500", "/502"],
- },
- // 排序
- order: 0,
- // 配置参数
- options: {
- name: "神仙",
- },
- // 示例页面
- demo: [
- {
- name: "基础用法",
- component: () => import("..."),
- },
- ],
- // 注册全局组件
- components: [],
- // 视图路由
- views: [],
- // 页面路由
- pages: [],
- // 顶部工具栏
- toolbar: {
- order: 1,
- pc: true, // 是否在 pc 端显示
- h5: true, // 是否在 h5 端显示
- component: import("./components/index.vue"),
- },
- // 注入全局组件
- index: {
- component: import("./components/index.vue"),
- },
- // 安装时触发
- install(app: Vue) {},
- // 加载时触发
- onLoad(events) {},
- };
- };
- ```
- - order 模块加载顺序,值越大越先
- - options 提供给外部使用的参数配置:
- ```ts
- import { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- options: {
- // 尺寸
- size: 120,
- // 显示文案
- text: "选择文件",
- // 限制
- limit: {
- // 上传最大数量
- upload: 9,
- // 文件空间选择数
- select: 9,
- // 上传大小限制
- size: 100,
- },
- },
- };
- };
- ```
- 获取方式:
- ```ts
- import { module } from "/@/cool";
- const config = module.config("模块名");
- ```
- - components 提供全局的组件:
- ```ts
- import type { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- components: [import("./components/test.vue")],
- };
- };
- ```
- 批量导入可以使用 [import.meta.glob](mdc:https:/vitejs.dev/guide/features.html#glob-import) 方法:
- ```ts
- import { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- components: Object.values(import.meta.glob("./components/**/*")),
- };
- };
- ```
- - views 全局注册的视图路由,存放在 `/` 中的子路由 `children`:
- ```ts
- import { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- views: [
- {
- path: "/test",
- meta: {
- label: "测试中心",
- },
- component: () => import("./views/test.vue"),
- },
- ],
- };
- };
- ```
- - pages 全局注册的页面路由:
- ```ts
- import { ModuleConfig } from "/@/cool";
- export default (): ModuleConfig => {
- return {
- pages: [
- {
- path: "/test",
- meta: {
- label: "测试中心",
- },
- component: () => import("./views/test.vue"),
- },
- ],
- };
- };
- ```
- - install 模块安装时触发。用于预先处理:
- ```ts
- import { ModuleConfig } from "/@/cool";
- import { Vue } from "vue";
- export default (): ModuleConfig => {
- return {
- install(app: Vue) {
- // 注册组件
- app.component("test", Test);
- // 注册指令
- app.directive("focus", {
- created(el, bind) {},
- });
- },
- };
- };
- ```
- - onLoad 模块安装时触发,预先加载数据,如菜单配置、用户信息:
- 1. 使用 `await` 等待加载完成后往下执行
- 2. 可往下模块导出某个方法和变量,如 `hasToken` 验证是否有登陆
- ```ts
- import { ModuleConfig } from "/@/cool";
- import { Vue } from "vue";
- export default (): ModuleConfig => {
- return {
- async onLoad() {
- const { user, menu } = useStore();
- if (user.token) {
- // 获取用户信息
- user.get();
- // 获取菜单权限
- await menu.get();
- }
- return {
- async hasToken(cb: () => Promise<any> | void) {
- if (user.token) {
- if (cb) await cb();
- }
- },
- };
- },
- };
- };
- ```
- 其他模块中接收 `hasToken` 方法:
- ```ts
- import { ModuleConfig } from "/@/cool";
- import { useDict } from "./index";
- export default (): ModuleConfig => {
- return {
- onLoad({ hasToken }) {
- const { dict } = useDict();
- hasToken(() => {
- dict.refresh();
- });
- },
- };
- };
- ```
- ## index.ts
- 该模块需要对外开放的变量及方法,方便于别人直接使用:
- ```ts
- // modules/test/index.ts
- import { useStore } from "./store";
- export function useTest() {
- return {
- // 导出 pinia
- ...useStore(),
- // 自定义方法
- test() {},
- // 自定义变量
- data: {
- description: "数据描述",
- },
- };
- }
- ```
- 导出命名规则 `useBase` `useDemo` `useDict` use + 模块名
- 使用:
- ```ts
- import { useTest } from "/$/test";
- const { data, test } = useTest();
- ```
|