vxe-table中vxe-grid(高级表格)的使用方法举例

 更新时间:2024年05月11日 10:14:51   作者:Gemini_Kanon  
vxe-table是一个基于vue的表格组件,下面这篇文章主要给大家介绍了关于vxe-table中vxe-grid(高级表格)的使用方法,文中通过代码介绍的非常详细,需要的朋友可以参考下

官网传送门,废话不多说了,经过自己半个月左右的踩雷经历,发篇博客记录一下,方便自己也方便他人。由于项目需求时间问题,前面的表格都没看直接使用了vxe-grid高级表格,下面上代码。

<vxe-grid
  ref='xGrid'
  v-bind="gridOptions"
  @cell-click="cellClickEvent" //设置表格编辑方式点击列触发,该方法是点击某列时触发的方法
  @edit-closed="editClosedEvent"> //当被编辑的列失去焦点时即为编辑结束,触发该方法
    <template #product_item="{ data }">   //这里是动态配置表单项productList是从后台请求到的数据经过处理后要渲染到option中的值,value、label
        <vxe-select v-model="data.topic" placeholder="选择项目名称" transfer>
          <vxe-option v-for="item in productList" :key="item.value" :value="item.value" :label="item.label" />
        </vxe-select>
    </template>
    <template #operate_item="{ data }">
        <vxe-button type="submit" status="primary" content="查询" />
        <vxe-button type="reset" content="重置" @click="haha(data)" />   //文档中自带的重置按钮如果不拦截的话无法对自定义的表单数据进行操作,故这里需要自定义一个方法
    </template>
</vxe-grid>

下面是核心代码写在data里,js,大部分配置官网上都有,可以找到对应API,我就着重写一下我踩雷的地方,代码中会有注释,请耐心观看

gridOptions: {
    border:true,   //是否带边框
    stripe: true,   //是否带斑马纹
    round: true,   //边框是否圆角
    showHeaderOverflow: true,   //表头内容过长时是否显示省略号
    showOverflow: true,   //所有内容过长时是否显示省略号
    keepSource: true,   //是否保持原始值状态
    id: 'full_edit_1',   //唯一标识,某些功能会用到,我这里没有用到,可以忽略
    rowConfig: {   //行配置信息
      isHover: true
    },
    columnConfig: {   //列配置信息
      resizable: true
    },
    printConfig: {   //打印配置项,具体的看文档吧,很详细了,注意columns里的field要和实际数据的key对应上
      columns: [
        { field: 'name' },
        { field: 'email' },
        { field: 'nickname' },
        { field: 'age' },
        { field: 'amount' }
      ]
    },
    sortConfig: {   //排序配置项
      trigger: 'cell',
      remote: true
    },
    filterConfig: {   //筛选配置项
      remote: true
    },
    pagerConfig: {   //配置分页
      pageSize: 15,
      pageSizes: [5, 10, 15, 20, 50, 100, 200, 500, 1000],
      layouts: ['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']
    },
    formConfig: {   //表单配置项:就是查询条件,items中的field一定要和实体类名称对应上,方便管理。这里只放一个input框和下拉框了,其他的自己探索吧,API里都有
      titleWidth: 100,
      titleAlign: 'right',
      items: [
        {
          field: 'topic',
          title: '项目名称',
          span: 4,
          slots: {
            default: 'product_item'   //这里要和上面动态配置的表单项名称对应
          }
        },
        {
          field: 'status',
          title: '状态',
          span: 4,
          folding: false,
          itemRender: {
            name: '$select',
            options: [
              { label: '待处理', value: '待处理' },
              { label: '处理中', value: '处理中' },
              { label: '已计划', value: '已计划' },
              { label: '已完成', value: '已完成' },
              { label: '已关闭', value: '已关闭' }
            ],
            props: { placeholder: '请选择项目状态' }
          }
        },
        { span: 24, align: 'center', slots: { default: 'operate_item' } }   //查询重置按钮
      ]
    },
    toolbarConfig: {   //工具栏配置项
      // 这种写法是官方文档写法,只会执行API中对应的方法,若想自己实现按钮功能需要自定义插槽,如下
      // buttons: [
      //   { code: 'delete', status: 'danger', name: '直接删除', icon: 'vxe-icon-delete' },
      // ],
      // 自定义插槽
      slots: {
        buttons: ({ row }) => {
          return <el-button-group>
                    <el-button icon="el-icon-plus" type="primary" onClick={() => this.showDialog()}>新建工单</el-button>
                    <el-button icon="el-icon-delete" type="danger" onClick={() => this.$refs.xGrid.commitProxy('delete')} style="margin-left: 10px;">直接删除</el-button>
                 </el-button-group>
        }
      },
      refresh: true,
      import: true,
      export: true,
      print: true,
      zoom: true,
      custom: true
    },
    proxyConfig: {   //数据代理配置项
      seq: true, // 启用动态序号代理,每一页的序号会根据当前页数变化
      sort: true, // 启用排序代理,当点击排序时会自动触发 query 行为
      filter: true, // 启用筛选代理,当点击筛选时会自动触发 query 行为
      form: true, // 启用表单代理,当点击表单提交按钮时会自动触发 reload 行为
      // 对应响应结果 { result: [], page: { total: 100 } }
      props: {
        result: 'result', // 配置响应结果列表字段
        total: 'page.total' // 配置响应结果总页数字段
      },
      // 只接收Promise,具体实现自由发挥
      ajax: {
        // 当点击工具栏查询按钮或者手动提交指令 query或reload 时会被触发
        query: ({ page, sorts, filters, form }) => {
          const queryParams = Object.assign({}, form)
          // 处理排序条件
          const firstSort = sorts[0]
          if (firstSort) {
            queryParams.sort = firstSort.property
            queryParams.order = firstSort.order
          }
          // 处理筛选条件
          filters.forEach(({ property, values }) => {
            queryParams[property] = values.join(',')
          })
          queryParams.page = page.currentPage;
          queryParams.pageSize = page.pageSize;
          //自己在data中定义个baseUrl,用来访问后台
          return XEAjax.post(`${this.baseUrl}/queryOrder`, queryParams)
        },
        // 当点击工具栏删除按钮或者手动提交指令 delete 时会被触发
        delete: ({ body }) => {
          return XEAjax.post(`${this.baseUrl}/deleteOrder`, JSON.stringify(body.removeRecords));
        },
        // 当点击工具栏保存按钮或者手动提交指令 save 时会被触发(用自带的添加按钮的话会用到这个保存事件,我这里已经自定义插槽按钮事件了,故将该处注释掉,而且需要实时保存的话也用不上这个按钮)
        // save: ({ body }) => {
        //   return XEAjax.post(`${this.baseUrl}/updateOrder`, JSON.stringify(body.updateRecords)).then(
        //     res => xxx
        //   );
        // }
      }
    },
    columns: [   //列配置:将在这里显示数据,field要和实体类名称对应上
      { type: 'checkbox', field: 'id', title: '工单序号' },   //多选框
      { field: 'title',  title: '标题' },
      {
        field: 'status',
        title: '状态',
        width: 95,
        slots: {   //该处展示自定义插槽,可以将数据封装到想用的组件里,视觉效果更佳
          default: ( {row} ) => {
            if (row.status == '待处理') {
              return <el-tag type="danger">{row.status}</el-tag>;
            }
            if (row.status == '处理中') {
              return <el-tag type="warning">{row.status}</el-tag>;
            }
            if (row.status == '已计划') {
              return <el-tag type="info">{row.status}</el-tag>;
            }
            if (row.status == '已完成') {
              return <el-tag>{row.status}</el-tag>;
            }
            if (row.status == '已关闭') {
              return <el-tag type="success">{row.status}</el-tag>;
            }
          }
        },
        filters: [   //配置筛选条件,配置后表头对应列会有筛选图标,点开即可操作
          { label: '待处理', value: '待处理' },
          { label: '处理中', value: '处理中' },
          { label: '已计划', value: '已计划' },
          { label: '已完成', value: '已完成' },
          { label: '已关闭', value: '已关闭' }
        ],
        filterMultiple: false,   //筛选是否可多选
        editRender: {   //该处是列可编辑状态下的编辑框,这里是一个静态下拉框,下面有一个动态下拉框也是我踩雷的地方
          name: '$select',
          options: [
            { label: '待处理', value: '待处理' },
            { label: '处理中', value: '处理中' },
            { label: '已计划', value: '已计划' },
            { label: '已完成', value: '已完成' },
            { label: '已关闭', value: '已关闭' }
          ],
          props: { placeholder: '请选择工单状态' }
        }
      },
      {   //该列是获取后台数据动态渲染到页面上的地方,踩雷好几天
        field: 'charger',
        title: '负责人',
        editRender: {
          name: '$select',
          props: {
            value: [],
            options: [],   //用来显示下拉框数据的地方
            optionProps: {   //下拉框option的配置,该处要有,否则点开下拉框选值的时候对应label不会高亮
              value: 'value',
              label: 'label'
            },
            multiple: true,   //可多选
            clearable: true,
            placeholder: '请选择负责人',
            optionConfig: {
              useKey: true
            }
          }
        },
        formatter: this.formatCharger
      },
      {   //自定义插槽可以自定义事件
        slots: {
          default: ({ row }) => {
            return <el-button type="text" onClick={() => this.handleCell(row)}>详情</el-button>
          }
        }
      }
    ],
    importConfig: {   //导入配置项,暂时没用到该功能没深入研究,API上都有
      remote: true,
      importMethod: this.importMethod,
      types: ['xlsx'],
      modes: ['insert']
    },
    exportConfig: {   //导出配置项,暂时没用到该功能没深入研究,API上都有
      remote: true,
      exportMethod: this.exportMethod,
      types: ['xlsx'],
      modes: ['current', 'selected', 'all']
    },
    checkboxConfig: {   //复选框配置项
      labelField: 'id',
      reserve: true,
      highlight: true,
      range: true
    },
    editRules: {   //列编辑规则
      charger: [
        { required: true, message: '负责人不能为空' }
      ]
    },
    editConfig: {   //可编辑配置项
      trigger: 'click',
      mode: 'cell',   //cell(单元格编辑模式),row(行编辑模式)
      showStatus: true
    }
  }

重置按钮方法

haha(val) {
  //这里可以看到所有表单配置中的值
  console.log(val);
}

下面是列编辑是如果是下拉框如何请求后台接口获取数据,并渲染到页面上,写到method里,该处就是用到了上面的单元格点击事件

//如果进页面就请求后台数据渲染下拉框的话,它是没有数据的,我也在网上找了很多解决办法,要么找不到,要么代码写的没头没尾的,很不友好
//点击列的时候判断列属性,如果是想要编辑的那个列再去后台请求数据,然后以下拉框的格式返回给option就有数据了
cellClickEvent({row, column}) {
  if (column.property == 'charger') {
    let list = [];
    // 该处是请求后台的方法,封装在别处了,直接用axios去请求也可
    getAllTeamUser(param).then(res => {
      for (let i = 0; i < res.data.length; i++) {
        let obj = {};
        obj.label = res.data[i].nickName;
        obj.value = res.data[i].openId;
        obj.key = res.data[i].openId;
        list.push(obj);
      }
    })
    column.editRender.props.options = list;
  }
}

下面是列编辑完后失去焦点自动保存的方法,也是写在method里

editClosedEvent ({ row, column }) {
  const $table = this.$refs.xGrid;
  const field = column.property;
  const cellValue = row[field];
  // 判断单元格值是否被修改
  if ($table.isUpdateByRow(row, field)) {
      setTimeout(() => {
        VXETable.modal.message({
          content: `保存成功!`,
          status: 'success'
        })
        // 局部更新单元格为已保存状态
        $table.reloadRow(row, null, field)
        // 保存数据后执行查询事件重新渲染表格数据,row就是你所编辑的行的数据,该处row的值是你编辑后的值
        // 这里遇到一个问题是:下拉框选择值时只能拿到其value值,不像el-select中可以同时拿到label和value的值
        // 由于时间紧我这里是拿到value值到后台数据库查询出其对应的lebel值再进行后续操作了,时间丰富的小伙伴可以深入研究一下
        XEAjax.post(`${this.baseUrl}/updateOrder`, JSON.stringify(row)).then(
          res => this.$refs.xGrid.commitProxy('query')
        );
      }, 300)
  }
}

vxe-grid 表格头标题设置及内容合并列项

附:vxe-grid 表格头标题设置及内容合并列项

1、vxe-grid 表格的高级使用: 自定义表格表头标题动态添加,内容列有合并项;实现效果如下所示:

 2、vxe-grid 代码部分设置,实现合并有两种方式可以根据情况自由选定合并方式,代码如下;

 <!--   :span-method="mergeRowMethod"  -->
<vxe-grid
            border
            ref="xGrid" 
            class="moz-style taskTable"
            row-class-name="my-vxe-table-row"
            resizable 
            :scroll-x="{enable: true}"
            :scroll-y="{enable: true}"
            :scrollToLeftOnChange="false" 
            :max-height="600"
            :loading="table.loading"  
            :columns="table.columns" 
            :data="table.dataSource"  
            :edit-config="table.editConfig"
            :menu-config="table.rightMenu" 
            :merge-cells="table.mergeCells" 
            @menu-click="menuClick"
            @edit-closed="editClosedEvent"
            @cell-click="fiveToggle" 
            >  
            <template #xh="{ row }">
                <span v-if="!row.isDictType" class="bl-center">{{ row.xh }}</span>
                <span v-if="row.isDictType" class="bl-left">{{ row.xh }}</span>
            </template>
            <template #text_edit="{ row, column }">
                <vxe-input v-if="!row.isDictType" v-model="row[column.field]" :type="column.fieldtype || 'text'"></vxe-input>
            </template>
            <template #date_edit="{ row, column }">
                <vxe-input v-model="row[column.field]" type="date" placeholder="请选择日期时间" transfer @change="handleSubmitSave($event, row, column)"></vxe-input> 
            </template>
            <template #list_default="{ row, column }"> 
                 <span class="bl-center"> {{ DictSearch(row, column) }} </span>
            </template> 
            <template #list_edit="{ row, column }">
                <vxe-select v-if="!row.isDictType" v-model="row[column.field]" transfer clearable :placeholder="'请选择' + column.title">
                    <vxe-option v-for="(item, index) in fxList" :key="index" :value="item.value" :label="item.text"></vxe-option>
                </vxe-select> 
            </template> 
        </vxe-grid> 

3、js 数据设置及方法设置实现,如下所示:

// 数据内容设置
data(){
      return {
        fxList: [], 
        table:{
            loading: false,
            mergeCells:[],
            rightMenu: {
                className: 'my-menus',
                body: {
                    options: [
                        [
                            { code: 'addRowOne', name: '新增' },
                            { code: 'handleDelete', name: '删除' }, 
                        ]
                    ]
                }, 
            },
            isEdit: false,
            editConfig: { 
                trigger: 'click', 
                mode: 'cell', 
                showIcon:false,
                activeMethod : this.activeCellMethod
            },
            columns: [
            { title: '任务工作台',
                align: 'center',
                children: [] , //注:其他表格头设置在 children 内设置列项即可
            } 
            ],  
            dataSource: [],
        }, 
      }
  },
 
// 方法设置
        // 通用行合并函数(将相同多列数据合并为一行)
       mergeRowMethod({ row, _rowIndex, column, visibleData }) {
           let that = this
           // console.log(row, _rowIndex, column, visibleData, '_rowIndex, column, visibleData')
           let col_span = that.table.columns[0].children.length || 0 
            if(row.isDictType == true){
                return { rowspan: 1, colspan: col_span }
            }   
       },
       // 计算合并列
       computMecall(dataSource, headList){
            this.table.mergeCells = [] 
            const headL = headList.length || 0
            const tabal_data = dataSource
            let MergeCell_row = 0
            let itemMergeCell = { row: MergeCell_row, rowspan: 1, colspan: headL, col: 0 }
            tabal_data.forEach((bitem, u)=>{
                if(bitem.isDictType){
                    itemMergeCell = { row: u, rowspan: 1, colspan: headL, col: 0 }
                    this.table.mergeCells.push(itemMergeCell)
                }
            })  
       }, 
       // 查字典
       DictSearch(row, column) {
            let res = ''  
            if(column.field in row){
                res = row[column.field]  
                this.fxList.forEach(item => {
                    if(item.value == res){
                        res = item.text
                    }
                })
            }
            return res
        }, 
   /********** 其他方法此处略过,具体根据项目需求设定处理即可...... *********/

以上内容仅供参考!

总结 

到此这篇关于vxe-table中vxe-grid(高级表格)使用方法的文章就介绍到这了,更多相关vxe-table vxe-grid高级表格使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue监听页面中的某个div的滚动事件并判断滚动的位置

    vue监听页面中的某个div的滚动事件并判断滚动的位置

    本文主要介绍了vue监听页面中的某个div的滚动事件并判断滚动的位置,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • vue中如何更改element-ui主题色

    vue中如何更改element-ui主题色

    这篇文章主要介绍了vue中如何更改element-ui主题色,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 如何理解Vue中computed和watch的区别

    如何理解Vue中computed和watch的区别

    这篇文章主要介绍了Vue中computed和watch的区别,对Vue感兴趣的同学,可以参考下
    2021-05-05
  • Vue 打包优化之externals抽离公共的第三方库详解

    Vue 打包优化之externals抽离公共的第三方库详解

    这篇文章主要为大家介绍了Vue 打包优化之externals抽离公共的第三方库详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪<BR>
    2023-06-06
  • vue实现web在线聊天功能

    vue实现web在线聊天功能

    这篇文章主要为大家详细介绍了vue实现web在线聊天功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • 关于Pinia状态管理解读

    关于Pinia状态管理解读

    这篇文章主要介绍了Pinia状态管理解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 解决vue初始化项目时,一直卡在Project description上的问题

    解决vue初始化项目时,一直卡在Project description上的问题

    今天小编就为大家分享一篇解决vue初始化项目时,一直卡在Project description上的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue实现数字变换动画的示例代码

    vue实现数字变换动画的示例代码

    本文主要介绍了vue实现数字变换动画的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • vue项目双滑块组件使用

    vue项目双滑块组件使用

    这篇文章主要介绍了vue项目双滑块组件使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Vue3进阶主题Composition API使用详解

    Vue3进阶主题Composition API使用详解

    这篇文章主要为大家介绍了Vue3进阶主题Composition API使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04

最新评论