效果如下:
因项目需求,需要做一个省市区街的四级联动,项目用的组件为taro的picker,奈何移动端与pc端共用一个接口,返回的数据并不是picker想要的数据结构(省级只有湖北省,有些区域下面无街道),因此基于picker再次封装
代码如下:
import { Picker, View } from '@tarojs/components'
import { useRefState } from 'hook-stash'
import React, { useEffect } from 'react'
import { useHttp } from 'hook-stash'
import styles from './index.module.scss'
interface stateDo {
value: number[],
ranges: string[][],
newList: any
}
export default function index(props) {
const { url, onChange } = props
const [list] = useHttp(url, { auto: true })
const [state, setState] = useRefState<stateDo>({
value: [0, 0, 0, 0],
ranges: [[], [], []],
newList: {}
})
const handlePickerShow = (e) => {
setState({
value: e.detail.value
})
}
const columnChange = (e) => {
let newVal = state.value
newVal[e.detail.column] = e.detail.value
let ranges = [
[state.newList?.districtName],
traversal(state.newList),
traversal(state.newList.children[newVal[1]]),
// 判断区角标为0
state.newList.children[newVal[1]].districtCode !== '0' ? traversal(state.newList.children[newVal[1]].children[newVal[2]]) : ['不详']
]
// 过滤code
let codes = [
state.newList?.districtCode,
traversalCode(state.newList)[newVal[1]],
traversalCode(state.newList.children[newVal[1]])[newVal[2]],
state.newList.children[newVal[1]].districtCode !== '0' ? traversalCode(state.newList.children[newVal[1]].children[newVal[2]])[newVal[3]] : "0"
].filter(el => el !== '0')
setState({ ranges: ranges, value: newVal })
onChange(codes[codes.length - 1])
}
// 转换districtName
const traversal = (arr: any[] | any) => {
if (!!arr?.children) {
return arr?.children.map(el => el.districtName)
} else {
if (arr?.districtCode === "0") {
return ['不详']
} else {
return [arr?.districtName]
}
}
}
// 转换districtCode
const traversalCode = (arr: any[] | any) => {
if (!!arr?.children) {
return arr?.children.map(el => el.districtCode)
} else {
return [arr?.districtCode]
}
}
// 初始化多列数据
const cityChange = () => {
const newList = dataChange(list)
let ranges = [[newList?.districtName],
traversal(newList),
]
if (!!newList) {
setState({
ranges: ranges,
newList: newList
})
let codes = [newList?.districtCode]
onChange(codes[codes.length - 1])
}
return ranges
}
// 递归初始化树形数据
const dataChange = (list) => {
if (list?.children) {
const option = { districtCode: "0", districtName: "不详" }
list.children.unshift(option)
list.children.map(el => {
dataChange(el)
})
}
return list
}
useEffect(() => {
cityChange()
}, [list])
return (
<View className={styles.manageBox}>
<Picker mode='multiSelector' value={state.value} range={state.ranges} onChange={handlePickerShow} onColumnChange={columnChange} >
<View>
{state.ranges &&
<View>
{state.ranges[state.value[0]]}
{state.value[1] !== 0 && state.ranges[1][state.value[1]]}
{state.value[2] !== 0 && state.ranges[2][state.value[2]]}
{state.value[3] !== 0 && state.ranges[3][state.value[3]]}
</View>
}
</View>
</Picker>
</View>
)
}