前端开发

开发必备

  1. 在进行开发之前,需要搭建好项目的运行环境。具体可查看“教程”-》“环境搭建”-》“软件安装”-》“Vue环境安装
  2. 需掌握一定的 Vue3open in new windowTypeScriptopen in new window 使用技能。
  3. 创建VueCMF前端项目。具体可查看“教程”-》“安装运行”-》“安装VueCMF前端

一切开发相关的都准备好了之后,就可以开始使用IDE工具(如vscodeopen in new windowwebstormopen in new window等)编写代码了。接下来开始前端代码部分介绍及如何在此基础上进行开发。

目录结构

先从代码的目录结构开始,打开你的VueCMF前端项目,你看到的项目目录结构应该是下面的形式。如下

├── node_modules                    # 依赖包所在目录
├── public                          # 项目首页及静态资源所在目录
├── src                             # 项目源码所在目录
|   ├── assets                      # 样式文件目录
|   ├── components                  # 组件目录
|   ├── model                       # 模型层文件目录
|   ├── router                      # 路由配置目录
|   ├── service                     # 服务层文件目录
|   ├── store                       # 状态管理配置目录
|   ├── typings                     # TypeScript类型配置目录
|   ├── views                       # 视图层文件目录
|   ├── App.vue                     # 模板首页
|   ├── main.ts                     # 项目入口文件
|   ├── registerServiceWorker.ts    # 资源缓存服务文件
|   └── shims-vue.d.ts              # TypeScript的.vue的适配定义文件
├── .browserslistrc                 # 浏览器兼容配置文件
├── .env.development                # 开发环境的后端API配置
├── .env.production                 # 生产环境的后端API配置
├── .env.test                       # 测试环境的后端API配置
├── .eslintignore                   # 代码规范检测忽略文件配置
├── .eslintrc.js                    # 代码规范检测配置
├── .gitignore                      # git忽略文件配置
├── auto-imports.d.ts               # 组件自动导入配置
├── babel.config.js                 # babel插件配置
├── components.d.ts                 # 组件自动导入配置
├── package.json                    # 项目依赖包配置
├── README.md                       # 使用说明文档
├── tsconfig.json                   # TypeScript配置
└── vue.config.js                   # webpack配置

代码架构

介绍完VueCMF前端的目录结构,下面说说代码是如何组织的。主要分为模型层、服务层、事件层及视图层。下面就一一展开介绍。

模型层

模型层的代码文件存放在项目的src下的model目录,其作用是负责与后端API的对接。刚创建的vuecmf项目由以下四个文件组成

  1. BaseModel.ts 基础模型抽象类:里面包含有get、post请求及获取后端URL等公共方法,主要用于其它继承用。
  2. DataModel.ts 数据模型类:主要封装了一些供服务层调用的获取后端数据的方法。
  3. LayoutModel.ts 界面布局模型类:里面含有获取导航菜单数据方法
  4. LoginModel.ts 登录模型类:里面含有登录后台及获取服务器信息的方法

若需要添加新的与后端API对接(如新增批量删除功能),可在DataModel.ts 文件中添加或继承BaseModel.ts, 例如

//在model目录下创建一个PhotoModel.ts文件,内容如下
import BaseModel from "./BaseModel"

/**
 * 相册模型
 */
export default class PhotoModel extends BaseModel {
    constructor() {
        super();
    }

    /**
     * 批量删除照片
     * @param id_list  照片id,多个用英文逗号分隔
     */
    batchDel = (id_list: string): Promise<AnyObject> => {
        return this.request('photo', 'batch_del', {
            data:{ id_list: id_list }
        }).then((res) => {
            if(res.status == 200 && res.data.code == 0){
                return Promise.resolve(res.data)
            }else{
                return Promise.reject(res.data)
            }
        })
    }
    
}

BaseModel.ts 中的公共API请求方法 request 的参数说明如下

  1. table_name: 模型表名(即在后台“模型配置”列表中的“表名”)
  2. action_type: 模型的动作类型(即在后台“模型配置”列表中找到“模型动作”,点击后面的“字段”按钮,在打开的列表中找到“动作类型”后点击“选项”按钮,在打开的列表中“选项值”列即是这里要填的值)
  3. data: 发送给后端的数据
  4. method: 请求方式(get或post),默认为post

模型中代码写好后,如何配置与后端接口的映射呢?可在后台的“模型配置”中设置,如下

  1. 默认系统中已内置了常用的动作类型,若没有你想要动作类型,可在“模型配置”列表找到“模型动作”,点击后面的“字段”按钮,在打开的弹窗列表中找到“动作类型”后,点击“动作类型”所在行后面的“选项”按钮,在打开的列表窗口中,点击“新增”按钮

新增模型动作

  1. 在“模型配置”列表找到需要添加动作类型的模型(如相册管理模型),点击该模型所在行后面的“动作”按钮,在打开的“设置(相册管理)动作”弹窗列表中,点击“新增”按钮, 如下

新增模型动作

通过上面两步操作就完成的前端与后端接口的对接。这样就可以在前端代码中通过 BaseModel 中的 request 方法传入参数table_name(photo)以及action_type(batch_del)与后端进行交互了。

注意

在新增模型的动作时,“后端请求地址”必须以“/”开头,不得以“/”结尾,否则在设置权限时不会生效。 例如

  1. 正确:/vuecmf/photo/batchDel
  2. 错误:vuecmf/photo/batchDel, vuecmf/photo/batchDel/, /vuecmf/photo/batchDel/

模型层介绍完了,接下来就是服务层了。

服务层

服务层代码文件存放在项目的src下的service目录,其作用是调用事件层及模型层供视图层中的模板(.vue文件)调用。刚创建的vuecmf项目由以下event目录和四个文件组成, 如下

  1. event 目录:存放事件类文件。在后面的“事件层”中有详细介绍。
  2. BaseService.ts 基础服务抽象类: 主要包含公共的变更及异常处理方法等,供其它服务类继承。
  3. ContentService.ts 内容服务类: 后台内容展示区的核心类,主要包含列表管理、用户、角色、权限、模型及事件处理。
  4. LayoutService.ts 后台布局服务类:主要包含调用LayoutModel来加载菜单及路由、标签页管理,界面响应式处理。
  5. LoginService.ts 登录服务类:主要包含调用LoginModel的登录、获取用户登录信息及服务器信息的事件方法。

例如,创建一个PhotoService服务类并添加一个批量删除方法

//在service目录下创建一个PhotoService.ts文件,内容如下
import BaseService from "@/service/BaseService";
import PhotoEvent from "@/service/event/PhotoEvent";
import PhotoModel from "@/model/PhotoModel";

/**
 * 相册服务类
 */
export default class PhotoService extends BaseService{

    //列表后端接口地址
    api_list_server: string
    
    constructor() {
        super();
        const photoModel = new PhotoModel()  //实例化PhotoModel类
        this.api_list_server = photoModel.getApiUrl('photo','list')  //调用后端列表接口
    }
    
    /**
     * 批量删除照片
     * @param selectRows  选择的行数据
     */
    public batchDel = (selectRows: any):void => {
        if(selectRows){
            let id_arr = []
            selectRows.forEach((row) => {
                id_arr.push(row.id)
            })
            const photoEvent = new PhotoEvent()
            photoEvent.batchDel(id_arr.join(','))
        }
    }
    
}

现服务类创建好了,有没有发现上面的PhotoEvent事件类还没创建呢,接下来就是创建该事件类的时候了。

事件层

事件层代码文件存放在项目的src下的service目录中的event目录,其作用是调用模型层并提供事件方法供服务类调用。刚创建的vuecmf项目由以下六个文件组成,如下

  1. BaseEvent.ts 基础事件抽象类:主要封装了初始化列表及权限相关事件处理,供其它事件类继承。
  2. AdminEvent.ts 管理员事件类:主要提供管理员事件的配置及事件方法供ContentService服务类调用(如设置角色、设置权限)。
  3. MenuEvent.ts 菜单事件类:主要提供菜单事件的配置及菜单列表中按钮权限的控制。
  4. ModelConfigEvent.ts 模型配置事件类:主要提供模型配置列表的事件配置及设置字段、设置索引、设置动作及设置表单等事件方法。
  5. RolesEvent.ts 角色事件类:主要提供角色管理列表中的事件配置及添加子角色、设置权限及设置用户事件方法。
  6. DefaultEvent.ts 默认事件类:事件配置及方法继承自BaseEvent,在后台“模型配置”列表中新增的模型都是调用此事件类。你可以在此事件类中自定义自己需要的功能,可参考其它事件类写法(如AdminEvent)

下面就接着上面服务层介绍中还没有创建的PhotoEvent事件类,在这里开始创建。如下

//在event目录下创建一个PhotoEvent.ts文件,内容如下
import PhotoModel from "@/model/PhotoModel";
import {ElMessage} from "element-plus/es";

/**
 * 相册事件类
 */
export default class PhotoEvent {

    photoModel: any  //定义一个相册模型实例

    /**
     * 构造方法
     * @protected
     */
    protected constructor()
    {
        //实例化PhotoModel类
        this.photoModel = new PhotoModel() 
    }

    /**
     * 批量删除照片
     * @param id_list  照片id,多个用英文逗号分隔
     */
    public batchDel = (id_list: string):void => {
        this.photoModel.batchDel(id_list).then((res:AnyObject) => {
            if(res.status == 200 && res.data.code == 0){
                ElMessage.success(res.data.msg)
            }else{
                ElMessage.error(res.data.msg)
            }
        })
    }
    
}

业务逻辑代码现都写好了,那么该如何加到模板文件(.vue)中,在后台界面中实现最终用户使用的功能呢?接下来,视图层就是解决这个问题的。

视图层

视图层的模板文件存放在项目的src下的views目录中,其作用是渲染后台界面,直接面对用户的。刚创建的vuecmf项目由template目录和四个模板文件组成,如下

  1. template 目录:存放后台主内容展示区的模板文件(如列表页模板)。
  2. Layout.vue 后台界面框架布局模板:主要功能是调用LayoutService加载菜单及路由信息并渲染后台整体的框架布局。
  3. Login.vue 登录页模板:主要功能是调用LoginService提供用户登录后台的界面。
  4. Refresh.vue 刷新页模板:供后台刷新界面事件调用。
  5. Welcome.vue 欢迎页模板:登录后台的欢迎页,主要展示当前服务器的配置信息等。

下面就接着上面事件层留下的一个问题,在template目录下开始创建一个相册列表模板文件(PhotoList.vue),并加入调用业务逻辑代码。如下

<template>
  <vuecmf-table
      ref="photo_list_ref"
      height="460px"
      :selectable="true"
      :checkbox="true"
      :token="token"
      :server="server"
  >
    <!-- 表格头部左边 自定义按钮操作 -->
    <template #headerAction="selectRows">
      <el-button type="danger" @click.prevent="batchDel(selectRows)">批量删除</el-button>
    </template>
  </vuecmf-table>
</template>

<script lang="ts" setup>
import PhotoService from "@/service/PhotoService";

const service = new PhotoService()

//调用服务类中成员变量
const server = service.api_list_server
const token = service.token

//调用服务类中成员方法
const batchDel = service.batchDel

</script>
<script lang="ts">
import {defineComponent} from "vue";

export default defineComponent({
  name: "PhotoList"
})
</script>

模板文件创建好了,下面就可以将模板文件通过后台的“模型配置”列表,找到“模型配置”模型,点击后面的“字段”按钮,在弹出的“设置(模型配置)字段”列表中找到“组件模板”字段,然后点击后面的“选项”按钮,在弹出的“设置(组件模板)字段选项”窗口中,点击“新增”按钮添加即可。如下

新增组件模板

组件模板添加好后,就可以在“模型配置”列表中新增或编辑对应模型的表单中选择添加的“组件模板”了。

到目前为止,前端项目的功能开发已全部完成了。 若你开发功能比较复杂,单个模板文件内容比较多,那你就可以按功能模块拆分将其封装成一个个组件,然后再加入模板文件中,这样可以便于代码阅读及后期模板维护。接下来就开始介绍这块了

组件

组件的.vue文件存放在项目的src下的components目录中,其作用是封装模板文件中可复用的功能供各模板文件调用。刚创建的vuecmf项目在components目录下有四个组件文件,如下

  1. LayoutAsideMenu.vue 后台左边菜单列表组件
  2. LayoutAsideMenuItem.vue 后台左边菜单列表中子菜单项组件
  3. LayoutHeader.vue 后台顶部导航主菜单组件
  4. LayoutTabs.vue 后台标签页管理组件

以下是Layout.vue模板文件中调用组件的部分代码,具体详细代码可查看项目中对应的代码文件,这里就不全部贴出来了。

<template>
  <el-container>
    <!-- 左侧菜单 -->
    <el-aside :width="aside_width" >
      <vuecmf-layout-aside-menu
          :aside_menu_active="aside_menu_active"
          :is_side_collapse="is_side_collapse"
          :aside_menu_list="aside_menu_list"
          :collapse="collapse"
          :addTab="addTab"
      ></vuecmf-layout-aside-menu>
    </el-aside>
    <!-- 这里省略部分代码, 具体详细代码可查看项目中对应的代码文件-->
  </el-container>
</template>

状态管理

状态管理的代码文件存放在项目的src下的store目录中,主要包含后台导航菜单列表及后端API映射列表的状态。关于状态管理如何配置及使用可查看vuex官方文档open in new window

下面是项目中状态管理的部分代码,详细的可查看src下的store目录中的index.ts文件

import { createStore } from 'vuex'

export default createStore({
    state: {
        nav_menu_list: [], //系统导航菜单列表
        api_maps: [], //后端API映射列表
    },
    //后面的代码省略,详细可查看对应代码文件
})

路由

路由的代码文件存放在项目的src下的router目录中,其作用是处理菜单链接的跳转处理及界面内容切换。刚创建的vuecmf项目在router目录下有一个index.ts路由配置文件,里面已全部配置好了,一般不推荐修改此文件。若你需要在路由跳转时做一些特殊处理,可以修改此文件。关于路由如何设置,可以查阅Vue Router官方文档open in new window

以下项目中的路由配置的部分代码,详细配置可查看src下的router目录中的index.ts文件

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    name: 'home',
    component: () => import('@/views/Layout.vue'),
    redirect: 'welcome',
    children: [
      {
        path: 'welcome',
        component: () => import('@/views/Welcome.vue'),
        name: 'welcome',
        meta: { breadcrumb_list: ['欢迎页'], title: 'welcome! - Powered by www.vuecmf.com', icon: 'welcome', noCache: true,topId:0, id:0, token:'123'}
      },
    ]
  },
    //后面配置代码已省略,详细配置可查看src下的router目录中的index.ts文件
]

类型配置

TypeScript的类型配置代码文件存放在项目的src下的typings目录中,其作用是定义一些类型用于TypeScript的类型检查。刚创建的vuecmf项目在typings目录下有一个vuecmf.ts文件。 你可以在此文件中添加自己的类型定义, 例如文件中已定义好的Tag类型,如下

export interface Tag {
    title: string,
    path: string
}

调试

代码都编写好了,下面就需要进行功能调试了,验证功能是否可用,有没有什么Bug。打开命令行终端,将目录切换到自己项目的根目录,然后输入“yarn dev”回车,即进入开发调试模式

yarn dev

部署

当调试没有问题,功能可以正常使用后,就可以打包项目,部署到生产环境了。打开命令行终端,将目录切换到自己项目的根目录,然后输入“yarn build”回车,即开始打包项目了

yarn build

详细的操作请参考:“教程”下面的 安装vuecmf前端 章节

Last Updated:
Contributors: emei8, vuecmf