1. 什么是无限级列表?
无限级列表,又称无限层级列表,是指可以展示无限深度的多层级树形结构。最常见的应用场景包括商品分类、地区选择、组织架构等多种业务场景中。
在无限级列表中,每个节点都可以有任意数量的子节点,因此可以实现非常复杂的数据展示和交互需求。
2. Vue 是什么?
Vue.js 是一套构建用户界面的渐进式框架,与 React、Angular 等框架相比,它相对较小、易上手、易扩展,是当前业内最流行的前端框架之一。
3. 使用 Vue 实现无限级列表的步骤
3.1 结构分析
在实现无限级列表之前,我们需要先了解数据的结构和组件的拆分,把整个页面划分为多个组件,以便于维护和复用。
下面是一个简单的数据结构示意图:
{
label: '节点1',
children: [
{
label: '节点1-1',
children: [
{
label: '节点1-1-1',
children: []
}
]
},
{
label: '节点1-2',
children: []
}
]
}
该数据结构由多个节点组成,每个节点包含两个字段:label 字段表示当前节点的文本内容,children 字段表示当前节点的子节点数组,如果 children 是空数组,则表示当前节点为叶子节点。
在组件拆分方面,我们可以将整个无限级列表划分为三个组件:
TreeView:整个树形结构组件,负责渲染节点和展开/折叠状态
TreeNode:树形节点组件,负责渲染节点文本和子节点
TreeLoading:树形节点加载中组件,负责在子节点异步加载时显示加载中状态
3.2 渲染树形结构
在 TreeView 组件中,我们通过递归的方式实现对整个树形结构的渲染:
<template>
<ul class="tree">
<li v-for="(node, index) in treeData" :key="index">
<tree-node :node="node" @toggle="toggleNode"></tree-node>
</li>
</ul>
</template>
<script>
import TreeNode from './TreeNode'
export default {
name: 'TreeView',
components: {
TreeNode
},
props: {
treeData: {
type: Array,
required: true
}
},
methods: {
toggleNode(node) {
node.expanded = !node.expanded
}
}
}
</script>
其中,treeData 是树形结构的根节点数组,通过 v-for 指令进行渲染,每个节点通过 <tree-node>
组件进行递归渲染。
在 toggleNode 方法中,我们通过修改 expanded 属性来控制节点的展开和折叠状态。
3.3 渲染树形节点
在 TreeNode 组件中,我们通过递归的方式实现对整个树形节点的渲染:
<template>
<div class="tree-node">
<span class="label" :class="{ 'has-children': hasChildren }" @click="handleClick">
<i v-if="hasChildren" class="icon" :class="{ 'icon-fold': node.expanded, 'icon-unfold': !node.expanded }"></i>
{{ node.label }}
</span>
<ul v-if="node.expanded">
<li v-for="(childNode, index) in node.children" :key="index">
<tree-node :node="childNode" @toggle="$emit('toggle', childNode)"></tree-node>
</li>
<tree-loading v-if="node.loading"></tree-loading>
</ul>
</div>
</template>
<script>
import TreeLoading from './TreeLoading'
export default {
name: 'TreeNode',
components: {
TreeLoading
},
props: {
node: {
type: Object,
required: true
}
},
computed: {
hasChildren() {
return this.node.children && this.node.children.length > 0
}
},
methods: {
handleClick() {
if (this.hasChildren) {
if (!this.node.expanded && this.node.children.length === 0) {
this.loadChildren()
} else {
this.$emit('toggle', this.node)
}
}
},
async loadChildren() {
this.node.loading = true
// 省略异步加载子节点的逻辑
await this.$nextTick()
this.node.expanded = true
this.node.loading = false
}
}
}
</script>
其中,node 属性表示当前节点,通过 <span class="label">
渲染节点的文本内容,通过计算属性 hasChildren 判断当前节点是否有子节点。
在 handleClick 方法中,我们通过判断节点是否有子节点来决定是展开还是折叠节点。如果该节点已经展开过或者没有子节点,则直接切换节点的展开/折叠状态。如果该节点没有展开过并且有子节点,则显示加载中状态并异步加载子节点,加载完成后自动展开该节点。
在 loadData 方法中,我们通过设置 loading 属性来显示加载中状态,然后通过异步请求获取子节点数据,加载完成后将数据设置到节点的 children 属性上,并将 loading 状态设置为 false。
3.4 渲染树形节点加载中状态
在 TreeLoading 组件中,我们简单地显示一个加载中的图标:
<template>
<div class="tree-loading">
<span class="loading-text">加载中...</span>
</div>
</template>
<script>
export default {
name: 'TreeLoading'
}
</script>
4. 完整代码
下面是基于 Vue 实现无限级列表的完整代码:
5. 总结
无限级列表是前端开发中常见的数据展示方式,通过 Vue 框架可以轻松地实现该功能。在实现无限级列表时,我们需要考虑数据的结构和组件的拆分,以便于代码的维护和复用。同时,通过异步加载子节点,可以实现更好的用户体验。