Vue CRUD 项目

Flying
2022-08-14 / 0 评论 / 118 阅读 / 正在检测是否收录...

本项目使用 Vue + element-ui + axios + testing library + JSON Server 开发的简单 CRUD Web 应用。麻雀虽小,五脏俱全。感兴趣的话,可以访问该项目的 GitHub 查看。

这是最终的效果图:

vue-crud.jpg

应用特性

本开源项目虽小但也有不少特性。

  1. 完整的 CRUD

没有像 Shop 系列项目 使用后台 API,取而代之的是 JSON Server。JSON Server 是以一个在本地运行,可以存储 json 数据的 server,最关键的是,它能支持 CRUD 操作,打破了 Node.js + Express + MongoDB 这些后台技术壁垒,与后台协商好数据结构后,前端就可以随性所欲的模拟服务端接口数据,放飞自己了。 表情

CRUD 代码集中在 App.vue 中。比如:

fetchData(params) {
  this.loading = true
  getReceiptList(params).then((data) => {
    this.loading = false
    this.tableData = data.list
    this.total = data.total
  })
  .catch(() => {
    this.loading = false
  })
},

toAdd() {
  this.adding = true
  this.dialogVisible = true
  this.form = {}
},

toEdit(row) {
  this.adding = false
  this.dialogVisible = true
  this.form = deepClone(row)
},

toDelete(id) {
  MessageBox.confirm('确定删除 ?', {
    title: '提示',
    type: 'warning',
    beforeClose: (action, instance, done) => {
      ...
  })
},

doAdd(data) {
  this.saveLoading = true
  addReceipt(data).then(() => {
    this.saveLoading = false
    this.refresh()
  })
  .catch(() => {
    this.saveLoading = false
  })
},

doEdit(data) {
  this.saveLoading = true
  editReceipt(data).then(() => {
    ...
  }).catch(() => {
    this.saveLoading = false
  })
}

对于中台系统来说,很多表单模块都有这种类似的 CRUD,收货表单和发货表单完全可以复用这部分逻辑。对于 Vue 应用,可以使用 mixins 来复用。

  1. 支持基本的搜索、分页、排序

可以按搜索姓名、手机号、收货日期、区域来搜索发货。分页、排序这些基本上都是 Element 自带组件的功能,开箱即用。

  1. 中国市区级联、自定义组件/数据访问/表单验证

考虑到代码复用,我们对很多 Element 组件进行了二次封装。BaseInput.vueBaseSelect.vueBaseDatePicker.vueBasePaginationDateColumn.vue 这些自定义组件大都通过自定义v-module实现了组件双向绑定。感兴趣的同学可以访问 Vue 双向数据绑定 了解更多。

AreaCascader 级联选择组件时,我们绑定了 area 区号,省市区名称可以通过 getCheckedNodes 方法获取选中的节点,然后通过节点的 athLabels 数组来拼接省市区名称,最终用 areaName 来保存。所以我们不仅需要为级联选择组件自定义 v-module 来绑定区号,还要为它自定义 select 事件将 areaName 值传递到父组件中。

  • 脚本片段
handleChange(value) {
  this.$emit('input', value)
  const node = this.$refs.area.getCheckedNodes()?.[0]
  if (node) {
    this.$emit('select', [...new Set(node.pathLabels)])
  }
}
  • 调用示例
<area-cascader
  v-model="form.area"
  @select="form.areaName=$event.join('')"
/>
省市区数据保存在area.js中,其实时一个数组结构的数据模块,查询时的选择组件和表单操作时的级联选择组件都会用到它。根据区号读取相应的名称,只要遍历数组就行,不用来回查询数据库。如下代码所示:
export function getAreaNameByCode(list, value) {
  if(Array.isArray(list)) {
    for (const item of list) {
      if (item.value === value) {
        return item.label
      } else if (item.children?.length > 0) {
        return getAreaNameByCode(item.children, value)
      }
    }
  }
  return ''
}
  1. 响应式布局

适当使用 CSS3 Media Query,响应式布局能适配桌面和多数移动设备。

@media screen and (max-width: 767px) {
  .el-dialog {
    width: 92% !important;
  }
}
  1. 单元测试

出于学习 testing library 初衷,本项目的单元测试写的比较系统。网上的 Vue 教程多数时使用 Vue Test Utils,库依赖性太强,没法在 React 项目复用。感兴趣的同学可以访问 Testing Library 学习指南 了解更多。

运行项目

  1. 安装依赖
npm install
  1. 编译前运行 JSON Server
npm run mock
  1. 编译和热重载用于开发
npm run serve
  1. 单元测试
npm run test:unit

相关项目

1

评论 (0)

取消