如何结合整洁架构和MVP模式提升前端开发体验(四)- 工具提效、经验分享篇

1,040

我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第n篇文章,点击查看活动详情

userManage
 └── List
     ├── api.ts
     ├── EditModal
     │   ├── index.vue
     │   ├── model.ts
     │   ├── presenter.ts
     │   └── service.ts
     ├── index.module.less
     ├── index.vue
     ├── model.ts
     ├── presenter.ts
     └── service.ts

按照我们的分层方式,创建一个组件需要创建 model.ts,service.ts,presenter.ts,index.vue 四个文件,太费事了。

快速创建代码模板

安装 vscode 插件,使用插件物料功能快速创建模板。

image.png

下载物料模板

image.png

image.png

image.png

image.png

vue 项目就选择 vue-mvp 模块。

点击确定后,区块物料就会下载到当前项目的 materials 目录下,之后直接使用即可。

image.png

配置区块物料为常用物料:

image.png

image.png

在需要创建新组件的文件右键:

image.png

image.png

以上就是使用 lowcode 插件快速创建代码区块的过程,这只是插件一小部分功能,更多的功能可以查看 lowcode 详细文档

有接口文档时如何开发

YApi 或者 Swagger

如果接口文档是 Swagger,可以将 Swagger 文档导入 YApi 中(如果团队没有部署,可以使用官方提供的 yapi.smart-xwork.cn,或者自己本地部署)。YApi 本地部署及导入Swagger 参考

使用 lowcode 插件可以快速的根据 YApi 接口信息生成代码:

下载物料

image.png

下载所有代码片段,代码片段会保存在目录 materials\snippets 中,可以手动添加修改。

image.png

配置 YApi 信息

image.png

image.png

复制接口 id,生成接口请求方法

image.png

写好接口请求方法(没有的话默认是 fetch),选中后右键(此时确保剪贴板中复制的内容是上面提到的 YAapi 接口 id)

image.png

image.png

选择项目之后选择模板

image.png

image.png

即可生成接口请求代码:

export interface IFetchUserListResult {
  code: number;
  msg: string;
  result: {
    rows: {
      /**
       * 姓名
       */
      name: string;
      /**
       * 年龄
       */
      age: number;
      /**
       * 电话
       */
      mobile: string;
      /**
       * 地址
       */
      address: string;
      /**
       * 标签
       */
      tags: string[];
      id: number;
    }[];
    total: number;
  };
}

export interface IFetchUserListParams {
  name: string;
  page: string;
  size: string;
}

/**
 * 用户列表
 * http://yapi.smart-xwork.cn/project/129987/interface/api/1796953
 * @author 划水摸鱼糊屎工程师
 *
 * @param {IFetchUserListParams} params
 * @returns
 */
export function fetchUserList(params: IFetchUserListParams) {
  return request<IFetchUserListResult>({
    url: `/api/user/page`,
    method: "GET",
    params,
  });
}

定义 model 时候,可以直接使用生成的 ts 类型:

import { reactive, ref } from "vue";
import { IFetchUserListResult } from "./api";

export const useModel = () => {
  const userList = reactive<{ value: IFetchUserListResult["result"]["rows"] }>({
    value: [],
  });

  return {
    userList,
  };
};

export type Model = ReturnType<typeof useModel>;

JSON

如果后端直接给的 json 数据,借助 lowcode 工具也可以自动生成代码。

复制 json 数据,选中方法名称,右键

image.png

选择模板

image.png

即可生成接口请求代码:

export interface IFetchResult {
  code: number;
  msg: string;
  result: {
    rows: {
      name: string;
      age: number;
      mobile: string;
      address: string;
      tags: string[];
      id: number;
    }[];
    total: number;
  };
}

export interface IFetchParams {
  id: number;
}

export interface IFetchData {
  xx: string;
}

export function fetch(params: IFetchParams, data: IFetchData) {
  return request<IFetchResult>({
    url: `xxxx`,
    method: "GET",
    params,
    data,
  });
}

没有接口文档如何开发

根据原型或设计稿定义 model。

管理后台某个列表页面为例:

import { reactive } from 'vue'

export type TableListItem = {
  id: number
  column1: string
  column2: string
  column3: string
  column4: string
  column5: string
  column6: string
  column7: string
  column8: string
  column9: string
  column10: string
  disabled?: boolean
  children?: {
    id: number
    column1: string
    column2: string
    column3: string
    column4: string
    column5: string
    column6: string
    column7: string
    column8: string
    column9: string
    column10: string
  }[]
}

type TableList = TableListItem[]

export const useModel = () => {
  const filterForm = reactive<{ cityCode?: string; store?: string }>({
    cityCode: undefined,
    store: undefined,
  })

  const filterFormOptions = reactive<{
    city: { value: string; lable: string }[]
    store: { value: string; lable: string }[]
  }>({ city: [], store: [] })

  const tableList = reactive<{ data: TableList }>({ data: [] })

  const pagination = reactive({
    page: 1,
    size: 10,
    total: 0,
  })

  return {
    filterForm,
    filterFormOptions,
    tableList,
    pagination,
  }
}

export type Model = ReturnType<typeof useModel>

使用 lowcode 工具以及相应的模板生成 API 请求方法:

复制 ts 类型(不需要包含类型名称 )

{
  id: number
  column1: string
  column2: string
  column3: string
  column4: string
  column5: string
  column6: string
  column7: string
  column8: string
  column9: string
  column10: string
  disabled?: boolean
  children?: {
    id: number
    column1: string
    column2: string
    column3: string
    column4: string
    column5: string
    column6: string
    column7: string
    column8: string
    column9: string
    column10: string
  }[]
}

声明方法名称并选中,右键

image.png

选择模板

image.png

即可生成代码

export interface IFetchTableListResult {
  code: number;
  msg: string;
  result: {
    id: number;
    column1: string;
    column2: string;
    column3: string;
    column4: string;
    column5: string;
    column6: string;
    column7: string;
    column8: string;
    column9: string;
    column10: string;
    disabled?: boolean;
    children?: {
      id: number;
      column1: string;
      column2: string;
      column3: string;
      column4: string;
      column5: string;
      column6: string;
      column7: string;
      column8: string;
      column9: string;
      column10: string;
    }[];
  };
}

export interface IFetchTableListParams {
  id: number;
}

export interface IFetchTableListData {
  xx: string;
}

export function fetchTableList(
  params: IFetchTableListParams,
  data: IFetchTableListData,
) {
  return request<IFetchTableListResult>({
    url: `xxxx`,
    method: "GET",
    params,
    data,
  });
}

结合之后的 mock,就不需要等后端的接口了。

后端接口可以联调的时候,只需要修改接口返回类型,url,入参以及调用的地方(一般都是 service 层),做字段的映射。结合 ts-check,很容易就能定位需要修改的地方。

后端接口返回的 json 数据也可以使用 lowcode 相应的模板快速的替换类型:

复制后端返回的json,选中原来的类型(不需要选择类型名称),如下图

image.png

右键,选择相应模板

image.png

即可更新类型声明

export interface IFetchTableListResult {
  code: number;
  msg: string;
  result: {
    rows: {
      name: string;
      age: number;
      mobile: string;
      address: string;
      tags: string[];
      id: number;
    }[];
    total: number;
  };
}

mock

没有到与后端联调的阶段,都可以使用 mock 进行开发。

YApi

YApi 做为接口文档的话,可以直接使用 YApi 的 mock 服务。请求方法的 url 参数直接使用 mock 地址。

image.png

普通 mock

image.png

比较麻烦,需要一个个字段手动调整,不然生成的 mock 数据比较怪异。支持使用 mockjs 占位符。

高级 mock 脚本

可以使用 lowcode 插件的相应模板,生成高级 mock 脚本。

跟之前一样,需要复制 YApi 接口 id,随便一个文件中右键,选择相应模板

image.png

将生成的代码复制粘贴到 YApi 中

image.png

lowcode-mock

使用脚手架创建 mock 项目

image.png

在打开的 mock 项目中,创建新的 mock 接口:

选中 routes 文件夹,右键

image.png

image.png

image.png

可以看到在 routes 目录下新创建了一个 newRoute 文件

image.png

根据 YApi 接口定义生成 mock

像上面一样先配置 YApi 地址,token 等信息。

复制对应的 YApi 接口 id,相应位置右键选择模板生成代码

image.png

image.png

image.png

根据 JSON 生成 mock

复制 JSON 数据,相应位置右键选择模板生成代码

image.png

根据 TS 类型生成 mock

复制 TS 类型(不需要复制类型名称),相应位置右键选择模板生成代码

image.png

建议每个前端项目对应的 mock 在 routes 文件夹下建一个对应的文件即可,不然一个前端项目对应一个 mock 项目不好维护。

样式

如果使用 css module,可以安装 CSS Modules 插件,可以像代码一样智能提示以及跳转到定义的地方。