vue 表格组件 vxe-table 配置 ajax 请求自动加载数据与表单查询

vxe-table 提供了强大的数据代理(Proxy)能力,只需配置好数据源和表单项,即可自动完成数据加载、分页、查询、重置等操作,从每个页面重复编写冗余代码中解放出来。本文将介绍如何通过 proxyConfig 配置 Ajax 查询接口、分页以及表单代理,并给出完整示例与注意事项。

功能概述

  • 自动加载数据:通过 proxyConfig.ajax.query 配置查询接口,表格自动请求并渲染数据。
  • 分页查询:只需添加 pagerConfig,接口返回分页信息,即可实现分页。
  • 表单查询:通过 formConfig.items 配置查询表单,并启用 proxyConfig.form,即可自动收集表单条件并提交查询。
  • 提交模式:默认提交为 reload 重新加载,可改为 query 只查询不清除条件。
  • 默认值:通过 itemRender.defaultValue 为表单项设置默认值。

核心配置

配置查询接口

proxyConfig: {
  ajax: {
    query: ({ page, form }) => {
      // page: 分页信息,form: 表单数据
      return findPageList(page.pageSize, page.currentPage, form)
    }
  }
}
  • query 函数接收一个对象,包含 page(分页参数)和 form(表单查询条件)。
  • 返回 Promise,解析结果需包含 result(数据列表)和 page.total(总条数,分页时需要)。

启用分页

pagerConfig: {} // 开启分页,可配置 pageSize、pageSizes 等
  • 分页查询与列表查询配置基本一致,区别在于:
    • 需要添加 pagerConfig。
    • 接口响应结果需包含分页信息,如 { result: [], page: { total: 100 } }

配置查询表单

formConfig: {
  items: [
    { field: 'name', title: '名称', span: 8, itemRender: { name: 'VxeInput' } },
    // ...
  ]
}
  • items 数组定义表单项,field 对应查询字段,title 为标签,span 控制栅格宽度。
  • itemRender 指定渲染组件,如 VxeInput、VxeSelect、VxeDatePicker 等。
  • changeToSubmit: true 表示值改变后自动提交查询。

启用表单代理

proxyConfig: {
  form: true, // 启用表单代理
  formOptions: {
    // submitMode: 'query' // 可选,默认 'reload'
  }
}
  • form: true 后,表单提交会自动触发 ajax.query。
  • formOptions.submitMode:
    • 'reload'(默认):提交后重新加载数据,并重置到第一页。
    • 'query':只查询,不清除条件,不重置分页。

设置默认值

{ field: 'name', title: '名称', itemRender: { name: 'VxeInput', defaultValue: '默认值' } }

代码

image

<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script setup>
import { reactive } from 'vue'

const list = [
  { id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, date: '', address: 'Shenzhen', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, date: '', address: 'test abc', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10006, name: 'Test6', nickname: 'T6', role: 'Designer', sex: 'Women', age: 21, date: '', address: 'Shenzhen', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10007, name: 'Test7', nickname: 'T7', role: 'Test', sex: 'Man', age: 29, date: '', address: 'Shenzhen', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10008, name: 'Test8', nickname: 'T8', role: 'Develop', sex: 'Man', age: 35, date: '', address: 'test abc', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 10009, name: 'Test9', nickname: 'T9', role: 'Develop', sex: 'Man', age: 35, date: '', address: 'Shenzhen', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100010, name: 'Test10', nickname: 'T10', role: 'Develop', sex: 'Man', age: 35, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100011, name: 'Test11', nickname: 'T11', role: 'Develop', sex: 'Man', age: 49, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100012, name: 'Test12', nickname: 'T12', role: 'Develop', sex: 'Women', age: 45, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100013, name: 'Test13', nickname: 'T13', role: 'Test', sex: 'Women', age: 35, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100014, name: 'Test14', nickname: 'T14', role: 'Test', sex: 'Man', age: 29, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100015, name: 'Test15', nickname: 'T15', role: 'Develop', sex: 'Man', age: 39, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100016, name: 'Test16', nickname: 'T16', role: 'Test', sex: 'Women', age: 35, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100017, name: 'Test17', nickname: 'T17', role: 'Test', sex: 'Man', age: 39, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100018, name: 'Test18', nickname: 'T18', role: 'Develop', sex: 'Man', age: 44, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100019, name: 'Test19', nickname: 'T19', role: 'Develop', sex: 'Man', age: 39, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100020, name: 'Test20', nickname: 'T20', role: 'Test', sex: 'Women', age: 35, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100021, name: 'Test21', nickname: 'T21', role: 'Test', sex: 'Man', age: 39, date: '', address: 'Shanghai', startDate: '2025-01-01', endDate: '2025-02-10' },
  { id: 100022, name: 'Test22', nickname: 'T22', role: 'Develop', sex: 'Man', age: 44, date: '', address: 'Guangzhou', startDate: '2025-01-01', endDate: '2025-02-10' }
]

// 模拟接口
const findPageList = (pageSize, currentPage, queryObj) => {
  console.log(`调用查询接口 pageSize=${pageSize} currentPage=${currentPage}`, queryObj)
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        result: list.slice((currentPage - 1) * pageSize, currentPage * pageSize),
        page: {
          total: list.length
        }
      })
    }, 100)
  })
}

const gridOptions = reactive({
  border: true,
  height: 500,
  pagerConfig: {},
  formConfig: {
    items: [
      { field: 'name', title: '名称', span: 8, itemRender: { name: 'VxeInput' } },
      {
        field: 'sex',
        title: '性别',
        span: 8,
        itemRender: {
          name: 'VxeSelect',
          options: [
            { label: '女', value: 'Women' },
            { label: '男', value: 'Man' }
          ],
          changeToSubmit: true
        }
      },
      { field: 'date', title: '日期', span: 8, itemRender: { name: 'VxeDatePicker', changeToSubmit: true } },
      { field: '_startAndEnd', title: '日期范围', span: 16, itemRender: { name: 'VxeDateRangePicker', changeToSubmit: true, startField: 'startDate', endField: 'endDate' } },
      {
        span: 24,
        align: 'center',
        itemRender: {
          name: 'VxeButtonGroup',
          options: [
            { type: 'submit', content: '搜索', status: 'primary' },
            { type: 'reset', content: '重置' }
          ]
        }
      }
    ]
  },
  proxyConfig: {
    // 启用表单代理
    form: true,
    // formOptions: {
    //   // 代理表单提交模式,支持 reload 和 query,默认 reload,点击搜索时,默认自动清除条件;如果 query 则不清除
    //   submitMode: 'query'
    // },
    ajax: {
      query: ({ page, form }) => {
        return findPageList(page.pageSize, page.currentPage, form)
      }
    }
  },
  columns: [
    { type: 'seq', width: 70 },
    { field: 'name', title: 'Name' },
    { field: 'nickname', title: 'Nickname' },
    { field: 'role', title: 'Role', sortable: true },
    { field: 'sex', title: 'Sex', sortable: true },
    { field: 'date', title: 'Date' },
    { field: 'address', title: 'Address' }
  ]
})
</script>

相关说明

模拟分页接口

const findPageList = (pageSize, currentPage, queryObj) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({
        result: list.slice((currentPage - 1) * pageSize, currentPage * pageSize),
        page: { total: list.length }
      })
    }, 100)
  })
}
  • 接收 pageSize、currentPage 和查询条件 queryObj。
  • 返回 { result, page: { total } },其中 result 为当前页数据,page.total 为总条数。
  • 实际项目中替换为真实 Ajax 请求即可。

分页查询与列表查询的区别

  • 列表查询:只需 proxyConfig.ajax.query,返回 { result: [] } 即可。
  • 分页查询:额外配置 pagerConfig,且接口返回需包含 page.total。

通过 proxyConfig 配置 Ajax 查询与表单代理,可以极大地简化表格数据加载与查询逻辑,减少重复代码。无论是简单的列表查询还是分页查询,只需少量配置即可完成,是 vxe-table 提升开发效率的重要特性。

https://vxetable.cn

posted @ 2026-09-21 13:01  独行者r2  阅读(6)  评论(0)    收藏  举报