1.需求:
类似于 百度网盘、阿里云盘的 云文件夹管理功能
2.问题点
1.页面刷新 导致面包屑子级未持久化
2.浏览器的 前进、后退 ;面包屑未能 跳转到指定 子级
3.数据不同步问题
3.解决方法
1.后端提供 根据 id 查询面包屑 text 的 api【这里并没有提供】
2.建立自己的 map 库,并自行进行对比选择
3.监听浏览器 前进后退
《思路灵感》
当时一直没有很好的思路,周末在刷手机的时候,看到有一名up主在玩“红警”;他说:“我们前期先 用狗子 进行地图的探索”……
💡 那我们也可以让用户 建立自己的 map
【url 说明】
http://localhost:8080/#/cloud/myf 【根路径】
http://localhost:8080/#/cloud/myf?id=1782957532607504385&path=0,1782957532607504385【非跟路径,文件夹id 为 1782957532607504385 的目录下;path 路径为 0<根路径>,1782957532607504385<文件夹>】
核心代码
监听浏览器是否点击了前进或后退
【其中 getFileList 是选择性加载 table 中的数据,比如判断是 根路径<默认加载第一页数据>;子路径<根据id查询子数据第一页数据> 等】
window.addEventListener("popstate", async function (evt) {
await getFileList()
await checkRouter()
}, false);
这里只展示 checkRouter 的核心对比方法【详细参数说明参考方法下面】
/**
* 面包屑核心对比 过程
*/
const checkRouter = async () => {
const pathTemplateDb = sessionStorage.getItem("pathTemplateDb")
if (pathTemplateDb) {
const pathTemplateDbObj = await JSON.parse(pathTemplateDb);
const path = route.query.path ? route.query.path.split(',') : "0"
const targetArray = []
if (path === "0") {
targetArray.push({path: "0", text: "全部文件", tag: "0"})
} else {
for (let i = 0; i < pathTemplateDbObj.length; i++) {
for (let j = 0; j < path.length; j++)
if (pathTemplateDbObj[i].tag === path[j]) {
targetArray.push(pathTemplateDbObj[i])
}
}
}
pathArray.value = targetArray;
sessionStorage.setItem('pathArray', JSON.stringify(pathArray.value))
}
}
【说明 1 】pathArray 是记录 要显示的 面包屑的实时路径 数组
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(item, index) in pathArray" :key="item.path"
@click.native.stop="handleClick(item, index)">
<span
style="cursor: pointer">{{ item.text }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
// 面包屑
const pathArray = ref([
{path: '0', text: '全部文件', tag: "0"}
])
【说明 2】handleClick 是 点击面包屑 实现 路径的切换
核心代码
const handleClick = throttle(async (item, index) => {
...
const targetIndex = findIndexWithTag(pathArray.value, item.tag);
if (item.tag !== "0") {
// 子路由
await router.push({path: route.path, query: {id: item.tag, path: item.path}})
} else {
// 根路由
await router.push({path: route.path})
}
pathArray.value = pathArray.value.slice(targetIndex, targetIndex + 1)
...
})
// 寻找到 用户点击的 面包屑的值的索引值,并且后面的子路径都不要了
function findIndexWithTag(jsonData, flag) {
for (var i = 0; i < jsonData.length; i++) {
if (jsonData[i].tag === flag) {
return i;
}
}
return -1;
}
【说明 3】enterDirectory 是用户点击文件夹 进入文件夹的操作【这里其实就是 “狗子” 建立map 的过程 pathTemplateDb 就是用户自己的 map】
// 自己构建的 map
const pathTemplateDb = ref([
{path: '0', text: '全部文件', tag: "0"}
])
const enterDirectory = throttle(async (row) => {
...
// 是文件夹
const filterTagsArray = pathArray.value.map(item => item.tag)
const targetPath = [...filterTagsArray, row.id].join(',')
tempRouter.value = targetPath;
pathArray.value.push({path: targetPath, text: row.fileName, tag: row.id})
const target = JSON.parse(sessionStorage.getItem('pathTemplateDb')) || [{path: '0', text: '全部文件', tag: "0"}]
//当用户首次进入文件夹的时候建立 map 《防止其中有重复的内容》
if (!target.filter(_ => _.tag === row.id).length >= 1) {
pathTemplateDb.value = [...target, {
path: targetPath,
text: row.fileName,
tag: row.id
}
]
sessionStorage.setItem('pathTemplateDb', JSON.stringify(pathTemplateDb.value))
}
// 数据持久化
sessionStorage.setItem('pathArray', JSON.stringify(pathArray.value))
...
})
小结
- 总得来说就是两个数组pathArray、pathTemplateDb、url 之间的操作,根据 url 中的 id 或 path 从 pathTemplateDb 查询对应数据 并 实时更改 pathArray
- 灵感来源于生活处处地方