场景:用树形控件展示数据结构为树状的带有目录的文章标题,用uni-app插件市场的ly-tree实现,
地址:https://ext.dcloud.net.cn/plugin?id=1000
【注】:该组件存在问题,没办法用组件自带的方法defaultExpandedKeys实现父节点自动展开,于是另外写了一个方法getAbsolutePathByNodeKey去获取当前节点的所有父节点,或者可以采用组件自带的getNodePath方法获取当前节点的所有父节点
<template>
<view class="">
<movable-area class="moableArea" @tap="showNav">
<movable-view
class="movableView"
direction="vertical"
x="600rpx"
y="800rpx"
>
<view class="navigator-button">
<u-icon name="list-dot"></u-icon>
导航
</view>
</movable-view>
</movable-area>
<u-popup v-model="showNavList" mode="bottom" border-radius="18">
<view class="nav-top">
<view class="nav-title">导航</view>
<view class="learn-center-search">
<u-search
v-model="filterText"
:show-action="false"
height="80"
shape="square"
bg-color="#FFF"
placeholder-color="#999999"
border-color="#D9D9D9"
>
</u-search>
</view>
</view>
<scroll-view
scroll-y
style="width: 100%; height: 100%; padding-bottom: 20rpx"
>
<view class="nav-content">
<ly-tree
ref="tree"
:tree-data="manualList"
:filter-node-method="filterNode"
:ready="ready"
node-key="id"
@node-expand="handleNodeExpand"
@node-click="handleNodeClick"
:props="props"
:check-on-click-node="true"
:highlight-current="true"
:current-node-key="id"
:default-expanded-keys="defaultExpandedKeys"
:accordion="true"
>
</ly-tree>
</view>
</scroll-view>
</u-popup>
</view>
</template>
<script>
import LyTree from "@/components/ly-tree/ly-tree.vue";
export default {
data() {
return {
showNavList: false,
ready: false, //这里用于自主控制loading加载状态,避免异步正在加载数据的空挡显示“暂无数据”
manualList: [],
props: {
label: "name",
children: "children",
},
filterText: "",
defaultExpandedKeys: [],
parentIdList: [],
parentList: [],
};
},
components: {
LyTree,
},
props: {
id: {
type: String,
default: () => {
return "";
},
},
},
mounted() {
let vm = this;
vm.$nextTick(() => {
vm.getManualList();
});
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
},
methods: {
//可以通过这个算法去获取当前节点的所有父节点
// getAbsolutePathByNodeKey(key) {
// let vm = this;
// let stack = [];
// function find(key, rest) {
// for (let i = 0, arr = rest, len = arr.length; i < len; i++) {
// let node = arr[i];
// stack.push(node.id);
// if (node.id === key) {
// return stack;
// } else if (node.children && node.children.length > 0) {
// let temp = find(key, node.children);
// if (temp[temp.length - 1] === key) return temp;
// else temp.pop();
// if (i + 1 < len) continue;
// return temp;
// } else {
// stack.pop();
// if (i + 1 < len) continue;
// return stack;
// }
// }
// }
// return find(key, vm.treeData);
// },
showNav() {
let vm = this;
vm.showNavList = true;
vm.parentIdList = [];
vm.$nextTick(() => {
if (vm.id) {
vm.$refs.tree.setCurrentKey(vm.id);
//通过getNodePath方法找到当前节点的所有父节点,并把id都push到一个空数组里
vm.parentList = vm.$refs.tree.getNodePath(vm.id);
for (let i = 0; i < vm.parentList.length; i++) {
vm.parentIdList.push(vm.parentList[i].id);
}
vm.defaultExpandedKeys = vm.parentIdList;
// vm.defaultExpandedKeys = vm.getAbsolutePathByNodeKey(
// vm.currentNodeKey
// );
}
});
},
//过滤节点的方法
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
// uni-app中emit触发的方法只能接受一个参数,所以会回传一个对象,打印对象即可见到其中的内容
handleNodeClick(obj) {
if (obj.data.type == "article") {
let platformList = {
1: "圆方1.0",
2: "数据集市",
3: "Seele平台",
4: "圆方2.0",
};
switch (obj.data.rootName) {
case "最新动态":
uni.navigateTo({
url: `/pages/learnCenter/components/detailPage?newsId=${
obj.data.id
}&platform=${
platformList[obj.data.data.platform]
}&module=${obj.data.rootName}`,
});
break;
case "使用手册":
uni.navigateTo({
url: `/pages/learnCenter/components/detailPage?issueId=${
obj.data.id
}&platform=${
platformList[obj.data.data.platform]
}&module=${obj.data.rootName}`,
});
break;
case "教学社区":
uni.navigateTo({
url: `/pages/learnCenter/components/detailPage?documentId=${
obj.data.id
}&platform=${
platformList[obj.data.data.platform]
}&module=${obj.data.rootName}`,
});
break;
case "视频教学":
uni.navigateTo({
url: `/pages/learnCenter/components/videoDetail?videoId=${
obj.data.id
}&platform=${
platformList[obj.data.data.platform]
}&module=${obj.data.rootName}`,
});
break;
default:
break;
}
}
},
handleNodeExpand(obj) {
console.log("handleNodeExpand", obj);
},
//处理数据结构的方法
parse(root, newRoot) {
let vm = this;
let i;
let len;
let node;
let newNode;
len = root.length;
for (i = 0; i < len; i++) {
node = root[i];
newNode = {};
if (
node.issueId ||
node.newsId ||
node.documentId ||
node.videoId
) {
if (node.issueId) {
newNode.id = node.issueId;
newNode.rootName = "使用手册";
}
if (node.newsId) {
newNode.id = node.newsId;
newNode.rootName = "最新动态";
}
if (node.documentId) {
newNode.id = node.documentId;
newNode.rootName = "教学社区";
}
if (node.videoId) {
newNode.id = node.videoId;
newNode.rootName = "视频教学";
}
newNode.name = node.title;
newNode.status = node.status;
newNode.type = "article";
newNode.isSelect = false;
} else if (node.catalogueId) {
newNode.id = node.catalogueId;
newNode.name = node.catalogueName;
newNode.type = "catalog";
newNode.children = [];
newNode.catalogNode = true;
newNode.topId = node.topId;
if (node.catalogueResponseList) {
vm.parse(node.catalogueResponseList, newNode.children);
}
if (node.objectList) {
vm.parse(node.objectList, newNode.children);
}
}
newNode.data = {
...node,
};
newRoot.push(newNode);
}
},
//获取后台数据
getManualList() {
let vm = this;
return new Promise((resolve, reject) => {
vm.$req
.doRequest({
alias: "dcs-catalogue-getCatalogueTree",
query: {
id: "0",
type: "2",
},
})
.then((res) => {
if (res.code == 0) {
vm.tempList = res.data.filter(
(item) => item.catalogueName != "优秀案例"
);
vm.parse(vm.tempList, vm.manualList);
vm.ready = true;
}
return resolve();
});
});
},
},
};
</script>
<style lang="less" scoped>
/deep/.ly-tree-node__content.is-current {
background-color: inherit;
color: #0a63f1;
}
/deep/.is-expanded {
}
.nav-top {
background: #fbfbfb;
border-bottom: 1px solid #e9e9e9;
padding: 36rpx 0 34rpx;
.nav-title {
margin: 0 46rpx 26rpx;
font-family: PingFangSC-Medium;
font-size: 32rpx;
color: #333333;
letter-spacing: 0.02px;
}
.u-search {
margin: 42rpx auto 0 !important;
width: 90%;
}
}
.nav-content {
background: #fff;
padding: 20rpx 46rpx 38rpx;
max-height: 962rpx;
/deep/.ly-tree {
padding: 0 !important;
}
/deep/.ly-tree-node__label {
font-size: 30rpx;
}
/deep/.ly-empty {
margin-top: 48rpx;
}
}
.navigator-button {
background: #ffffff;
border-radius: 39rpx 0 0 39rpx;
border-radius: 39rpx 0 0 39rpx;
box-shadow: -4rpx 0 10rpx 0 rgba(0, 0, 0, 0.2);
font-size: 28rpx;
color: #202020;
padding-left: 16rpx;
/deep/ .uicon-list-dot {
top: 3.8rpx !important;
margin-right: 1px;
font-size: 36rpx !important;
margin: 0 10rpx 0 10rpx;
color: #000;
}
}
.moableArea {
position: fixed;
top: 0;
left: 50rpx;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 99999;
}
.movableView {
pointer-events: auto;
width: 186rpx;
height: 78rpx;
line-height: 78rpx;
}
</style>