demand
Currently in the development of small programs, met a demand, need to choose a province/city/district, today write a simple solution
The solution
1. Try components
Currently, vant, the UI library, is used in the development of mini programs. Vant-appellate p itself provides the component ADDRESS, but the data structure returned by the interface of this project is as follows:
- To choose the province
- Then call the interface to get the city under the province
- Then call the interface to get the region under this city
However, van-address needs to use the data of all provinces and cities. Since adding an interface requires passing in the id of the province and city back, it is not practical to use the component directly.
2. Strike out on a different path
To build the skeleton
But Vant provides another component, the van-picker, which starts with the basic picker.
<van-picker column="{{data}}" />
Copy the code
According to the Vant documentation, column is the data for the entire picker, which is the structure you need if you want multiple selections
/ / a column
data: ['aa'.'bb'.'cc'].// Multiple columns, in order
data: [{values: ['1'.'2'.'3'] {},values: [1-1 ' '.'2'.'1-3'] {},values: ['1-1-1'.'1-1-2'.'1-1-3']}]Copy the code
Fill in the data
Now that you have a basic three-column selector, the next step is to populate the data
// These three data are returned by the cache interface
let _provinceList = []
let _cityList = []
let _districtList = []
// This data is used to determine whether picker's data exists
let __pickerDataInit__ = false
// These three data are used to get the index of the currently selected province
let __selectProvinceId__ = 0
let __selectCityId__ = 0
let __selectDistrictId__ = 0
/ / get province
getProvince() {
// Interface interaction
Res. data is the data returned by the interface
// Cache a copy first, because the data returned by the interface is different from the data required by van-picker
{id=xx, name='xx'}
_provinceList = res.data
// Get the reasonable data, put it directly into data, the first column is province
this.setData({
"data[0].values": _parse2VanPickerData(res.data)
})
__pikcerDataInit__ = true
}
/ / for the city
getCity(provinceId) {
// The interface needs provinceId to get cities
Res. data is the data returned by the interface
// Cache a copy
_cityList = res.data
this.setData({
"data[1].values": _parse2VanPickerData(res.data)
})
// The market can be retrieved directly from the market, since the market can be retrieved simultaneously from the market
this.getDistrict(_districtList(__selectDistrictId__))
}
/ / access area
getDistrict(cityId) {
// The interface needs to use provinceId to fetch a districts
Res. data is the data returned by the interface
_districtList = res.data
this.setData({
"data[2].values": _parse2VanPickerData(res.data)
})
}
// Open popUp for the selected province
showPopup() {
this.setData({
popUpShow: true
})
// Get data
this.getProvince()
if(! __pickerDataInit__){// No data available yet
// We want to initialize the data to display the first district of the first city of the first province
this.getProvince()
this.getCity(_cityList[__selectCityId__].id))
}
}
function _parse2VanPickerData(arr) {
let res = []
arr.forEach(item= > {
res.push(item)
})
return res
}
Copy the code
Switch options
Next, is the most critical, switch when the three linkage
<! -- bind:change van-picker -->
<van-picker id="picker" column="{{pickerColumnData}}" bind:change="onPickerChange" />
Copy the code
Index is the next table to which the column is currently switched. For example, if you slide the first column, it is 0, and the second column, it is 1
// Get the picker instance through selectComponent. There is a method getIndexs that gets all the subscripts for the three groups
onPickerChange(e) {
// Get the current subscript s
const currentIndexs = this.selectComponent('#picker').getIndexes()
// Determine which of the three slides is used
switch (e.detail.index) {
case 0:
// If it is the first one, we get the id of the province and the cities under the province
const provinceId = PROVINCE_LIST[currentIndexs[0]].id
__selectProvinceIndex__ = currentIndexs[0]
this.getCityList(provinceId)
case 1:
// If you slide the city, get the region under the city
const cityId = CITY_LIST[currentIndexs[1]].id
this.getDistrictList(cityId)
__selectCityIndex__ = currentIndexs[1]}}Copy the code
Complete choice
onPickerConfirm() {
// The selection is complete
const currentIndexs = this.selectComponent('#picker').getIndexes()
// Get the name and ID of the selected province
const province = PROVINCE_LIST[currentIndexs[0]]
const city = CITY_LIST[currentIndexs[1]]
const district = DISTRICT_LIST[currentIndexs[2]]
this.setData({
// The provincial id is passed to the backend when it needs to be added
addProvinceId: province.id,
addCityId: city.id,
addDistrictId: district.id,
// This is the front display, only show the name of the province, put together
addFormAreaValue: province.name + city.name + district.name,
// defaultIndex: the index selected by province by default
// The main effect of this is: if you press the wrong button, come back to the same place you just selected
"data[0].defaultIndex": currentIndexs[0]."data[1].defaultIndex": currentIndexs[1]."data[2].defaultIndex": currentIndexs[2].// Finally close popup
popupShow: false})},Copy the code
At this point, the process is probably over
The final result
To optimize the
1. loading
<! -- Van-picker has a property loading that can be loaded on request -->
<van-picker loading="{{pickerLoading}}"></van-picker>
Copy the code
2. Initialize global variables
Remember to initialize global variables in onUnload
onUnload() {
let _provinceList = []
let _cityList = []
let _districtList = []
let __pickerDataInit__ = false
let __selectProvinceId__ = 0
let __selectCityId__ = 0
let __selectDistrictId__ = 0
}
Copy the code