微信小程序?qū)崿F(xiàn)省市區(qū)三級(jí)地址選擇
國(guó)際慣例先上效果圖:
省市區(qū)三級(jí)聯(lián)動(dòng),選擇省自動(dòng)刷新市,選擇市自動(dòng)刷新區(qū),點(diǎn)擊取消自動(dòng)返回上一級(jí)重新選擇,點(diǎn)擊確定,保存地址。



數(shù)據(jù)庫(kù)
這份數(shù)據(jù)庫(kù)是某天在網(wǎng)上逛到的,當(dāng)時(shí)未記錄出處,直接貼出給讀者使用,實(shí)在不妥,此處僅貼出表結(jié)構(gòu),方便大家交流學(xué)習(xí)。如有讀者了解此份數(shù)據(jù)出處,煩請(qǐng)留言,謝謝!
數(shù)據(jù)表結(jié)構(gòu)如下:

部分使用到的字段信息:
id:唯一標(biāo)識(shí)每一個(gè)數(shù)據(jù)
name:地區(qū)名
parent_id:上級(jí)地區(qū)的id,若parent_id = 0 ,表示無(wú)上級(jí)信息,當(dāng)前即為最高行政區(qū)。
extra:主要標(biāo)識(shí)少數(shù)民族自治州或者自治縣的信息,如:巴音郭楞 蒙古 自治州,此處存儲(chǔ) 蒙古
例:

suffix:行政級(jí)別 市 省 縣 區(qū)等
部分地區(qū)數(shù)據(jù)信息如下:

后臺(tái)
后臺(tái)僅需提供一個(gè)接口,根據(jù)parent_id,查詢地區(qū)信息
此處使用的后臺(tái)是SSM框架,貼出主要接口、sql
1.與小程序交互接口
@RequestMapping(value = "/getArea", method = RequestMethod.POST)
private @ResponseBody
List<District> getArea(HttpServletRequest request) {
int parentId = Integer.parseInt(request.getParameter("parentId"));
logger.info("getArea");
List<District> list = new ArrayList<District>();
try {
list = districtService.getAreas(parentId);
} catch (Exception e) {
}
return list;
}
2.查詢sql
<select id="getAreas" resultType="District">
<!-- 具體的sql -->
SELECT
id,concat(name,extra,suffix) as name,parent_id as parentId
FROM
district
WHERE
parent_id = #{parentId}
</select>
前端
先貼出css:
.hotCity {
padding-right: 50rpx;
margin: auto;
}
.weui-grid {
padding: 10rpx 0;
width: 160rpx;
box-sizing: border-box;
border: 1rpx solid #ececec;
border-radius: 8rpx;
background-color: white;
margin: 8rpx 0;
}
.weui-grids {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.weui-grid__label {
display: block;
text-align: center;
color: #333;
font-size: 30rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.county {
display: flex;
flex-wrap: wrap;
margin-top: 30px;
margin-left: 15px;
}
/** 頭部css **/
.headTitle{
display: flex;
}
.headButton{
background: #f68135;
border-radius: 25rpx;
border: 1px solid #f68135;
color: #fff;
height: 80rpx;
line-height: 80rpx;
margin: 0 auto;
width: 150rpx;
font-size: 45rpx;
text-align: center;
padding:0px;
vertical-align:middle ;
}
html
html僅由兩部分組成:
頭部:確定、取消按鈕,顯示當(dāng)前選擇地址信息
確定取消主要綁定了兩個(gè)方法:submitChoose 及 cancleChoose 兩個(gè)方法,點(diǎn)擊不同按鈕,執(zhí)行不同js方法。
顯示當(dāng)前地址信息:finalCity,只要在js中使用setData設(shè)置該值,該值就會(huì)動(dòng)態(tài)改變。
city:顯示當(dāng)前可選的地區(qū)
使用block組件,對(duì)json數(shù)組areaList進(jìn)行循環(huán)顯示,同樣,使用setData設(shè)置該值,該值就會(huì)動(dòng)態(tài)改變,達(dá)到省市區(qū)聯(lián)動(dòng)選擇的效果。每一個(gè)小地區(qū)控件,有bindArea方法,并且在用戶選擇該地區(qū),執(zhí)行bindArea方法時(shí),使用data-數(shù)據(jù)名的方法,向后臺(tái)傳遞用戶選擇數(shù)據(jù)。
<view class="headTitle">
<button class="headButton" bindtap="cancleChoose">取消</button>
<view>{{finalCity == "" ? "請(qǐng)選擇地址" : finalCity}}</view>
<button class="headButton" bindtap="submitChoose">確定</button>
</view>
<view class="county">
<block class="hotCity" wx:for-items="{{areaList}}" wx:key="id">
<view class="weui-grid" style="margin-right: 16rpx;" data-parentId="{{item.parentId}}" data-id="{{item.id}}" data-city="{{item.name}}" bindtap="bindArea">
<view class="weui-grid__label">{{item.name}}</view>
</view>
</block>
</view>
js:
// pages/chooseCity/chooseCity.js
//獲取應(yīng)用實(shí)例
const model = require('../cityChoose/cityChoose.js')
const config = require('../../utils/config.js')
const util = require('../../utils/util.js')
const app = getApp();
//記錄省市區(qū)
var nav = 0;
var chooseCity = new Array(3);
//記錄每一次的parentId
var finalParentId = new Array(3);
var flag = 0;
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
finalCity:"",
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面加載
*/
onLoad: function(options) {
//parentId = 0 取所有省份數(shù)據(jù)
var that = this;
that.getData(0);
chooseCity = new Array("","","");
finalParentId = new Array(0,0,0);
nav = 0;
},
submitChoose:function(e){
if(flag != 1){
util.showLog("請(qǐng)選擇完整地址")
return;
}else{
var address_components = { "province": "", "city": "", "district": ""};
address_components["province"] = chooseCity[0];
address_components["city"] = chooseCity[1];
address_components["district"] = chooseCity[2];
console.log(address_components);
app.globalData.address_components = address_components;
wx.navigateBack();
}
},
cancleChoose:function(e){
console.log(finalParentId);
var that = this;
if(nav == 0){
wx.navigateBack();
} else {
nav = nav - 1;
chooseCity[nav] = "";
console.log(chooseCity);
that.setData({
finalCity: chooseCity[0] + chooseCity[1] + chooseCity[2]
})
that.getData(finalParentId[nav]);
}
},
bindArea: function(e) {
if(flag == 0){
console.log(e);
var that = this;
var parentId = e.currentTarget.dataset.id;
var city = e.currentTarget.dataset.city;
that.getData(parentId);
chooseCity[nav] = city;
finalParentId[nav] = e.currentTarget.dataset.parentid;
nav++;
console.log(chooseCity)
that.setData({
finalCity:chooseCity[0]+chooseCity[1]+chooseCity[2]
})
}
},
getData(parentId) {
var that = this;
var url = config.getArea + "?parentId=" + parentId;
wx.request({
url: url,
success: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求成功");
console.log(res)
if (res.data.length != 0) {
flag = 0;
//設(shè)置數(shù)據(jù)到全局變量
that.setData({
areaList: res.data,
});
}else{
//防止用戶再次點(diǎn)擊;
flag = 1;
}
},
method: "POST",
header: {
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
},
fail: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求失敗");
}
})
},
})
js解析
全局變量作用:
//記錄用戶已選擇層次
var nav = 0;
//記錄省市區(qū)三級(jí)數(shù)據(jù)
var chooseCity = new Array(3);
//記錄每一次的parentId,主要記錄用戶選擇路徑,取消時(shí)根據(jù)用戶路徑顯示上一級(jí)數(shù)據(jù)
var finalParentId = new Array(3);
//記錄是否已經(jīng)到最底層,再無(wú)數(shù)據(jù)可以選擇
var flag = 0;
執(zhí)行過程:
進(jìn)入頁(yè)面執(zhí)行onLoad生命周期函數(shù),在onLoad中調(diào)用getData初始化數(shù)據(jù),及默認(rèn)顯示行政級(jí)別為省的數(shù)據(jù),即請(qǐng)求parent_id為0的數(shù)據(jù)
getData:
getData(parentId) {
var that = this;
//請(qǐng)求的url,由后臺(tái)決定,此處填入你的請(qǐng)求url即可
var url = config.getArea + "?parentId=" + parentId;
wx.request({
url: url,
success: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求成功");
console.log(res)
if (res.data.length != 0) {
flag = 0;
//設(shè)置數(shù)據(jù)到全局變量
that.setData({
areaList: res.data,
});
}else{
//已到最后一層數(shù)據(jù)
flag = 1;
}
},
method: "POST",
header: {
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
},
fail: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求失敗");
}
})
},
點(diǎn)擊地區(qū)數(shù)據(jù)執(zhí)行bindArea
bindArea: function(e) {
//如果未到最后一層,即可向下執(zhí)行
if(flag == 0){
console.log(e);
var that = this;
//獲取html傳參,獲取用戶點(diǎn)擊信息
var parentId = e.currentTarget.dataset.id;
var city = e.currentTarget.dataset.city;
//根據(jù)用戶點(diǎn)擊的數(shù)據(jù),傳入當(dāng)前的id作為下一層的parentId,請(qǐng)求下一層數(shù)據(jù),
that.getData(parentId);
//記錄用戶選擇
chooseCity[nav] = city;
//用戶點(diǎn)擊取消,到此層時(shí),需要使用當(dāng)前的parientid來(lái)請(qǐng)求此層應(yīng)顯示的數(shù)據(jù)
finalParentId[nav] = e.currentTarget.dataset.parentid;
//記錄路徑數(shù)+1
nav++;
console.log(chooseCity)
//更新用戶選擇地區(qū)顯示
that.setData({
finalCity:chooseCity[0]+chooseCity[1]+chooseCity[2]
})
}
},
點(diǎn)擊取消,執(zhí)行方法cancleChoose
cancleChoose:function(e){
var that = this;
//已是最后一層,則返回上一頁(yè)
if(nav == 0){
wx.navigateBack();
} else {
//記錄路徑數(shù)-1
nav = nav - 1;
//將上次已選擇的地區(qū)清空
chooseCity[nav] = "";
console.log(chooseCity);
//更新選擇數(shù)據(jù)
that.setData({
finalCity: chooseCity[0] + chooseCity[1] + chooseCity[2]
})
//根據(jù)finalParent中記錄的每一層應(yīng)請(qǐng)求的數(shù)據(jù)來(lái)更新地區(qū)數(shù)據(jù)
that.getData(finalParentId[nav]);
}
},
點(diǎn)擊確定,執(zhí)行方法submitChoose
submitChoose:function(e){
//如果未到最后一層,表示地址未選擇完,如果不需要選擇完整地址,此處去掉即可
if(flag != 1){
util.showLog("請(qǐng)選擇完整地址")
return;
}else{
//存儲(chǔ)數(shù)據(jù)到全局變量中,采用了json的方式存儲(chǔ),可以分別存儲(chǔ)省市區(qū)數(shù)據(jù)
var address_components = { "province": "", "city": "", "district": ""};
address_components["province"] = chooseCity[0];
address_components["city"] = chooseCity[1];
address_components["district"] = chooseCity[2];
console.log(address_components);
app.globalData.address_components = address_components;
//返回上一次頁(yè)面
wx.navigateBack();
}
},
謝謝大家查看,評(píng)論里希望貼出cityChoose.js 及 util.js ,在下面貼出來(lái)啦,注:util.js里不是所有方法都要用到。
希望能夠幫助到大家。
cityChoose
// pages/chooseCity/chooseCity.js
//獲取應(yīng)用實(shí)例
const model = require('../cityChoose/cityChoose.js')
const config = require('../../utils/config.js')
const util = require('../../utils/util.js')
const app = getApp();
//記錄省市區(qū)
var nav = 0;
var chooseCity = new Array(3);
//記錄每一次的parentId
var finalParentId = new Array(3);
//記錄是否到最后一級(jí)
var flag = 0;
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
finalCity:"",
},
/**
* 生命周期函數(shù)--監(jiān)聽頁(yè)面加載
*/
onLoad: function(options) {
//parentId = 0 取所有省份數(shù)據(jù)
var that = this;
that.getData(0);
chooseCity = new Array("","","");
finalParentId = new Array(0,0,0);
nav = 0;
},
submitChoose:function(e){
if(flag != 1){
util.showLog("請(qǐng)選擇完整地址")
return;
}else{
var address_components = { "province": "", "city": "", "district": ""};
address_components["province"] = chooseCity[0];
address_components["city"] = chooseCity[1];
address_components["district"] = chooseCity[2];
console.log(address_components);
app.globalData.address_components = address_components;
wx.navigateBack();
}
},
cancleChoose:function(e){
console.log(finalParentId);
var that = this;
if(nav == 0){
wx.navigateBack();
} else {
nav = nav - 1;
chooseCity[nav] = "";
console.log(chooseCity);
that.setData({
finalCity: chooseCity[0] + chooseCity[1] + chooseCity[2]
})
that.getData(finalParentId[nav]);
}
},
bindArea: function(e) {
if(flag == 0){
console.log(e);
var that = this;
var parentId = e.currentTarget.dataset.id;
var city = e.currentTarget.dataset.city;
//刷新出下一級(jí)地址前重復(fù)點(diǎn)擊
console.log(chooseCity[nav - 1] );
console.log(city);
if(chooseCity[nav-1] == city){
return;
}
that.getData(parentId);
chooseCity[nav] = city;
finalParentId[nav] = e.currentTarget.dataset.parentid;
nav++;
console.log(chooseCity)
that.setData({
finalCity:chooseCity[0]+chooseCity[1]+chooseCity[2]
})
}
},
getData(parentId) {
var that = this;
var url = config.getArea + "?parentId=" + parentId;
wx.request({
url: url,
success: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求成功");
console.log(res)
if (res.data.length != 0) {
flag = 0;
//設(shè)置數(shù)據(jù)到全局變量
that.setData({
areaList: res.data,
});
}else{
//防止用戶再次點(diǎn)擊;
flag = 1;
}
},
method: "POST",
header: {
"content-type": "application/x-www-form-urlencoded;charset=utf-8",
},
fail: (res) => {
console.log("地區(qū)數(shù)據(jù)請(qǐng)求失敗");
}
})
},
})
util.js
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
function showLog(e) {
wx.showToast({
title: e,
icon: "none"
})
}
function trim(str) {
return str.replace(/(^\s*)|(\s*$)/g, "");
}
function showLoading() {
wx.showLoading({
title: '加載中',
mask: true
})
}
// 驗(yàn)證碼倒計(jì)時(shí)
function phone_code(t, second) {
// t是this,second是重新發(fā)送的間隔時(shí)間,需要設(shè)置按鈕可點(diǎn)擊
var s = second;
// 避免重復(fù)點(diǎn)擊
t.setData({
phone_code_text: s + "s",
phone_code_class: "",
phone_code_buff: true
});
// 倒計(jì)時(shí)
var clock = setInterval(function () {
if (s > 1) {
t.setData({
phone_code_text: --s + "s"
})
} else {
clearInterval(clock);
t.setData({
phone_code_text: "重新發(fā)送",
phone_code_class: "on",
phone_code_buff: false
});
// 重置數(shù)據(jù)
s = second;
}
}, 1000)
}
function getNowFormatDate() {
var date = new Date();
var seperator1 = "-";
var year = date.getFullYear();
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = year + seperator1 + month + seperator1 + strDate;
return currentdate;
}
function checkAndCall(sourceId,recordType,tele,app,config){
console.log(app.globalData.haulUserInfo)
console.log(tele);
if (app.globalData.haulUserInfo == null) {
showLog("正在獲取用戶數(shù)據(jù),請(qǐng)稍后。")
app.Promise.then(function (value) {
console.log(value);
if (value) {
// success
wx.makePhoneCall({
phoneNumber: tele,
success: ph => {
mycall(config, app,recordType, sourceId, function () {
//記錄聯(lián)系次數(shù)
})
}
})
} else {
// failure
showLog("注冊(cè)完成即可聯(lián)系" + "。。。即將跳轉(zhuǎn)")
setTimeout(function () {
wx.navigateTo({
url: '../registUser/registUser',
})
}, 1000);
}
}).catch(function (error) {
});
} else {
// success
wx.makePhoneCall({
phoneNumber: tele,
success: ph => {
mycall(config,app, recordType, sourceId,function () {
//記錄聯(lián)系次數(shù)
})
}
})
}
}
//記錄互相聯(lián)系
function mycall(config,app, recordType, sourceId, callback) {
console.log(typeof (recordType))
var that = this;
wx.request({
url: config.insertRecord,
method: "POST",
data: {
sourceId: sourceId,
userId: app.globalData.haulUserInfo.id,
recordType: recordType
},
header: {
"content-type": "application/x-www-form-urlencoded",
},
success: res => {
if (res.data.success) {
console.log('聯(lián)系成功');
callback();
} else {
showLog(res.data.error);
}
}
})
}
module.exports = {
formatNumber: formatNumber,
formatTime: formatTime,
phone_code_clock: phone_code,
showLoading: showLoading,
showLog: showLog,
getNowFormatDate: getNowFormatDate,
trim: trim,
mycall: mycall,
checkAndCall: checkAndCall
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 微信小程序如何獲取用戶收貨地址
- 微信小程序三級(jí)聯(lián)動(dòng)地址選擇器的實(shí)例代碼
- 微信小程序?qū)崿F(xiàn)獲取準(zhǔn)確的騰訊定位地址功能示例
- 微信小程序?qū)崿F(xiàn)選擇地址省市區(qū)三級(jí)聯(lián)動(dòng)
- 微信小程序 (地址選擇1)--選取搜索地點(diǎn)并顯示效果
- 微信小程序開發(fā)實(shí)現(xiàn)的IP地址查詢功能示例
- 微信小程序 可搜索的地址選擇實(shí)現(xiàn)詳解
- 微信小程序在地圖選擇地址并返回經(jīng)緯度簡(jiǎn)單示例
- 微信小程序 ecshop地址三級(jí)聯(lián)動(dòng)實(shí)現(xiàn)實(shí)例代碼
- 微信小程序自定義地址組件
相關(guān)文章
JS前端組件設(shè)計(jì)以業(yè)務(wù)為導(dǎo)向?qū)嵺`思考
這篇文章主要為大家介紹了JS前端組件設(shè)計(jì)以業(yè)務(wù)為導(dǎo)向?qū)嵺`思考,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
BootstrapTable與KnockoutJS相結(jié)合實(shí)現(xiàn)增刪改查功能【二】
這篇文章主要介紹了BootstrapTable與KnockoutJS相結(jié)合實(shí)現(xiàn)增刪改查功能【二】的相關(guān)資料,非常具有參考價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-05-05
JS關(guān)鍵字球狀旋轉(zhuǎn)效果的實(shí)例代碼
這篇文章主要介紹了JS關(guān)鍵字球狀旋轉(zhuǎn)效果的實(shí)例代碼。需要的朋友可以過來(lái)參考下,希望對(duì)大家有所幫助2013-11-11
可以測(cè)試javascript運(yùn)行效果的代碼
這篇文章主要介紹了如何在頁(yè)面中可以簡(jiǎn)單的測(cè)試一些簡(jiǎn)單的JavaScript語(yǔ)句,需要的朋友可以參考下2010-04-04
JavaScript定時(shí)器實(shí)現(xiàn)無(wú)縫滾動(dòng)圖片
這篇文章主要為大家詳細(xì)介紹了JavaScript定時(shí)器實(shí)現(xiàn)無(wú)縫滾動(dòng)圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
原生JS實(shí)現(xiàn)首頁(yè)進(jìn)度加載動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)首頁(yè)進(jìn)度加載動(dòng)畫,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09

