AngularJS嵌套ng-repeat内容分页适配视口问题求助
基于视口高度的嵌套ng-repeat分页解决方案
我来给你梳理一个适配动态高度的分页方案——毕竟固定slice(0,10)的方式,完全没法应对这种外层项高度不一的嵌套场景(有的日期下节目多,高度就高;有的少,高度就低)。咱们核心思路是先计算每个外层项的实际高度,再根据视口高度动态拆分分页,具体实现如下:
1. 控制器层面的分页逻辑(AngularJS 1.x)
首先在控制器里处理高度计算、分页拆分和窗口 resize 适配:
app.controller('EpgController', function($scope, $window, $timeout) { // 假设你的epgDates已经是接口返回的数据源 $scope.epgDates = [...]; $scope.currentPage = 1; $scope.paginatedItems = []; // 获取可用视口高度(记得减去页面固定栏的高度,比如顶部导航、底部状态栏) const getUsableViewportHeight = () => { return $window.innerHeight - 120; // 这里的120是示例值,根据你的页面调整 }; // 计算单个外层项(包含日期标题+内层所有节目)的总高度 const getItemTotalHeight = (itemEl) => { return itemEl.offsetHeight; }; // 核心:根据视口高度拆分epgDates为分页数组 const splitIntoPages = () => { $scope.paginatedItems = []; let currentPageGroup = []; let currentPageTotalHeight = 0; const viewportHeight = getUsableViewportHeight(); // 必须等DOM渲染完成才能拿到正确的元素高度,所以用$timeout延迟执行 $timeout(() => { const outerItems = document.querySelectorAll('.outer-ng-repeat'); for (let i = 0; i < outerItems.length; i++) { const itemHeight = getItemTotalHeight(outerItems[i]); // 如果当前页加上这个项就超过视口高度,就把当前页存起来,开新页 if (currentPageTotalHeight + itemHeight > viewportHeight && currentPageGroup.length > 0) { $scope.paginatedItems.push([...currentPageGroup]); currentPageGroup = []; currentPageTotalHeight = 0; } currentPageGroup.push($scope.epgDates[i]); currentPageTotalHeight += itemHeight; } // 把最后一组未完成的页加进去 if (currentPageGroup.length > 0) { $scope.paginatedItems.push(currentPageGroup); } // 防止切换窗口后页码超出范围 if ($scope.currentPage > $scope.paginatedItems.length) { $scope.currentPage = 1; } }, 0); }; // 初始化分页,同时监听窗口大小变化重新计算 $scope.initPagination = () => { splitIntoPages(); angular.element($window).on('resize', () => { $scope.$apply(() => { splitIntoPages(); }); }); }; // 页码切换方法 $scope.switchPage = (pageNum) => { if (pageNum >= 1 && pageNum <= $scope.paginatedItems.length) { $scope.currentPage = pageNum; } }; // 页面加载完成后触发初始化 $timeout(() => { $scope.initPagination(); }, 0); });
2. 修改HTML模板,适配分页数据
把原来的直接遍历epgDates改成遍历当前页的分组数据,同时加上分页控制按钮:
<!-- 分页控制区 --> <div class="epg-pagination"> <button ng-disabled="currentPage === 1" ng-click="switchPage(currentPage - 1)">← 上一页</button> <span>第 {{currentPage}} 页 / 共 {{paginatedItems.length}} 页</span> <button ng-disabled="currentPage === paginatedItems.length" ng-click="switchPage(currentPage + 1)">下一页 →</button> </div> <!-- 渲染当前页的嵌套内容 --> <ul> <li class="outer-ng-repeat" ng-repeat="epgDate in paginatedItems[currentPage - 1]"> <h3>{{epgDate.dateText}}</h3> <!-- 这里替换成你的日期显示字段 --> <div class="inner-container"> <div class="nested-ng-repeat" ng-repeat="epg in epgDate.epg"> <div class="telecast__name">{{epg.programName}}</div> <!-- 替换成你的节目名称字段 --> </div> </div> </li> </ul>
3. 关键注意点
- DOM渲染时机:一定要用
$timeout包裹高度计算逻辑,不然DOM还没渲染出来,拿不到正确的元素高度,分页就会出错。 - 视口高度校准:
getUsableViewportHeight里减去的数值,一定要对应你页面上固定元素的高度(比如顶部导航栏占了80px,底部工具栏占了40px,就减120),不然内容会被遮挡或者留白太多。 - 窗口resize适配:监听窗口大小变化重新计算分页,保证在用户调整窗口尺寸时,分页能自动适配。
4. 备选方案:虚拟滚动
如果分页不是必须的,也可以考虑用虚拟滚动来优化性能——只渲染当前视口内的内容,不用一次性把所有数据都渲染出来。不过虚拟滚动的逻辑会比分页复杂一些,如果不想引入第三方库,自己实现的话需要监听滚动事件,计算元素的位置,动态控制元素的显示/隐藏。
内容的提问来源于stack exchange,提问作者La_Concorde
相关产品推荐
相关产品推荐

