0


【庖丁解牛】vue-element-admin前端CRUD通用操作组件详解,对,核心就是crud.js文件

【庖丁解牛】vue-element-admin前端CRUD通用操作组件详解,对,核心就是crud.js文件

一、背景

vue-element-admin

框架之所以能够快速定制应用,得益于其通配的CRUD操作,属性配置多样化且个性化,能够满足绝大部分开发需求,也方便了代码生成。

可以深入学习重点源文件是:

src/components/Crud/crud.js

,一共

863

行代码,以及下图中其它四个vue组件,形成了对通用CRUD操作的高级封装。

在这里插入图片描述
来一段该文件的历史:

在该文件之前有一个老版本的文件,在

src/mixins

文件夹下。有4处使用的地方,
在这里插入图片描述
在源码版本记录中观察到:

  1. 在2019年12月9日老版本的文件停止更新了,重新添加了src/components/crud/crud.js以及其它组件,包括表单、分页、搜索框、表格;
  2. 在2019年12月12日更改了现在的名字,并以此为基础进行迭代。

在这里插入图片描述

二、知识储备

2.1 mixins混入

2.1.1 什么是混入,能做什么

混入后的方法以组件中的方法为准。

2.1.2 混入的数组中对象执行顺序

组件混入对象是一个包含多个对象的数组,对象是Vue组件,钩子函数会按照生命周期依次执行。

mixins: [A, B, C]

A beforeCreate
B beforeCreate
C beforeCreate
A created
B created
C created

2.1.3 混入后this对象指代

在混入的方法中,

this

关键字指向的是调用这个方法的组件实例。当你在组件中使用混入的方法时,Vue.js 在运行时会将混入的方法合并到组件实例中,并确保在调用混入方法时,

this

指向的是组件实例本身。

例如,在上面的例子中,当在组件的

created

钩子中调用

this.mixinMethod()

时,

this

指向的是

YourComponent

组件的实例。

总之,

this

关键字的上下文取决于它所在的函数被调用的方式。在 Vue 组件中,它通常指向组件实例,而在混入的方法中也是如此。

2.2 父子组件加载顺序

2.2.1 同步引入子组件

如图所示是Vue2中父组件同步引入子组件钩子函数调用的顺序。

在这里插入图片描述

2.2.2 异步引入子组件

异步方式引入组件钩子函数执行顺序。

在这里插入图片描述

三、文件一览

共计9个函数,最重要的就是

CRUD(options)

函数,封装了配置项、方法、钩子函数。
在这里插入图片描述

  1. CRUD(options)
  2. callVmHook(crud, hook) 调用钩子函数
  3. mergeOptions(src, opts) 合并配置项,将传入的参数合并到当前实例中
  4. presenter(crud) 生成crud
  5. header() 头部
  6. pagination() 分页
  7. form(defaultForm) 表单
  8. crud(options = {})

四、配置项

默认配置项有:
在这里插入图片描述

五、方法

5.1 普通方法

在这里插入图片描述

5.2 钩子函数

在这里插入图片描述
钩子函数应该说是做的很精细,包含各个用户操作的事件。

钩子函数与vue生命周期的执行顺序应该是我们最关注的,因为事件的起始影响着编程的思路。

在这里插入图片描述

六、小试牛刀

  1. 编写后台接口
  2. 引入各个组件和数据API接口函数
  3. 声明默认表格对象defaultForm 该对象对应着表格要显示的数据列
  4. 定义函数cruds() 该函数返回第二节中的CRUD(options)实例,参数options是一个可配置对象,根据需求更改配置元素的值。
  5. 混入对象 通过vue混入属性,将通用CRUD暴露的组件函数拿过来mixins: [presenter(), header(), form(defaultForm), crud()]
  6. 请求后台数据 通过钩子函数CRUD.HOOK.beforeRefresh

七、拨云见雾

通用组件怎么运行起来的?

离不开assign,vm.$option,callVm

八、crud流程

8.1 单表crud流程

  1. 实例化CRUD组件 在代码中执行CRUD(options)函数,用于实例化一个CRUD业务组件。在这里插入图片描述
  2. 依次执行混入数组中的主页、头部、表单、crud对象的钩子函数
  3. 执行子组件的钩子函数
  4. 完成整个组件的实例化

8.2 多表crud流程

划重点,如何实现多表crud

在进行多表CRUD时候,需要执行以下操作。

  1. 在嵌套组件的cruds()函数中添加tag属性标记;
  2. 嵌套组件添加crud-tag$attrs属性
  3. 在对应的嵌套组件内的分页组件、操作组件等添加crud-tag属性。

使用笔者修改过的crud.js文件可以省去第一步。

import{ initData, download }from'@/api/data'import{ parseTime, downloadFile }from'@/utils/index'import Vue from'vue'/**
 * CRUD配置
 * @author moxun
 * @param {*} options <br>
 * @return crud instance.
 * @example
 * 要使用多crud时,请在关联crud的组件处使用crud-tag进行标记,如:<jobForm :job-status="dict.job_status" crud-tag="job" />
 */functionCRUD(options){const defaultOptions ={tag:'default',// id字段名idField:'id',// 标题title:'',// 请求数据的urlurl:'',// 表格数据data:[],// 选择项selections:[],// 待查询的对象query:{},// 查询数据的参数params:{},// Form 表单form:{},// 重置表单defaultForm:()=>{},// 排序规则,默认 id 降序, 支持多字段排序 ['id,desc', 'createTime,asc']sort:['id,desc'],// 等待时间time:50,// CRUD MethodcrudMethod:{add:(form)=>{},del:(id)=>{},edit:(form)=>{},get:(id)=>{}},// 主页操作栏显示哪些按钮optShow:{add:true,edit:true,del:true,download:true,reset:true},// 自定义一些扩展属性props:{},// 在主页准备queryOnPresenterCreated:true,// 调试开关debug:true}
  options =mergeOptions(defaultOptions, options)const data ={...options,// 记录数据状态dataStatus:{},status:{add:CRUD.STATUS.NORMAL,edit:CRUD.STATUS.NORMAL,// 添加或编辑状态getcu(){if(this.add ===CRUD.STATUS.NORMAL&&this.edit ===CRUD.STATUS.NORMAL){returnCRUD.STATUS.NORMAL}elseif(this.add ===CRUD.STATUS.PREPARED||this.edit ===CRUD.STATUS.PREPARED){returnCRUD.STATUS.PREPARED}elseif(this.add ===CRUD.STATUS.PROCESSING||this.edit ===CRUD.STATUS.PROCESSING){returnCRUD.STATUS.PROCESSING}thrownewError('wrong crud\'s cu status')},// 标题gettitle(){returnthis.add >CRUD.STATUS.NORMAL?`新增${crud.title}`:this.edit >CRUD.STATUS.NORMAL?`编辑${crud.title}`: crud.title
      }},msg:{submit:'提交成功',add:'新增成功',edit:'编辑成功',del:'删除成功'},page:{// 页码page:0,// 每页数据条数size:10,// 总数据条数total:0},// 整体loadingloading:false,// 导出的 LoadingdownloadLoading:false,// 删除的 LoadingdelAllLoading:false}const methods ={/**
     * 通用的提示
     */submitSuccessNotify(){
      crud.notify(crud.msg.submit,CRUD.NOTIFICATION_TYPE.SUCCESS)},addSuccessNotify(){
      crud.notify(crud.msg.add,CRUD.NOTIFICATION_TYPE.SUCCESS)},editSuccessNotify(){
      crud.notify(crud.msg.edit,CRUD.NOTIFICATION_TYPE.SUCCESS)},delSuccessNotify(){
      crud.notify(crud.msg.del,CRUD.NOTIFICATION_TYPE.SUCCESS)},// 搜索toQuery(){
      crud.page.page =1
      crud.refresh()},// 刷新refresh(){if(!callVmHook(crud,CRUD.HOOK.beforeRefresh)){return}returnnewPromise((resolve, reject)=>{
        crud.loading =true// 请求数据initData(crud.url, crud.getQueryParams()).then(data=>{const table = crud.getTable()if(table && table.lazy){// 懒加载子节点数据,清掉已加载的数据
            table.store.states.treeData ={}
            table.store.states.lazyTreeNodeMap ={}}
          crud.page.total = data.totalElements
          crud.data = data.content

          crud.resetDataStatus()// time 毫秒后显示表格setTimeout(()=>{
            crud.loading =falsecallVmHook(crud,CRUD.HOOK.afterRefresh)}, crud.time)resolve(data)}).catch(err=>{
          crud.loading =falsereject(err)})})},/**
     * 启动添加
     */toAdd(){
      crud.resetForm()if(!(callVmHook(crud,CRUD.HOOK.beforeToAdd, crud.form)&&callVmHook(crud,CRUD.HOOK.beforeToCU, crud.form))){return}
      crud.status.add =CRUD.STATUS.PREPAREDcallVmHook(crud,CRUD.HOOK.afterToAdd, crud.form)callVmHook(crud,CRUD.HOOK.afterToCU, crud.form)},/**
     * 启动编辑
     * @param {*} data 数据项
     */toEdit(data){
      crud.resetForm(JSON.parse(JSON.stringify(data)))if(!(callVmHook(crud,CRUD.HOOK.beforeToEdit, crud.form)&&callVmHook(crud,CRUD.HOOK.beforeToCU, crud.form))){return}
      crud.status.edit =CRUD.STATUS.PREPARED
      crud.getDataStatus(crud.getDataId(data)).edit =CRUD.STATUS.PREPAREDcallVmHook(crud,CRUD.HOOK.afterToEdit, crud.form)callVmHook(crud,CRUD.HOOK.afterToCU, crud.form)},/**
     * 启动删除
     * @param {*} data 数据项
     */toDelete(data){
      crud.getDataStatus(crud.getDataId(data)).delete =CRUD.STATUS.PREPARED},/**
     * 取消删除
     * @param {*} data 数据项
     */cancelDelete(data){if(!callVmHook(crud,CRUD.HOOK.beforeDeleteCancel, data)){return}
      crud.getDataStatus(crud.getDataId(data)).delete =CRUD.STATUS.NORMALcallVmHook(crud,CRUD.HOOK.afterDeleteCancel, data)},/**
     * 取消新增/编辑
     */cancelCU(){const addStatus = crud.status.add
      const editStatus = crud.status.edit
      if(addStatus ===CRUD.STATUS.PREPARED){if(!callVmHook(crud,CRUD.HOOK.beforeAddCancel, crud.form)){return}
        crud.status.add =CRUD.STATUS.NORMAL}if(editStatus ===CRUD.STATUS.PREPARED){if(!callVmHook(crud,CRUD.HOOK.beforeEditCancel, crud.form)){return}
        crud.status.edit =CRUD.STATUS.NORMAL
        crud.getDataStatus(crud.getDataId(crud.form)).edit =CRUD.STATUS.NORMAL}
      crud.resetForm()if(addStatus ===CRUD.STATUS.PREPARED){callVmHook(crud,CRUD.HOOK.afterAddCancel, crud.form)}if(editStatus ===CRUD.STATUS.PREPARED){callVmHook(crud,CRUD.HOOK.afterEditCancel, crud.form)}// 清除表单验证if(crud.findVM('form').$refs['form']){
        crud.findVM('form').$refs['form'].clearValidate()}},/**
     * 提交新增/编辑
     */submitCU(){if(!callVmHook(crud,CRUD.HOOK.beforeValidateCU)){return}
      crud.findVM('form').$refs['form'].validate(valid=>{if(!valid){return}if(!callVmHook(crud,CRUD.HOOK.afterValidateCU)){return}if(crud.status.add ===CRUD.STATUS.PREPARED){
          crud.doAdd()}elseif(crud.status.edit ===CRUD.STATUS.PREPARED){
          crud.doEdit()}})},/**
     * 执行添加
     */doAdd(){if(!callVmHook(crud,CRUD.HOOK.beforeSubmit)){return}
      crud.status.add =CRUD.STATUS.PROCESSING
      crud.crudMethod.add(crud.form).then(()=>{
        crud.status.add =CRUD.STATUS.NORMAL
        crud.resetForm()
        crud.addSuccessNotify()callVmHook(crud,CRUD.HOOK.afterSubmit)
        crud.toQuery()}).catch(()=>{
        crud.status.add =CRUD.STATUS.PREPAREDcallVmHook(crud,CRUD.HOOK.afterAddError)})},/**
     * 执行编辑
     */doEdit(){if(!callVmHook(crud,CRUD.HOOK.beforeSubmit)){return}
      crud.status.edit =CRUD.STATUS.PROCESSING
      crud.crudMethod.edit(crud.form).then(()=>{
        crud.status.edit =CRUD.STATUS.NORMAL
        crud.getDataStatus(crud.getDataId(crud.form)).edit =CRUD.STATUS.NORMAL
        crud.editSuccessNotify()
        crud.resetForm()callVmHook(crud,CRUD.HOOK.afterSubmit)
        crud.refresh()}).catch(()=>{
        crud.status.edit =CRUD.STATUS.PREPAREDcallVmHook(crud,CRUD.HOOK.afterEditError)})},/**
     * 执行删除
     * @param {*} data 数据项
     */doDelete(data){let delAll =falselet dataStatus
      const ids =[]if(data instanceofArray){
        delAll =true
        data.forEach(val=>{
          ids.push(this.getDataId(val))})}else{
        ids.push(this.getDataId(data))
        dataStatus = crud.getDataStatus(this.getDataId(data))}if(!callVmHook(crud,CRUD.HOOK.beforeDelete, data)){return}if(!delAll){
        dataStatus.delete =CRUD.STATUS.PROCESSING}return crud.crudMethod.del(ids).then(()=>{if(delAll){
          crud.delAllLoading =false}else dataStatus.delete =CRUD.STATUS.PREPARED
        crud.dleChangePage(1)
        crud.delSuccessNotify()callVmHook(crud,CRUD.HOOK.afterDelete, data)
        crud.refresh()}).catch(()=>{if(delAll){
          crud.delAllLoading =false}else dataStatus.delete =CRUD.STATUS.PREPARED})},/**
     * 通用导出
     */doExport(){
      crud.downloadLoading =truedownload(crud.url +'/download', crud.getQueryParams()).then(result=>{downloadFile(result, crud.title +'数据','xlsx')
        crud.downloadLoading =false}).catch(()=>{
        crud.downloadLoading =false})},/**
     * 获取查询参数
     */getQueryParams:function(){// 清除参数无值的情况
      Object.keys(crud.query).length !==0&& Object.keys(crud.query).forEach(item=>{if(crud.query[item]===null|| crud.query[item]==='') crud.query[item]=undefined})
      Object.keys(crud.params).length !==0&& Object.keys(crud.params).forEach(item=>{if(crud.params[item]===null|| crud.params[item]==='') crud.params[item]=undefined})return{page: crud.page.page -1,size: crud.page.size,sort: crud.sort,...crud.query,...crud.params
      }},// 当前页改变pageChangeHandler(e){
      crud.page.page = e
      crud.refresh()},// 每页条数改变sizeChangeHandler(e){
      crud.page.size = e
      crud.page.page =1
      crud.refresh()},// 预防删除第二页最后一条数据时,或者多选删除第二页的数据时,页码错误导致请求无数据dleChangePage(size){if(crud.data.length === size && crud.page.page !==1){
        crud.page.page -=1}},// 选择改变selectionChangeHandler(val){
      crud.selections = val
    },/**
     * 重置查询参数
     * @param {Boolean} toQuery 重置后进行查询操作
     */resetQuery(toQuery =true){const defaultQuery =JSON.parse(JSON.stringify(crud.defaultQuery))const query = crud.query
      Object.keys(query).forEach(key=>{
        query[key]= defaultQuery[key]})// 重置参数this.params ={}if(toQuery){
        crud.toQuery()}},/**
     * 重置表单
     * @param {Array} data 数据
     */resetForm(data){const form = data ||(typeof crud.defaultForm ==='object'?JSON.parse(JSON.stringify(crud.defaultForm)): crud.defaultForm.apply(crud.findVM('form')))const crudFrom = crud.form
      for(const key in form){if(crudFrom.hasOwnProperty(key)){
          crudFrom[key]= form[key]}else{
          Vue.set(crudFrom, key, form[key])}}// add by ghl 2020-10-04  页面重复添加信息时,下拉框的校验会存在,需要找工取消if(crud.findVM('form').$refs['form']){
        crud.findVM('form').$refs['form'].clearValidate()}},/**
     * 重置数据状态
     */resetDataStatus(){const dataStatus ={}functionresetStatus(datas){

        console.log('datas',datas)

        datas.forEach(e=>{
          dataStatus[crud.getDataId(e)]={delete:0,edit:0}if(e.children){resetStatus(e.children)}})}resetStatus(crud.data)
      crud.dataStatus = dataStatus

      console.log('crud.dataStatus', crud.dataStatus,crud)},/**
     * 获取数据状态
     * @param {Number | String} id 数据项id
     */getDataStatus(id){return crud.dataStatus[id]},/**
     * 用于树形表格多选, 选中所有
     * @param selection
     */selectAllChange(selection){// 如果选中的数目与请求到的数目相同就选中子节点,否则就清空选中if(selection && selection.length === crud.data.length){
        selection.forEach(val=>{
          crud.selectChange(selection, val)})}else{
        crud.getTable().clearSelection()}},/**
     * 用于树形表格多选,单选的封装
     * @param selection
     * @param row
     */selectChange(selection, row){// 如果selection中存在row代表是选中,否则是取消选中if(selection.find(val=>{return crud.getDataId(val)=== crud.getDataId(row)})){if(row.children){
          row.children.forEach(val=>{
            crud.getTable().toggleRowSelection(val,true)
            selection.push(val)if(val.children){
              crud.selectChange(selection, val)}})}}else{
        crud.toggleRowSelection(selection, row)}},/**
     * 切换选中状态
     * @param selection
     * @param data
     */toggleRowSelection(selection, data){if(data.children){
        data.children.forEach(val=>{
          crud.getTable().toggleRowSelection(val,false)if(val.children){
            crud.toggleRowSelection(selection, val)}})}},findVM(type){return crud.vms.find(vm=> vm && vm.type === type).vm
    },notify(title, type =CRUD.NOTIFICATION_TYPE.INFO){
      crud.vms[0].vm.$notify({
        title,
        type,duration:2500})},updateProp(name, value){
      Vue.set(crud.props, name, value)},getDataId(data){return data[this.idField]},getTable(){returnthis.findVM('presenter').$refs.table
    },attchTable(){const table =this.getTable()this.updateProp('table', table)const that =this
      table.$on('expand-change',(row, expanded)=>{if(!expanded){return}const lazyTreeNodeMap = table.store.states.lazyTreeNodeMap
        row.children = lazyTreeNodeMap[crud.getDataId(row)]if(row.children){
          row.children.forEach(ele=>{const id = crud.getDataId(ele)if(that.dataStatus[id]===undefined){
              that.dataStatus[id]={delete:0,edit:0}}})}})}}const crud = Object.assign({}, data)// 可观测化
  Vue.observable(crud)// 附加方法
  Object.assign(crud, methods)// 记录初始默认的查询参数,后续重置查询时使用
  Object.assign(crud,{defaultQuery:JSON.parse(JSON.stringify(data.query)),// 预留4位存储:组件 主页、头部、分页、表单,调试查看也方便找vms:Array(4),/**
     * 注册组件实例
     * @param {String} type 类型
     * @param {*} vm 组件实例
     * @param {Number} index 该参数内部使用
     */registerVM(type, vm, index =-1){const vmObj ={
        type,vm: vm
      }if(index <0){this.vms.push(vmObj)return}if(index <4){// 内置预留vm数this.vms[index]= vmObj
        return}this.vms.length = Math.max(this.vms.length, index)this.vms.splice(index,1, vmObj)},/**
     * 取消注册组件实例
     * @param {*} vm 组件实例
     */unregisterVM(type, vm){for(let i =this.vms.length -1; i >=0; i--){if(this.vms[i]===undefined){continue}if(this.vms[i].type === type &&this.vms[i].vm === vm){if(i <4){// 内置预留vm数this.vms[i]=undefined}else{this.vms.splice(i,1)}break}}}})// 冻结处理,需要扩展数据的话,使用crud.updateProp(name, value),以crud.props.name形式访问,这个是响应式的,可以做数据绑定
  Object.freeze(crud)
  console.log("CRUD对象", crud)return crud
}// hook VMfunctioncallVmHook(crud, hook){if(crud.debug){
    console.log('callVmHook: '+ hook)}//捕获不到this对象// console.log('this', this)const tagHook = hook +'$'+ crud.tag

  console.log(tagHook)let ret =trueconst nargs =[crud]for(let i =2; i < arguments.length;++i){
    nargs.push(arguments[i])}// 有些组件扮演了多个角色,调用钩子时,需要去重const vmSet =newSet()
  crud.vms.forEach(vm=> vm && vmSet.add(vm.vm))
  vmSet.forEach(vm=>{if(vm[hook]){
      ret = vm[hook].apply(vm, nargs)!==false&& ret
    }if(tagHook && vm[tagHook]){
      ret = vm[tagHook].apply(vm, nargs)!==false&& ret
    }})return ret
}// 统一配置项functionmergeOptions(src, opts){const optsRet ={...src
  }for(const key in src){if(opts.hasOwnProperty(key)){
      optsRet[key]= opts[key]}}return optsRet
}/**
 * 查找crud
 * @param {*} vm
 * @param {string} tag
 */functionlookupCrud(vm, tag){

  tag = tag || vm.$attrs['crud-tag']||'default'// function lookupCrud(vm, tag) {if(vm.$crud){const ret = vm.$crud[tag]if(ret){return ret
    }}return vm.$parent ?lookupCrud(vm.$parent, tag):undefined}/**
 * crud主页
 */functionpresenter(crud){if(crud){
    console.warn('[CRUD warn]: '+'please use $options.cruds() { return CRUD(...) or [CRUD(...), ...] }')}return{data(){// 在data中返回crud,是为了将crud与当前实例关联,组件观测crud相关属性变化return{crud:this.crud
      }},beforeCreate(){

      console.log("presenter(crud)还没有crud",this)this.$crud =this.$crud ||{}let cruds =this.$options.cruds instanceofFunction?this.$options.cruds(): crud

      cruds.registerVM('presenter',this,0)let tag =this.$attrs['crud-tag']?this.$attrs['crud-tag']:'default'this.$crud[tag]= cruds

      this.crud =this.$crud[tag]},methods:{
      parseTime
    },created(){for(const k inthis.$crud){if(this.$crud[k].queryOnPresenterCreated){
          console.log("k",k,this.$crud[k])this.$crud[k].toQuery()}}},destroyed(){for(const k inthis.$crud){this.$crud[k].unregisterVM('presenter',this)}},mounted(){// 如果table未实例化(例如使用了v-if),请稍后在适当时机crud.attchTable刷新table信息if(this.$refs.table !==undefined){this.crud.attchTable()}}}}/**
 * 头部
 */functionheader(){return{data(){return{crud:this.crud,query:this.crud.query
      }},beforeCreate(){this.crud =lookupCrud(this)this.crud.registerVM('header',this,1)

      console.log("header() this",this)},destroyed(){this.crud.unregisterVM('header',this)}}}/**
 * 分页
 */functionpagination(){return{data(){return{crud:this.crud,page:this.crud.page
      }},beforeCreate(){this.crud =lookupCrud(this)this.crud.registerVM('pagination',this,2)

      console.log("pagination(crud) this",this)},destroyed(){this.crud.unregisterVM('pagination',this)}}}/**
 * 表单
 */functionform(defaultForm){return{data(){return{crud:this.crud,form:this.crud.form
      }},beforeCreate(){this.crud =lookupCrud(this)this.crud.registerVM('form',this,3)
      console.log("form(defaultForm) this",this)},created(){this.crud.defaultForm = defaultForm
      this.crud.resetForm()},destroyed(){this.crud.unregisterVM('form',this)}}}/**
 * crud
 */functioncrud(options ={}){const defaultOptions ={type:undefined}
  options =mergeOptions(defaultOptions, options)return{data(){return{crud:this.crud
      }},beforeCreate(){this.crud =lookupCrud(this)//此时的this指向调用混入的组件本身this.crud.registerVM(options.type,this)

      console.log("crud() this",this)},destroyed(){this.crud.unregisterVM(options.type,this)}}}/**
 * CRUD钩子
 */CRUD.HOOK={/** 刷新 - 之前 */beforeRefresh:'beforeCrudRefresh',/** 刷新 - 之后 */afterRefresh:'afterCrudRefresh',/** 删除 - 之前 */beforeDelete:'beforeCrudDelete',/** 删除 - 之后 */afterDelete:'afterCrudDelete',/** 删除取消 - 之前 */beforeDeleteCancel:'beforeCrudDeleteCancel',/** 删除取消 - 之后 */afterDeleteCancel:'afterCrudDeleteCancel',/** 新建 - 之前 */beforeToAdd:'beforeCrudToAdd',/** 新建 - 之后 */afterToAdd:'afterCrudToAdd',/** 编辑 - 之前 */beforeToEdit:'beforeCrudToEdit',/** 编辑 - 之后 */afterToEdit:'afterCrudToEdit',/** 开始 "新建/编辑" - 之前 */beforeToCU:'beforeCrudToCU',/** 开始 "新建/编辑" - 之后 */afterToCU:'afterCrudToCU',/** "新建/编辑" 验证 - 之前 */beforeValidateCU:'beforeCrudValidateCU',/** "新建/编辑" 验证 - 之后 */afterValidateCU:'afterCrudValidateCU',/** 添加取消 - 之前 */beforeAddCancel:'beforeCrudAddCancel',/** 添加取消 - 之后 */afterAddCancel:'afterCrudAddCancel',/** 编辑取消 - 之前 */beforeEditCancel:'beforeCrudEditCancel',/** 编辑取消 - 之后 */afterEditCancel:'afterCrudEditCancel',/** 提交 - 之前 */beforeSubmit:'beforeCrudSubmitCU',/** 提交 - 之后 */afterSubmit:'afterCrudSubmitCU',afterAddError:'afterCrudAddError',afterEditError:'afterCrudEditError'}/**
 * CRUD状态
 */CRUD.STATUS={NORMAL:0,PREPARED:1,PROCESSING:2}/**
 * CRUD通知类型
 */CRUD.NOTIFICATION_TYPE={SUCCESS:'success',WARNING:'warning',INFO:'info',ERROR:'error'}exportdefaultCRUDexport{
  presenter,
  header,
  form,
  pagination,
  crud
}

8.3 vms组件数组

一个CRUD组件完成渲染后,出现vms对象大小是17。这个可以自行研究。


本文转载自: https://blog.csdn.net/qq_40657528/article/details/127275856
版权归原作者 追寻上飞 所有, 如有侵权,请联系我们删除。

“【庖丁解牛】vue-element-admin前端CRUD通用操作组件详解,对,核心就是crud.js文件”的评论:

还没有评论