修改 uniapp中的ba-tree-picker插件,只能单选,选中后返回选中值以及所有父级值,vue3写法,原始数据结构为:"[{"city": "重庆市", "children": [{"area": "武隆区", "children": [{"street": "仙女山街道", "children": [{"children": "", "community": "石梁子社区治理中心"},]}]}]}]"
时间: 2025-05-23 22:24:13 浏览: 24
### 修改 `ba-tree-picker` 插件以支持单选功能并返回选中值及所有父级值
在 UniApp 中,基于 Vue3 对 `ba-tree-picker` 插件进行改造,使其能够实现单选功能,并在选中后返回选中值及其所有父级值。以下是详细的解决方案。
---
#### 数据结构假设
给定的数据结构为嵌套对象数组,例如:
```javascript
const treeData = [
{
city: "重庆市",
children: [
{
area: "武隆区",
children: [
{
street: "仙女山街道",
children: [
{ community: "石梁子社区治理中心" }
]
}
]
}
]
}
];
```
---
#### 实现思路
1. **单选逻辑**:通过事件监听机制捕获用户的点击操作,并记录当前选中的节点。
2. **父级路径提取**:编写递归函数,从顶层数据向下查找目标节点的所有父级节点。
3. **组件封装**:将上述逻辑封装到 `ba-tree-picker` 的核心方法中,确保其兼容 Vue3 的响应式特性。
---
#### 完整代码示例
##### 主组件(调用方)
```vue
<template>
<view class="container">
<button @click="openPicker">打开树形选择器</button>
<baTreePicker
ref="treePickerRef"
:localdata="treeData"
value-key="id"
text-key="name"
children-key="children"
:multiple="false"
@select-change="handleSelectChange"
/>
</view>
</template>
<script setup>
import { ref } from "vue";
import baTreePicker from "./components/ba-tree-picker.vue";
// 树形数据
const treeData = ref([
{
id: "1",
name: "重庆市",
children: [
{
id: "1-1",
name: "武隆区",
children: [
{
id: "1-1-1",
name: "仙女山街道",
children: [{ id: "1-1-1-1", name: "石梁子社区治理中心" }]
}
]
}
]
}
]);
// 打开选择器
const treePickerRef = ref(null);
function openPicker() {
treePickerRef.value.show();
}
// 处理选中变化
function handleSelectChange(selectedInfo) {
console.log("选中信息:", selectedInfo);
}
</script>
```
---
##### 自定义 `ba-tree-picker` 组件
对原生插件的核心逻辑进行调整,增加单选模式下的父子关系处理能力。
###### 1. 单选逻辑与父级路径提取
```javascript
export default {
props: {
localdata: {
type: Array,
default: () => []
},
multiple: {
type: Boolean,
default: false // 默认关闭多选
},
valueKey: {
type: String,
default: "id"
},
textKey: {
type: String,
default: "name"
},
childrenKey: {
type: String,
default: "children"
}
},
emits: ["select-change"],
data() {
return {
selectedNode: null, // 当前选中的节点
parentPathCache: [] // 父级路径缓存
};
},
methods: {
/**
* 查找指定节点的父级路径
*/
getParentPath(data, targetId) {
let path = [];
function findParents(nodes) {
for (let i = 0; i < nodes.length; i++) {
if (!nodes[i][this.childrenKey]) continue;
if (
nodes[i][this.childrenKey].some(
(child) => child[this.valueKey] === targetId
)
) {
path.push(nodes[i]);
break;
} else {
findParents.call(this, nodes[i][this.childrenKey]);
}
}
}
findParents.call(this, data);
return path.reverse(); // 反转得到从根到叶子的顺序
},
/**
* 更新选中状态
*/
updateSelection(node) {
this.selectedNode = node;
this.parentPathCache = this.getParentPath(this.localdata, node[this.valueKey]); // 计算父级路径
this.$emit("select-change", {
currentNode: this.selectedNode,
parentPath: this.parentPathCache
});
}
}
};
```
###### 2. 渲染树形结构
使用递归方式渲染树形结构,并绑定点击事件。
```vue
<template>
<view class="tree-picker">
<ul v-for="(node, index) in localdata" :key="index">
<li @click="updateSelection(node)">
{{ node[textKey] }}
</li>
<tree-item
v-if="node[childrenKey]"
:localdata="node[childrenKey]"
:value-key="valueKey"
:text-key="textKey"
:children-key="childrenKey"
@select-change="$emit('select-change', $event)"
/>
</ul>
</view>
</template>
<script>
export default {
name: "tree-item",
props: ["localdata", "valueKey", "textKey", "childrenKey"]
};
</script>
```
---
#### 样式定制
如果需要自定义样式,可以通过 `::v-deep` 或者覆盖默认类名的方式实现。例如:
```css
<style scoped>
.tree-picker ul {
list-style-type: none;
padding-left: 20px;
}
.tree-picker li {
cursor: pointer;
line-height: 30px;
}
/* 覆盖内部样式 */
.loginTree ::v-deep .item-label .uni-flex-item {
display: flex !important;
}
.loginTree ::v-deep .item-label .uni-flex-item .item-name {
line-height: 40px !important;
}
</style>
```
---
### 总结
以上实现了对 `ba-tree-picker` 插件的改造,使其能够在单选模式下返回选中值及其所有父级值。主要涉及以下几个方面:
1. 编写递归函数获取父级路径[^1]。
2. 封装单选逻辑并与 Vue3 的响应式系统集成[^2]。
3. 提供灵活的样式定制接口[^3]。
---
阅读全文
相关推荐



















