AvueAvue
首页
  • 开发指南
  • Skill开发
  • 在线测试工具
  • Form组件
  • Crud组件
  • Default组件
  • Data组件
  • Component组件
产品
工作台
授权
联系
2.x文档
个人支付接口
首页
  • 开发指南
  • Skill开发
  • 在线测试工具
  • Form组件
  • Crud组件
  • Default组件
  • Data组件
  • Component组件
产品
工作台
授权
联系
2.x文档
个人支付接口
  • CRUD API
  • Object对象用法
  • 表格虚拟化
  • 分页
  • 搜索
  • 表头配置
  • 表格行配置项
  • 表格列配置项
  • 数据字典
  • 操作栏配置
  • 增删改查方法
  • 按钮文案和图标
  • 按钮自定义
  • 弹窗表单配置
  • 深层结构数据
  • 卡片模式
  • 统计合计
  • 导入导出
  • 表格树
  • 父子表
  • 行编辑
  • 权限控制
  • 动态行列合并
  • 空状态
  • 等待加载
  • 拖拽排序
  • 其它类型
  • 表格高级用法
  • 大表哥(宇宙最强表格)
  • CRUD模块封装
  • CRUD极简增删改查封装

分页

v-model:page 控制分页器,data 是已经加载的当前页记录。CRUD 不会自动对完整数组分页,也不会自动调用业务接口。

页码和条数

效果预览可直接操作下方示例

currentPage 是从 1 开始的页码,total 是总记录数,pageSize 是每页条数。分页器默认每页 10 条;示例可通过输入修改分页参数。

正在加载示例…
<template>
  <p>
    页码:{{page.currentPage}}
    <el-button type="primary"
               @click="page.currentPage=page.currentPage+1">页码+1</el-button>
  </p>
  <p>
    条数:{{page.pageSize}}
    <el-button type="primary"
               @click="page.pageSize=page.pageSize+10">条数+10</el-button>
  </p>
  <p>
    总数:{{page.total}}
    <el-button type="primary"
               @click="page.total=page.total+10">总记录数+10</el-button>
  </p>
  <avue-crud :data="data"
             :option="option"
             v-model:page="page"></avue-crud>

</template>
<script setup>
import { ref } from 'vue';
const data = ref([])
const page = ref({
  total: 1000,
  currentPage: 1,
  pageSize: 10
})
const option = ref({
  header: false,
  column: [{
    label: '姓名',
    prop: 'name'
  }]
})
</script>

设置最大页码按钮数

效果预览可直接操作下方示例

pagerCount 默认 7,页数较多时折叠中间页码,不影响真实总页数。

正在加载示例…
<template>
  <avue-crud :data="data"
             :option="option"
             v-model:page="page" />
</template>

<script setup>
import { ref } from 'vue';

const page = ref({
  pagerCount: 11,
  total: 1000
});
const data = ref([]);
const option = ref({
  header: false,
  column: [{
    label: '姓名',
    prop: 'name'
  }]
});
</script>

无背景色的分页

效果预览可直接操作下方示例

background 默认 true,设置 false 可以取消分页按钮背景。

正在加载示例…
<template>
  <avue-crud :data="data"
             :option="option"
             v-model:page="page"></avue-crud>
</template>
<script setup>
import { ref } from 'vue';
const page = ref({
  background: false,
  total: 1000
})
const option = ref({
  header: false,
  column: [{
    label: '姓名',
    prop: 'name'
  }]
})
const data = ref([])
</script>

附加功能

效果预览可直接操作下方示例

layout 用逗号分隔,桌面默认 total, sizes, prev, pager, next, jumper。显式设置可以选择需要的功能。

正在加载示例…
<template>
  <el-button @click="setSimpleMode">简单模式</el-button>
  <el-button @click="setComplexMode">复杂模式</el-button>
  <br /><br />
  <avue-crud :data="data"
             :option="option"
             v-model:page="page"></avue-crud>
</template>

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

const page = ref({
  total: 1000,
  layout: "total, sizes, prev, pager, next, jumper",
})

const data = ref([])
const option = {
  header: false,
  column: [{
    label: '姓名',
    prop: 'name'
  }]
}

const setSimpleMode = () => {
  page.value.layout = 'sizes,pager'
}

const setComplexMode = () => {
  page.value.layout = 'total, sizes, prev, pager, next, jumper'
}
</script>

综合用法

效果预览可直接操作下方示例

on-load(page) 会在初次创建、用户改变页码和每页条数时触发。本例在内存中按页截取数据,翻页后检查实际行 ID 和总记录数。

正在加载示例…
<template>
  <div>
    <avue-crud :data="data" :option="option" v-model:page="page" @on-load="onLoad" />
    <p aria-live="polite">第 {{ page.currentPage }} 页,共 {{ page.total }} 条;当前 ID:{{ data.map(row => row.id).join('、') }}</p>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const records = Array.from({ length: 23 }, (_, index) => ({
  id: index + 1,
  name: '成员 ' + (index + 1),
  department: index % 2 ? '产品部' : '研发部'
}));
const page = ref({ currentPage: 1, pageSize: 5, pageSizes: [5, 10, 20], total: records.length });
const data = ref([]);
const option = ref({
  rowKey: 'id',
  addBtn: false,
  menu: false,
  refreshBtn: false,
  gridBtn: false,
  columnBtn: false,
  column: [
    { label: 'ID', prop: 'id', width: 80 },
    { label: '姓名', prop: 'name' },
    { label: '部门', prop: 'department' }
  ]
});
function onLoad(current) {
  const start = (current.currentPage - 1) * current.pageSize;
  data.value = records.slice(start, start + current.pageSize).map(row => ({ ...row }));
}
</script>

page.total = 0 或 option.page = false 会隐藏分页区域。page.single = true 在总共只有一页时隐藏分页器,配置名不是 simplePage。修改每页条数会先将页码设为 1,再触发 on-load。

current-change 和 size-change 适合记录操作或处理附加状态;如果已经在 on-load 请求列表,就不要再在这两个事件中请求一次。

分页与搜索一起使用

效果预览可直接操作下方示例

输入姓名关键字或选择状态后搜索,结果会从第 1 页开始;翻页沿用已提交条件。状态「待处理」保存数字 0,也会参与过滤。清空恢复完整列表,刷新保留当前已提交的条件,下方显示每次加载所用参数。

正在加载示例…
<template>
  <div class="query-example">
    <avue-crud v-model:search="search"
               v-model:page="page"
               :data="data"
               :option="option"
               @on-load="loadList"
               @refresh-change="loadList"
               @search-change="searchChange"
               @search-reset="searchReset" />
    <div class="query-result" aria-live="polite">
      <strong>已加载 {{ requestCount }} 次 · 符合条件 {{ page.total }} 条</strong>
      <pre>{{ requestText }}</pre>
    </div>
  </div>
</template>

<script setup>
import { computed, ref } from 'vue';

const records = Array.from({ length: 36 }, (_, index) => ({
  id: index + 1,
  name: ['张三', '李四', '王五'][index % 3] + ' ' + (index + 1),
  status: index % 2
}));
const search = ref({});
const query = ref({});
const page = ref({ currentPage: 1, pageSize: 5, pageSizes: [5, 10, 20], total: 0 });
const data = ref([]);
const requestCount = ref(0);
const requestText = computed(() => JSON.stringify({
  currentPage: page.value.currentPage,
  pageSize: page.value.pageSize,
  ...query.value
}, null, 2));
const option = ref({
  rowKey: 'id',
  border: true,
  addBtn: false,
  menu: false,
  gridBtn: false,
  columnBtn: false,
  searchSpan: 12,
  searchMenuSpan: 24,
  column: [
    { label: 'ID', prop: 'id', width: 70 },
    { label: '姓名', prop: 'name', search: true, searchProp: 'keyword' },
    {
      label: '状态',
      prop: 'status',
      type: 'select',
      search: true,
      dicData: [
        { label: '待处理', value: 0 },
        { label: '已完成', value: 1 }
      ]
    }
  ]
});

// 用固定本地数据模拟业务接口;接入项目时替换这段加载逻辑。
function loadList() {
  const keyword = String(query.value.keyword || '').trim();
  const filtered = records.filter(row =>
    row.name.includes(keyword) &&
    (!Object.prototype.hasOwnProperty.call(query.value, 'status') || row.status === query.value.status)
  );
  page.value.total = filtered.length;
  const start = (page.value.currentPage - 1) * page.value.pageSize;
  data.value = filtered.slice(start, start + page.value.pageSize).map(row => ({ ...row }));
  requestCount.value += 1;
}
function searchChange(params, done) {
  query.value = { ...params };
  page.value.currentPage = 1;
  try {
    loadList();
  } finally {
    done();
  }
}
function searchReset() {
  query.value = {};
  page.value.currentPage = 1;
  loadList();
}
</script>

<style scoped>
.query-result {
  margin-top: 16px;
  padding: 16px;
  border-radius: 8px;
  background: var(--el-fill-color-light);
  overflow-wrap: anywhere;
}
.query-result pre { margin: 10px 0 0; white-space: pre-wrap; font-size: 13px; }
</style>

搜索输入对象与已经提交的查询条件应分别保存。这样输入但尚未提交的新值,不会意外改变翻页查询:

const searchChange = async (params, done) => {
  query.value = { ...params };
  page.value.currentPage = 1;
  try {
    await loadList();
  } finally {
    done();
  }
};

const searchReset = async () => {
  query.value = {};
  page.value.currentPage = 1;
  await loadList();
};

search-change、search-reset 和 refresh-change 不会自动调用 on-load。页码在代码中改变时也应主动加载;table-loading 由业务请求管理,请在 finally 中恢复。多个请求可能重叠时,取消旧请求或检查请求序号,避免旧页覆盖新页。

自定义分页

效果预览可直接操作下方示例

page 插槽可以在内置分页区域添加内容。总记录数赋给 total,不是把总页数赋给它。需要完全替换分页器时,可关闭 option.page 并在组件外使用自己的分页组件。

正在加载示例…
<template>
  {{ page }}
  <avue-crud :data="data"
             :option="option"
             v-model:page="page"
             @size-change="sizeChange"
             @current-change="currentChange" />
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';

const page = ref({
  currentPage: 1,
  total: 0,
  layout: "total,pager,prev,next",
  background: false,
  pageSize: 10
});

const data = ref([]);
const option = ref({
  align: 'center',
  menuAlign: 'center',
  column: [
    {
      label: '姓名',
      prop: 'name'
    },
    {
      label: '性别',
      prop: 'sex'
    }
  ]
});

function getList () {
  page.value.total = 40;
  if (page.value.currentPage === 1) {
    data.value = [
      { id: 1, name: '张三', sex: '男' },
      { id: 2, name: '李四', sex: '女' }
    ];
  } else if (page.value.currentPage === 2) {
    data.value = [
      { id: 3, name: '王五', sex: '女' },
      { id: 4, name: '赵六', sex: '女' }
    ];
  }
}

function sizeChange (val) {
  page.value.currentPage = 1;
  page.value.pageSize = val;
  getList();
  ElMessage.success(`行数 ${val}`);
}

function currentChange (val) {
  page.value.currentPage = val;
  getList();
  ElMessage.success(`页码 ${val}`);
}

onMounted(() => {
  getList();
});
</script>

完整字段见 Page API,保存、删除后的刷新见 增删改查。

最后更新:
贡献者: smallwei
Prev
表格虚拟化
Next
搜索