要求:使用van组件的indexBar索引栏实现地区的联动效果。
效果:
思路:
1.修改vant组件的indexBar变成规定样式;
2.将组件写成循环现实,并添加点击事件;
3.点击地区确定方法;
4.点击顶部方法;
5.点击列表方法;
6.字母排序方法;
相关代码实现:
1. 样式框架
<!-- 地区弹出层 -->
<div class="map-popup">
<van-action-sheet v-model="showPicker" title="请选择查看区域">
<ul class="address-box">
<li>
<span :class="{'address-active': address.city=='请选择'}" @click="handleTopToAddress('city',0, address.city)">{{ address.city }}</span>
<span :class="{'address-active': address.district=='请选择'}" @click="handleTopToAddress('district',1, address.district)">{{ address.district }}</span>
<span :class="{'address-active': address.town=='请选择'}" @click="handleTopToAddress('town',2, address.town)">{{ address.town }}</span>
<span :class="{'address-active': address.village=='请选择'}" @click="handleTopToAddress('village',3, address.village)">{{ address.village }}</span>
</li>
<li>
<van-button @click="handleSubmit">确定</van-button>
</li>
</ul>
<van-index-bar highlight-color="#3378E0" :sticky="false" :index-list="indexList" >
<div v-for="(item,index) in addressData" :key="index">
<van-index-anchor :index="item.letter"></van-index-anchor>
<van-cell v-for="(ite,index) in item.data" :key="index" :title="ite.name" @click="handleListToAddress(addressIndex+1,ite.name)"></van-cell>
</div>
</van-index-bar>
</van-action-sheet>
</div>
2.点击弹出该地区选择框
// 点击地区弹出
handleToAddressShow() {
this.showPicker = true;
const addressKeyArr = ['city', 'district', 'town', 'village'];
let addressArr = [];
addressArr = Object.values(this.address);
let _index = addressArr.findIndex(item => item == '');
let _ind = !!_index && _index != -1 ? _index - 1 : 3;
if (addressKeyArr[_ind]) {
this.handleToAddress(addressKeyArr[_ind], _ind + 1, addressArr[_ind], this.currData);
}
},
3. 点击地区确定
// 地区确定
handleSubmit() {
this.addressValue = '';
for (let key in this.address) {
if (this.address[key] == '请选择') {
this.address[key] = '';
} else if (this.address[key]) {
this.addressValue = this.address[key];
}
}
this.showPicker = false;
},
4.点击顶部地区
// 点击顶部地区
handleTopToAddress(key, index, name) {
var data = this.getCurChild(name);
if (key == 'city') {
this.address = {
city:name,
district:'',
town:'',
village:''
}
} else if (key == 'district') {
this.address.town = '';
this.address.village = '';
} else if (key == 'town') {
this.address.village = '';
}
this.handleToAddress(key, index + 1, data);
},
5.点击列表地区
// 点击底部地区
handleListToAddress(index, name) {
var data = this.getCurChild(name);
var addressKey = this.addressKeyArr[index-1];
this.address[addressKey] = name;
if (addressKey == 'city') {
this.address.district = this.address.district ? this.address.district : '请选择';
} else if (addressKey == 'district') {
this.address.town = this.address.town ? this.address.town : '请选择';
} else if (addressKey == 'town') {
this.address.village = this.address.village ? this.address.village : '请选择';
}
this.handleToAddress(addressKey, index, data);
},
6.获取下一级的数据回调显示
// 获取下一级的数据回调显示
getCurChild(name) {
var _data = [];
var _land = this.land;
var getCurChildList = function (data) {
data.forEach(function (item) {
if (item.children) {
if (item.name === name) {
_data = item.children;
} else {
getCurChildList(item.children);
}
}
});
};
getCurChildList(_land.children);
return _data;
},
7.公共方法:根据data来显示列表数据
// 公共方法:根据data来显示列表数据
handleToAddress(key, index, data) {
this.addressIndex = index;
this.addressData = [];
this.currData = [];
if (data && data.length > 0) {
this.addressData = this.initAddress(data);
this.currData = data;
}
if (key == 'city') {
this.addressData = this.initAddress(this.land.children);
}
},
8.根据首字母排序
initAddress(arr) {
if (!String.prototype.localeCompare) return null;
var letters = '*ABCDEFGHJKLMNOPQRSTWXYZ'.split('');
var zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('');
var segs = [];
var curr;
letters.forEach(function (item, i) {
curr = {
letter: item,
data: [],
};
arr.forEach(function (item2) {
if ((!zh[i - 1] || zh[i - 1].localeCompare(item2.name) <= 0) && item2.name.localeCompare(zh[i]) == -1) {
curr.data.push(item2);
}
});
if (curr.data.length) {
segs.push(curr);
curr.data.sort(function (a, b) {
return a.name.localeCompare(b.name);
});
}
});
this.indexList = [];
segs.forEach(v => {
this.indexList.push(v.letter);
});
return segs;
},