You need to enable JavaScript to run this app. Vue b-pagination如何在对应数据不存在时隐藏对应分页按钮
优惠活动
大模型
产品
解决方案
定价
更多

Vue b-pagination如何在对应数据不存在时隐藏对应分页按钮

问题根源说明

Bootstrap Vue 的 b-pagination 分页按钮渲染逻辑完全由传入的 total-rows、per-page 参数驱动,page 插槽仅用于替换按钮内部的显示内容,不会从组件的底层渲染逻辑移除对应按钮的DOM节点。即使插槽内返回空内容,按钮的基础结构依然会生成,最终就出现了无内容的空白占位按钮。

可行实现方案

根据你的业务里无效分页按钮的分布场景,可以选择对应方案:

方案1:无效页为末尾连续场景(即从某一页开始后面全是无内容的页)

直接在组件计算逻辑层面限制最大渲染页数,让组件根本不会生成无内容的按钮,从根源解决问题:

  1. 新增计算属性,逐页校验是否有对应有效内容,一旦遇到第一页无内容,就截止计算最大有效页数:
    computed: {
      // 计算存在有效内容的最大页码
      validMaxPage() {
        for (let page = 1; page <= this.submissionFiles.length; page++) {
          // 校验当前页是否存在匹配当前学生页的有效数据
          const hasValidContent = Boolean(
            this.submissionFiles[page - 1]?.[this.currentStudentPage - 1]
          )
          // 遇到第一个无内容的页,返回上一页作为最大有效页
          if (!hasValidContent) {
            return page - 1
          }
        }
        // 所有页都有有效内容时,返回数组总长度
        return this.submissionFiles.length
      }
    }
    
  2. 替换组件的total-rows入参,把原来的全量数组长度改成基于有效页数计算的值:
    <!-- 原来的 :total-rows="submissionFiles.length" 替换成下面的写法 -->
    <b-pagination
      :total-rows="validMaxPage * perPage"
      <!-- 其他原有配置保持不变 -->
    >
    

这种方式因为从组件参数层面限制了总页数,组件生成的按钮全是有有效内容的,不会出现空白按钮。

方案2:无效页为非连续分布场景(即中间夹杂无内容的页)

因为b-pagination本身默认是生成从1到N的连续页码,不支持跳过中间的无效页,有两种实现路径:

路径A:基于计算属性手动生成有效页列表,替代组件自动的连续页码逻辑

不依赖组件的自动连续页码生成能力,完全自己控制要渲染的分页按钮:

  1. 先计算当前场景下所有存在有效内容的页码列表:
    computed: {
      // 筛出所有有有效内容的页码
      validPageList() {
        const result = []
        this.submissionFiles.forEach((fileItem, index) => {
          const pageNum = index + 1
          const hasContent = Boolean(fileItem?.[this.currentStudentPage - 1])
          if (hasContent) {
            result.push(pageNum)
          }
        })
        return result
      }
    }
    
  2. 基于这个有效页列表,自定义渲染分页按钮,直接跳过无内容的页,从根源上不生成对应的DOM。如果还是想保留b-pagination的样式,也可以配合手动渲染的结构复用组件的分页类名,实现和原生分页一致的视觉效果。

路径B:兼容保留b-pagination原生结构,通过CSS隐藏无效按钮

如果不想改动原有组件结构,可以配合插槽标记+CSS隐藏的方式实现无内容按钮的视觉隐藏:

  1. 在page插槽内,对无有效内容的页打标记:
    <template v-slot:page="{ page, active }">
      <span v-if="!submissionFiles[page - 1]?.[currentStudentPage - 1]" class="invalid-page-marker"></span>
      <span v-else>
        {{ submissionFiles[page - 1][currentStudentPage - 1].order }}
      </span>
    </template>
    
  2. 新增CSS规则,把带标记的无效按钮对应的父级节点隐藏:
    /* 隐藏标记本身 */
    .b-pagination .invalid-page-marker {
      display: none;
    }
    /* 找到包裹标记的分页li元素,整体隐藏 */
    .b-pagination li:has(.invalid-page-marker) {
      display: none !important;
    }
    

注意:这种方式依赖CSS的:has选择器,仅兼容较新版本浏览器,低版本场景不适用。而且本质是CSS隐藏DOM,不是从渲染逻辑上阻止DOM生成。

代码优化建议

你原有插槽的取值逻辑存在空指针报错风险,当submissionFiles[page-1]为undefined时,直接访问内层数组会抛出错误,建议统一改成可选链的写法:

<!-- 原来的取值逻辑 -->
{{ submissionFiles[page - 1][currentStudentPage - 1] && submissionFiles[page - 1][currentStudentPage - 1].order }}
<!-- 优化后避免报错的写法 -->
{{ submissionFiles[page - 1]?.[currentStudentPage - 1]?.order }}

另外你给组件加的:key="currentQuestionPage"属性没必要,会导致currentQuestionPage变化时整个分页组件重新渲染,增加不必要的性能开销,因为currentQuestionPage本身就是组件绑定的v-model值,不需要额外强制重渲染。

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.24 13:57:02