记一次umi插件开发-拓展generate

427 阅读2分钟

需求

使用umi搭建的一个管理平台,集成了多个系统的数据整合和分析,采用了配置式路由。每次新增一个系统,都要

  • 1、在pages目录下新增一个对应名称的文件夹(MeetingReport),包含如下所列文件

catalogue.png

  • 2、在models文件夹下新增一个数据文件,命名为页面文件+'Store'(MeetingReportStore.js)
  • 3.在services文件夹下新增一个请求文件,命名为页面文件+'Service'(MeetingReportService) 为了避免不必要的重复,所以有了这个拓展generate插件

初始化插件

yarn create umi umi-plugin-generate-enhance

等待中。。。

? Select the boilerplate type
  ant-design-pro  - Create project with a layout-only ant-design-pro boilerplate, use together with umi block.
  app             - Create project with a simple boilerplate, support typescript.
> plugin          - Create a umi plugin.

一路回车。。。

? Select the boilerplate type plugin
? What's the plugin name? umi-plugin-generate-enhance
? What's your plugin used for? 
? What's your email? 
? What's your name? 
? Which organization is your plugin stored under github? 
? Select the development language TypeScript
? Does your plugin have ui interaction(umi ui)? No
   create...
✨ File Generate Done

安装 node 模块

cd umi-plugin-generate-enhance
yarn install

启动项目

yarn build --watch  //将src文件编译放至lib目录下
yarn start  //根据example文件启动项目

已经可以看到界面啦~~~ initPage.png

开发插件

src/index.js

import  createPagesGenerator  from './createPagesGenerator'
export default function (api) {
  api.registerGenerator({
    key: 'pages',
    Generator: createPagesGenerator({ api }),
  });

}

src/createPagesGenerator.js

import { Generator, randomColor } from '@umijs/utils';
import { basename, join } from 'path';

export default function createPagesGenerator({ api }) {
  return class PageGenerator extends Generator {
    constructor(opts) {
      super(opts);
    }
    async writing() {
      const [path] = this.args._;
      const jsExt = this.args.typescript ? '.tsx' : '.js';
      const cssExt = this.args.less ? '.less' : '.css';
      // 路由js/jsx文件
      this.copyTpl({
        templatePath: join(__dirname, `page${jsExt}.tpl`),
        target: join(api.paths.absPagesPath, `${path}/index${jsExt}`),
        context: {
          path,
          name: basename(path),
          cssExt,
        },
      });
      // 路由css/scss文件
      this.copyTpl({
        templatePath: join(__dirname, `page.css.tpl`),
        target: join(api.paths.absPagesPath, `${path}/index${cssExt}`),
        context: {
          color: 'red',
        },
      });
      // model文件
      this.copyTpl({
        templatePath: join(__dirname, `model.js.tpl`),
        target: join(api.paths.absSrcPath, `models/${path}.js`),
        context: {
          path,
          name: basename(path),
        },
      });
      // service文件
      this.copyTpl({
        templatePath: join(__dirname, `service.js.tpl`),
        target: join(api.paths.absSrcPath, `services/${path}.js`),
        context: {
          path,
          name: basename(path),
        },
      });
    }
  }
}

this.args 是命令携带的参数

umi generate pages Login --less

this.args = { _: [ 'Login' ], less: true }
api.paths = {
  cwd: 'D:/xxx/umi-plugin-generate-enhance/example',
  absNodeModulesPath: 'D:/xxx/umi-plugin-generate-enhance/example/node_modules',
  absOutputPath: 'D:\\xxx\\umi-plugin-generate-enhance\\example\\dist',
  absSrcPath: 'D:/xxx/umi-plugin-generate-enhance/example',
  absPagesPath: 'D:/xxx/umi-plugin-generate-enhance/example/pages',
  absTmpPath: 'D:/xxx/umi-plugin-generate-enhance/example/.umi'
}

src/page.js.tpl

import React from 'react';
import styles from './index{{{ cssExt }}}';

export default function {{{path}}}Page() {
  return (
    <div>
      <h1 className={styles.title}>Page {{{ path }}}</h1>
    </div>
  );
}

src/page.css.tpl

.title {
  background: {{{ color }}};
}

src/model.js.tpl

import {getTitle} from '../services/{{{name}}}Service.js'
export default {
  namespace: '{{{name}}}Store',
  state: {
    title:{}
  },
  reducers: {
    changeState(state, { payload }) {
      return { ...state, title: payload };
    }
  },
  effects: {
    *getTitleData({ payload }, { call, put }) {
      const response = yield call(getTitle);
      // console.log(response, ' <==getTitle');
      if (response &&response.code===100200){
        yield put({
          type: "changeState",
          payload: response.data
        });
      }
    }
  }
};

src/service.js.tpl

import request from '../utils/request';
import api from '../utils/api.js'

export function getTitle(params) {
  return request.get(api.titleData, {
    params: params
  });
}

在example目录下执行 umi generate pages Login --less 命令,就可以看到目录变成这样了

example.png 至于具体的页面模板,就需要根据自己的业务需求去封装啦。。。

引入插件

在配置文件中引入插件

export default defineConfig({
  plugins: [
    // npm 依赖
    'umi-plugin-generate-enhance',
    // 相对路径
    './src/plugins/umi-plugin-generate-enhance'
  ],
});