前言
昨天做的项目中,有个需求是这样的:
项目是关于知识学习的培训平台,里面有课程和资料,课程和资料均展示多级目录(无限级) ,展示方式与B站上的视频目录同理,只不过我们需要无限级。要求在目录上方展示"共几个视频/资料" 。
备注:项目是Vue2的。
项目页面展示和接口结构
如下图所示,这样看可能会比较直接。目录是一个数组,里面有无限个 children(子数组)
,children
里面也会有无限层 children
。
下图中只有两层数组,第三层children
为空,本文将以这个为例进行说明,每层用了不同颜色标注,方便对应。
备注:我只需要计算可播放的视频的总数量。
比如,如果有两层目录,第二层直接对应视频,需要计算视频的数量,第一层的目录不需计算。
实现思路
在Vue中,可以使用递归 来处理无限嵌套数组并计算其子元素的个数。
其实这就是一个普通js
的写法,只是写在vue项目中。
实现方案
- 首先,我们需要定义一个名为
countSubElements
的函数(名字自定义即可,最好遵循语义化原则),该函数接收一个参数arr
表示当前待统计的数组。 - 然后,通过判断数组的每个元素类型,如果是对象或者数组则调用自身进行递归操作;否则直接返回1(因为非对象、非数组都被视为单个子元素)。
- 最后将所有子元素的个数相加得到结果。
具体代码如下图:
- 此为通用思路代码:
js
/** 此为通用思路代码 **/
function countSubElements(arr) {
let total = 0; // 记录子元素个数的变量
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i]) || typeof arr[i] === 'object') {
total += countSubElements(arr[i]); // 递归调用自身
} else {
total++; // 非对象、非数组被认为是单个子元素
}
}
return total;
}
// 测试样例
const nestedArr = [1, [2], [[3]], [{}, []]];
console.log('子元素个数:', countSubElements(nestedArr));
// 输出结果为:6
- 此为适配我项目中的代码(因为我的需求是计算"视频总数量",所以只需要计算可播放的子元素即可,不需要将外层无法播放的目录计算进去)。
js
/** 此为适配我项目中的代码 **/
// 无限多维数组数量计算
this.elementsLength = this.countSubElements(data.details); // [调用]
countSubElements(arr) {
let total = 0; // 记录子元素个数的变量
for (let i = 0; i < arr.length; i++) {
if (arr[i].children && arr[i].children.length) {
total += this.countSubElements(arr[i].children); // 递归调用自身
} else {
total++; // 非对象、非数组被认为是单个子元素
}
}
return total;
}
将项目中相关的所有代码全部附上
下图为页面中数量的显示位置:
所有代码如下:
html
<div class="menu-info-right">共{{ elementsLength }}个视频</div>
js
export default {
data() {
return {
elementsLength: 0, // 统计视频/资料数量
}
},
created() {
this.getCourseInfo();
},
methods: {
// 获取视频页数据
getCourseInfo() {
courseInfoApi({
id: this.courseId,
}).then(res => {
// 无限多维数组数量计算
this.elementsLength = this.countSubElements(data.details);
})
},
// 无限多维数组length计算
countSubElements(arr) {
let total = 0; // 记录子元素个数的变量
for (let i = 0; i < arr.length; i++) {
if (arr[i].children && arr[i].children.length) {
total += this.countSubElements(arr[i].children); // 递归调用自身
} else {
total++; // 非对象、非数组被认为是单个子元素
}
}
return total;
}
}
}
以上,希望对大家有帮助!