@holyhigh/crud-vue

A CRUD Container in Vue

Usage no npm install needed!

<script type="module">
  import holyhighCrudVue from 'https://cdn.skypack.dev/@holyhigh/crud-vue';
</script>

README

CRUD-vue

  基于Vue的通用CRUD视图模型库;提供对常用CRUD场景的视图与操作托管,通过安装适配器可以实现对主流UI库的自动适配。

概念图

CRUD-vue

介绍

  在所有存在列表展示的业务系统中,无论使用何种UI库都存在大量的CRUD场景。如何规范、有效的管理并抽象为通用操作就是CRUD-vue所关注的。

基本特性

  • 数据托管
<!-- $crud.query 托管搜索数据 -->
<el-input v-model="$crud.query.xxx"> 
<!-- $crud.table.data 托管表格数据 -->
<el-table v-model="$crud.table.data"> 
<!-- $crud.form 托管表单数据 -->
<el-form :model="$crud.form"> 
<!-- $crud.table.data 托管tree(表单数据) -->
<el-tree :model="$crud.table.data"> 
  • 操作托管
$crud.submit() //提交表单
$crud.reload() //刷新数据
$crud.cancel() //设置表单状态为取消
  • 过程封装
/*调用查询方法时,系统会执行
1. 设置表单与查询按钮的loading状态为true
2. 自动封装查询参数(query、分页、排序、...)
3. 触发钩子
4. 异常捕获
5. ...
*/
$crud.toQuery()
  • RESTful HTTP Method
$crud.toQuery() //GET
$crud.toDelete() //DELETE
$crud.doUpdate() //PUT

如何使用

1. 安装

  选择对应ui库并安装适配器

// 安装CRUD
import request from 'axios'
import CRUD from '@holyhigh/crud-vue/crud-element-ui'
Vue.use(CRUD, { request: request })

2. 激活

//在vue对象的根属性中标记crud/cruds(多实例)属性
export default {
  crud: 'auth/users',
  // crud: {url:'auth/users'} 对象方式
  mounted() {
    // 激活后业务组件会被注入一个名为“$crud”的CRUD实例
    this.$crud.reload()
    // 以及一个入口标识。标识可以用于区分入口或自定义组件
    this.$isCrudEntry
  }
  ...
}

通过对象方式激活CRUD时,可以传递除url外的其他自定义参数。比如

export default {
  crud: {url:'auth/users',permission:'a_b_c'}
  ...
}

之后可通过VM属性params(read only)来获取激活参数

this.$crud.params.permission

params参数在创建自定义CRUD组件时非常有用,比如通过permission参数可以实现组件自动权限管理,控制组件视图展示

3. 使用

<!-- 一旦组件激活crud,即可通过$crud在视图/模型中调用方法/变量 -->
<!-- 下面的例子实现了一个点击查询时锁定按钮的场景。注意,这通常不会在每个页面重复实现,而是以全局组件方式调用 -->
<button
    class="..."
    :loading="$crud.loading.query"
    @click="$crud.reload()"
>查询</button>

3. 使用(element-ui)

  通过在组件上标记crud属性,CRUD-vue可以自动托管这些组件的事件及行为,但对于数据 —— 你仍然需要手动编写并挂载相关变量,这一点也适用于自定义(二次封装)组件。

//表格
<el-table
  v-loading="$crud.loading.table"
  row-key="uid"
  :data="$crud.table.data"
  crud
>...</el-table>
//分页
<el-pagination
  :page-size.sync="$crud.pagination.pageSize"
  :total="$crud.pagination.total"
  :current-page.sync="$crud.pagination.currentPage"
  style="..."
  crud
/>
//表单
<el-form
  crud
  name="add"
  ...
>
  <el-button
    :loading="$crud.loading.submit"
    type="primary"
    @click="$crud.submit('add')"
  >确认</el-button>
</el-form>
//tree
<el-tree
  v-loading="$crud.loading.table"
  node-key="uid"
  :data="$crud.table.data"
  crud
>...</el-tree>

注意,如果在一个CRUD场景中使用多个form,必须在from中指定name属性并在提交时明确。

4. 多实例

//在一个页面上需要同时处理多CRUD业务时可以通过修改激活方式来处理
export default {
  cruds: {//注意,激活标识与单实例不同,多了一个 "s"
    user: '/api/users',// user: {url:'/api/users'} 对象方式
    log: '/api/logs'
  },
  mounted() {
    // 多实例激活时注入变量会变成“$cruds”,且必须通过明确的实例标识来调用API
    this.$cruds.user.reload()
  }
  ...
}

注意,一旦注册多实例,组件托管必须明确crud标识,比如

<!-- table挂载到user实例下 -->
<el-table
  v-loading="$crud.loading.table"
  row-key="uid"
  :data="$crud.table.data"
  crud="user"
>...</el-table>

5. HOOK

//CRUD提供多种回调钩子以满足不同的业务场景
import CRUD from '@holyhigh/crud-vue'

export default {
  crud: '/api/users',
  methods:{
    [CRUD.HOOK.AFTER_QUERY](crud, rs) {
      //根据查询结果设置分页值与表格数据
      crud.pagination.total = rs.data.total
      crud.table.data = rs.data.records || []
    }
  }
  ...
}

6. defaults

可以为CRUD指定全局defaults属性

// 如果项目返回值统一格式就可以设置全局HOOK实现查询结果赋值
CRUD.defaults[CRUD.HOOK.AFTER_QUERY] = function(crud, rs) {
  crud.pagination.total = rs.data.total
  crud.table.data = rs.data.records || []
}
// 可以设置默认的全局分页数
CRUD.defaults.pagination.pageSize = 10;
// 可以设置默认的按钮显示状态
CRUD.defaults.view.queryReset = true;

支持默认值设置的属性可在VM中查看

7. RESTAPI

RESTAPI用来构建资源请求地址。默认C/R/U/D的资源标识符都为空,如果服务器有不同模式可以修改API地址。

CRUD.RESTAPI = {
  QUERY: '', //R
  EXPORT: '/export',
  ADD: '', //C
  UPDATE: '', //U
  DELETE: '', //D
}

注意,C/R/U/D对应的HTTP Method不会变更

8. 自定义组件

  通过内置的mixins,可以实现自定义组件。下面以一个查询框为例展示自定义组件需要关注的几个方面

  • 通过$crud.view控制视图显示/隐藏
  • 通过$crud.loading控制按钮/视图的锁定
  • 通过$crud.query/table/form/pagination/...实现视图映射
  • 通过内置API实现UI交互
<template>
  <div v-show="$crud.view.queryShow" class="...">
    <slot />
    <el-button
      class="..."
      :loading="$crud.loading.query"
      @click="$crud.reload()"
    >查询</el-button>
    <el-button
      v-if="$crud.view.queryReset"
      class="..."
      @click="reset()"
    >重置</el-button>
  </div>
</template>
<script>
import CRUD from '@holyhigh/crud-vue'
import { each } from '@holyhigh/func.js/collection'
//author info...
export default {
  mixins: [CRUD.mixins],
  methods: {
    reset() {
      each(this.$crud.query, (v, k) => {
        this.$crud.query[k] = this.$crud.defaults.query[k]
        this.$crud.reload()
      })
    }
  }
}
</script>

9. URL参数

  CRUD激活时,REST地址支持URL参数来动态构建。通过 :varName 来声明变量,如下例

//user实例的地址使用了orgId参数
export default {
  crud: {
    org: '/api/orgs',
    user: '/api/orgs/:orgId/users'
  },
  ...
  methods:{
    //切换org时调用该方法
    setOrg(orgId){
      this.$cruds.user.setURLParams({orgId})
      this.$cruds.user.toQuery()
    }
  }
}

如你所见,动态URL最典型的使用场景就是关联业务(当然,非动态URL也可实现相同功能)。通过setURLParams方法可以动态修改请求地址,之后进行C/R/U/D操作

VM

  • view ✅

    业务组件通过view来控制UI > - queryShow 查询框显示开关

    • queryReset 查询框重置按钮显示开关
    • opAdd 新增按钮显示开关
    • opEdit 编辑按钮显示开关
    • opDel 删除按钮显示开关
    • opExport 导出按钮显示开关
  • loading

    通过loading控制锁定状态 > - query 查询按钮锁定开关

    • table 表格锁定开关
    • del 删除按钮锁定开关
    • export 导出按钮锁定开关
    • submit 提交按钮锁定开关
    • form 表单加载锁定开关
  • query

    托管查询条件的容器

  • table

    表格容器托管当前crud实例的列表/tree数据及显示状态 > - data 表格数据

    • selection 当前选中行
    • allColumns 表格所有列,用于动态展示 > - orders 排序列表,会传递给GET请求
    • rowKey 表格行的id key,默认为'id'。通常由适配器自动设置
    • vm 对应的vue对象(element-ui中为el-table)
  • pagination

    分页容器托管当前crud实例的列表分页状态 > - pageSize✅ 每页记录数

    • currentPage 当前页号
    • total 总记录数
  • form

    表单容器托管当前crud实例的表单数据

  • formStatus

    表单当前状态 0:默认;1:新增;2:编辑;3:查看

  • formVM

    crud绑定的vue对象。如果只绑定一个时,formVM直接指向VM对象;绑定多个时,formVM变为以VM的name属性为key的对象,如{addForm:vm,editForm:vm}

  • vm

    crud所在的vue对象

  • params

    crud激活参数,通过对象方式构造crud时可以注入。可用于自定义组件中进行附加操作,比如附加CRUD权限控制

表示支持全局默认值

APIs

  • toQuery()

    启动crud实例的查询。向指定REST地址发送GET请求

  • toDelete(rows)

    启动crud实例的删除。向指定REST地址发送DELETE请求

  • toExport()

    启动crud实例的导出。向指定REST地址发送GET请求

  • toAdd(...args)

    设置form状态为新增。

  • toEdit(row)

    设置form状态为编辑。向指定REST地址发送GET请求

  • toView(row)

    设置form状态为查看。向指定REST地址发送GET请求

  • cancel()

    设置form状态为取消。

  • submit(formName)

    进行validate(需要适配器实现)成功后执行doAdd(POST)/doEdit(PUT)操作

  • reload()

    重置分页信息并执行一次toQuery()

  • getRestURL()

    获取crud实例的服务地址。通常用于crud内部

  • setURLParams(paramObj)

    设置服务地址中的参数表

HOOKs

  • BEFORE_QUERY(crud,params,orders)

    查询前回调,可以修改请求参数,比如分页名称等

  • AFTER_QUERY(crud,rs)

    查询后回调,可以获取查询结果,设置表格

  • BEFORE_DELETE(crud,rows)

    删除前调用

  • AFTER_DELETE(crud,rs)

    删除后调用

  • BEFORE_ADD(crud,...args)

    新增前调用,可以用来清空表单或产生uuid等

  • BEFORE_EDIT(crud,rs)

    编辑前调用,可以用来锁定某些字段

  • BEFORE_VIEW(crud,rs)

    查看前调用,同BEFORE_EDIT

  • BEFORE_SUBMIT(crud)

    提交前调用,可以用来处理form字段

  • AFTER_SUBMIT(crud,rs)

    提交后调用,可以用来刷新页面、发送通知或其他操作

  • BEFORE_EXPORT(crud,params,orders)

    导出前调用,同BEFORE_QUERY

  • AFTER_EXPORT(crud,rs)

    获取导出数据后调用

  • ON_ERROR(crud,error)

    操作发生错误时调用

  • ON_CANCEL(crud)

    表单取消编辑时触发(调用cancel后)

错误信息

  • Multiple instances detected, but no crud tag found on Xxx

    页面已启用多实例,但组件标识未明确。解决方法见【4. 多实例】

  • Cannot find $crud or $cruds on Xxx

    组件托管crud,但所在环境并未激活crud。解决方法见【2. 激活】

  • form validation Xxx

    表单提交时验证错误信息

  • Cannot find [request] in the installation options

    安装时未指定请求器。解决方法见【1. 安装】