使用Vuex getter赋值的BootstrapVue表格为何无法启用内置排序功能
问题根本原因
- BootstrapVue的
b-table默认开启的排序功能,会尝试原地修改你绑定给items属性的数组,来完成排序后的视图更新 - Vuex的核心规则是所有state的修改必须通过
mutation提交,直接修改state(包括state衍生的getter返回的对应原state数组的引用)的操作会被Vuex静默拦截,不会实际触发状态变更,因此排序后的数组没法更新到视图,看起来就像排序功能失效 - 你用axios直接请求数据赋值给组件本地
data属性时,这个数组是组件内可直接修改的普通响应式变量,没有修改限制,所以排序功能可以正常运行
解决方案
方案1:浅拷贝数组到组件本地(最简便)
如果该表格数据不需要和其他组件共享状态变更,你可以在拿到getter返回的数组后做一层浅拷贝,赋值给组件本地的data属性,直接给b-table绑定这个本地数组即可,和你用axios请求赋值的逻辑效果完全一致,无需额外修改排序逻辑:
<script> export default { data() { return { tableItems: [] } }, mounted() { // 浅拷贝避免直接操作Vuex的state数组 this.tableItems = [...this.$store.getters.tableItems] } } </script>
方案2:使用受控排序逻辑,适配Vuex规则
如果你需要把表格的排序状态也统一放到Vuex管理,可以使用b-table的sort-by和sort-desc受控属性,自定义排序逻辑:
<template> <b-table :items="sortedTableItems" :sort-by="sortBy" :sort-desc="sortDesc" @sort-changed="handleSortChange" ></b-table> </template> <script> import { mapGetters, mapState } from 'vuex' export default { computed: { ...mapGetters(['originalTableItems']), ...mapState(['sortBy', 'sortDesc']), sortedTableItems() { // 该排序逻辑也可以直接放到Vuex的getter中实现 const items = [...this.originalTableItems] if (!this.sortBy) return items return items.sort((a, b) => { if (a[this.sortBy] > b[this.sortBy]) return this.sortDesc ? -1 : 1 if (a[this.sortBy] < b[this.sortBy]) return this.sortDesc ? 1 : -1 return 0 }) } }, methods: { handleSortChange(ctx) { // 提交mutation更新Vuex内存储的排序参数 this.$store.commit('updateTableSort', { sortBy: ctx.sortBy, sortDesc: ctx.sortDesc }) } } } </script>
方案3:使用服务端排序
如果你的数据量较大,可以开启b-table的remote属性,监听排序事件后向后端请求排序完成的数据,更新到Vuex后再渲染即可。
内容的提问来源于stack exchange,提问作者djwest
相关产品推荐
相关产品推荐

