微信小程序 使用picker封裝省市區(qū)三級(jí)聯(lián)動(dòng)實(shí)例代碼
微信小程序 使用picker封裝省市區(qū)三級(jí)聯(lián)動(dòng)實(shí)例
目前學(xué)習(xí)小程序更多的是看看能否二次封裝其它組件,利于以后能快速開發(fā)各種小程序應(yīng)用。目前發(fā)現(xiàn)picker的selector模式只有一級(jí)下拉,那么我們是否可以通過(guò)3個(gè)picker來(lái)實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)模板的形式來(lái)引入其它頁(yè)面中呢?答案是肯定可以的。那么我的思路是這樣的:
1、使用template模板語(yǔ)法進(jìn)行封裝,數(shù)據(jù)從頁(yè)面?zhèn)魅?/strong>
2、根據(jù)picker組件的語(yǔ)法,range只能是一組中文地區(qū)數(shù)組,但是我們需要每個(gè)地區(qū)的唯一碼來(lái)觸發(fā)下一級(jí)聯(lián)動(dòng)數(shù)據(jù)。這樣,我的做法是通過(guò)一個(gè)對(duì)象里面的兩組數(shù)據(jù)分表存儲(chǔ)中文名和唯一碼的兩個(gè)對(duì)象數(shù)組。格式【province:{code:['110000', '220000'...], name: ['北京市', '天津市'...]}】,這個(gè)格式是固定的,需要服務(wù)端配合返回
3、通過(guò)picker的bindchange事件來(lái)獲取下一級(jí)的數(shù)據(jù),每個(gè)方法都寫入函數(shù)中在暴露出來(lái)供頁(yè)面調(diào)用
然后講下我demo的目錄結(jié)構(gòu):
common
-net.js//wx.request請(qǐng)求接口二次整合
-cityTemplate.js//三級(jí)聯(lián)動(dòng)方法
page
-demo
-demo.js
-demo.wxml
template
-cityTemplate.wxml
app.js
app.json
app.wxss
然后,使用phpstudy搭建了簡(jiǎn)單的服務(wù)端供測(cè)試。不要問(wèn)我服務(wù)端的為啥是這樣的,我也不懂,剛?cè)腴T我只要數(shù)據(jù)...
當(dāng)然你可以省掉這一步,將數(shù)據(jù)直接固定在demo.js里面進(jìn)行測(cè)試...
代碼如下:【服務(wù)端的返回?cái)?shù)據(jù)格式是遵循了下面的retArr的規(guī)范的】
<?php
header("Content-type: text/html; charset=utf-8");
$type=$_REQUEST["type"];//獲取省市區(qū)的標(biāo)志
$fcode=$_GET["fcode"];
$retArr=[
"status"=>true,
"data"=>[],
"msg"=>""
];
if($type!="province" && $type!="city" && $type!="county"){
$retArr["status"]=false;
$retArr["msg"]="獲取地區(qū)類型錯(cuò)誤,請(qǐng)檢查";
echo json_encode($retArr);
exit;
}
function getProvince(){
$province=[];
$code=["110000", "350000", "710000"];
$province["code"]=$code;
$name=["北京市", "福建省", "臺(tái)灣省"];
$province["name"]=$name;
$fcode=["0", "0", "0"];
$province["fcode"]=$fcode;
return $province;
}
function getCity($P_fcode){
$city=[];
$code=[];
$name=[];
$fcode=[];
if($P_fcode=="110000"){
$code=["110100"];
$name=["北京市"];
$fcode=$P_fcode;
}
if($P_fcode=="350000"){
$code=["350100", "350200", "350300", "350400", "350500", "350600", "350700", "350800", "350900"];
$name=["福州市", "廈門市", "莆田市", "三明市", "泉州市", "漳州市", "南平市", "龍巖市", "寧德市"];
$fcode=$P_fcode;
}
if($P_fcode=="710000"){
}
$city=["code"=>$code, "name"=>$name, "fcode"=>$fcode];
return $city;
}
function getCounty($P_fcode){
$county=[];
$code=[];
$name=[];
$fcode=[];
if($P_fcode=="110100"){
$code=["110101", "110102", "110103", "110104", "110105", "110106", "110107"];
$name=["東城區(qū)", "西城區(qū)", "崇文區(qū)", "宣武區(qū)", "朝陽(yáng)區(qū)", "豐臺(tái)區(qū)", "石景山區(qū)"];
$fcode=$P_fcode;
}
if($P_fcode=="350100"){
$code=["350102", "350103", "350104"];
$name=["鼓樓區(qū)", "臺(tái)江區(qū)", "蒼山區(qū)"];
$fcode=$P_fcode;
}
if($P_fcode=="350200"){
$code=["350203", "350205", "350206"];
$name=["思明區(qū)", "海滄區(qū)", "湖里區(qū)"];
$fcode=$P_fcode;
}
$county=["code"=>$code, "name"=>$name, "fcode"=>$fcode];
return $county;
}
//var_dump($province);
if($type=="province"){
$province=getProvince();
$retArr["data"]=$province;
}else if($type=="city"){
$city=getCity($fcode);
$retArr["data"]=$city;
}else if($type="county"){
$county=getCounty($fcode);
$retArr["data"]=$county;
}
echo json_encode($retArr);
?>
接下來(lái)是cityTemplate.wxml::
<template name="city">
<view class="areas">
<view class="province">
<picker bindchange="provincePickerChange" value="{{provinceIndex}}" range="{{province.name}}" data-city-url="{{cityUrl}}">
<text class="select-item">{{province.name[provinceIndex]}}</text>
</picker>
</view>
<view class="city">
<block wx:if="{{!city.name.length}}"> --二級(jí)市區(qū)-- </block>
<block wx:if="{{city.name.length>0}}">
<picker bindchange="cityPickerChange" value="{{cityIndex}}" range="{{city.name}}" data-county-url="{{countyUrl}}">
<text class="select-item">{{city.name[cityIndex]}}</text>
</picker>
</block>
</view>
<view class="county">
<block wx:if="{{!county.name.length}}"> --三級(jí)地區(qū)-- </block>
<block wx:if="{{county.name.length>0}}">
<picker bindchange="countyPickerChange" value="{{countyIndex}}" range="{{county.name}}">
<text class="select-item">{{county.name[countyIndex]}}</text>
</picker>
</block>
</view>
</view>
</template>
cityTemplate.js::
/**
* 獲取三級(jí)聯(lián)動(dòng)的三個(gè)函數(shù)
* that: 注冊(cè)頁(yè)面的this實(shí)例 必填
* p_url: 一級(jí)省份url 必填
* p_data:一級(jí)省份參數(shù) 選填
*/
var net = require( "net" );//引入request方法
var g_url, g_datd, g_cbSuccess, g_cbSuccessErr, g_cbFail, g_cbComplete, g_header, g_method;
function initCityFun( that, p_url, p_data ) {
//獲取一級(jí)省份數(shù)據(jù)
g_cbSuccess = function( res ) {
that.setData( {
'city.province': res
});
};
net.r( p_url, p_data, g_cbSuccess, g_cbSuccessErr, g_cbFail, g_cbComplete, g_header, g_method );
//點(diǎn)擊一級(jí)picker觸發(fā)事件并獲取市區(qū)方法
var changeProvince = function( e ) {
that.setData( {
'city.provinceIndex': e.detail.value
});
var _fcode = that.data.city.province.code[ e.detail.value ];
if( !_fcode ) {
_fcode = 0;
}
var _cityUrl = e.target.dataset.cityUrl;
g_url = _cityUrl + _fcode;
g_cbSuccess = function( res ) {
that.setData( {
'city.city': res
});
}
net.r( g_url, g_datd, g_cbSuccess, g_cbSuccessErr, g_cbFail, g_cbComplete, g_header, g_method );
};
that[ "provincePickerChange" ] = changeProvince;
//點(diǎn)擊二級(jí)picker觸發(fā)事件并獲取地區(qū)方法
var changeCity = function( e ) {
that.setData( {
'city.cityIndex': e.detail.value
});
var _fcode = that.data.city.city.code[ e.detail.value ];
if( !_fcode ) {
_fcode = 0;
}
var _countyUrl = e.target.dataset.countyUrl;
g_url = _countyUrl + _fcode;
g_cbSuccess = function( res ) {
that.setData( {
'city.county': res
});
};
net.r( g_url, g_datd, g_cbSuccess, g_cbSuccessErr, g_cbFail, g_cbComplete, g_header, g_method );
};
that[ "cityPickerChange" ] = changeCity;
//點(diǎn)擊三級(jí)picker觸發(fā)事件
var changeCounty = function( e ) {
that.setData( {
'city.countyIndex': e.detail.value
});
};
that["countyPickerChange"]=changeCounty;
}
function getProvinceFun(that, p_url, p_data){
g_cbSuccess = function( res ) {
that.setData( {
'city.province': res
});
};
net.r( p_url, p_data, g_cbSuccess, g_cbSuccessErr, g_cbFail, g_cbComplete, g_header, g_method );
}
module.exports={
initCityFun: initCityFun,
getProvinceFun: getProvinceFun
}
順道net.js方法::
/**
* 網(wǎng)絡(luò)發(fā)送http請(qǐng)求,默認(rèn)為返回類型為json
*
* url: 必須,其他參數(shù)非必須 接口地址
* data:請(qǐng)求的參數(shù) Object或String
* successFun(dts):成功返回的回調(diào)函數(shù),已自動(dòng)過(guò)濾微信端添加數(shù)據(jù),按接口約定,返回成功后的data數(shù)據(jù),過(guò)濾掉msg和status
* successErrorFun(msg):成功執(zhí)行請(qǐng)求,但是服務(wù)端認(rèn)為業(yè)務(wù)錯(cuò)誤,執(zhí)行其他行為,默認(rèn)彈出系統(tǒng)提示信息.
* failFun:接口調(diào)用失敗的回調(diào)函數(shù)
* completeFun:接口調(diào)用結(jié)束的回調(diào)函數(shù)(調(diào)用成功、失敗都會(huì)執(zhí)行)
* header:object,設(shè)置請(qǐng)求的 header , header 中不能設(shè)置 Referer
* method:默認(rèn)為 GET,有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
*
*/
function r( url, data, successFun, successErrorFun, failFun, completeFun, header, method ) {
var reqObj = {};
reqObj.url = url;
reqObj.data = data;
//默認(rèn)頭為json
reqObj.header = { 'Content-Type': 'application/json' };
if( header ) {
//覆蓋header
reqObj.header = header;
}
if( method ) {
reqObj.method = method;
}
reqObj.success = function( res ) {
var returnData = res.data; //將微信端結(jié)果過(guò)濾,獲取服務(wù)端返回的原樣數(shù)據(jù)
var status = returnData.status; //按接口約定,返回status時(shí),才調(diào)用成功函數(shù)
//console.log(res);
//正常執(zhí)行的業(yè)務(wù)函數(shù)
if( status == true ) {
if( successFun ) {
var dts = returnData.data;
successFun( dts );//回調(diào),相當(dāng)于獲取到data后直接在回調(diào)里面處理賦值數(shù)據(jù)
}
} else if( status == false ) {
var msg = returnData.msg;
if( !successErrorFun ) {
console.log( msg );
} else {
successErrorFun( msg );
}
} else {
console.log( "服務(wù)端沒(méi)有按照接口約定格式返回?cái)?shù)據(jù)" );
}
}
reqObj.fail = function( res ) {
if( failFun ) {
failFun( res );
}
}
reqObj.complete = function( res ) {
if( completeFun ) {
completeFun( res );
}
}
wx.request( reqObj );
}
module.exports = {
r: r
}
核心代碼就是上面這三個(gè)文件,接下來(lái)是demo文件做測(cè)試::
demo.wxml::
<import src="../../template/cityTemplate.wxml"/>
<template is="city" data="{{...city}}" />
demo.js::
var city = require( '../../common/cityTemplate' );
Page( {
data: {
},
onLoad: function( options ) {
var _that = this;
//創(chuàng)建三級(jí)聯(lián)動(dòng)數(shù)據(jù)對(duì)象 ---- 這個(gè)city對(duì)象是固定的,只有請(qǐng)求的url是根據(jù)各自的服務(wù)端地址來(lái)更改的
_that.setData( {
city: {
province: {},//格式province:{code: ["11000", "12000"], name: ["北京市", "上海市"]},只能固定是name和code,因?yàn)槟0逍枰鶕?jù)這倆參數(shù)顯示
city: {},
county: {},
provinceIndex: 0,
cityIndex: 0,
countyIndex: 0,
cityUrl: "http://localhost:8282/phpserver/areas.php?type=city&fcode=",//type表示獲取地區(qū) fcode是一級(jí)code碼,到時(shí)具體根據(jù)后端請(qǐng)求參數(shù)修改
countyUrl: "http://localhost:8282/phpserver/areas.php?type=county&fcode="
}
})
var _url = "http://localhost:8282/phpserver/areas.php";
var _data = { 'type': 'province', 'fcode': '0' };
city.initCityFun( _that, _url, _data );
}
})
以上完整代碼文件,最終測(cè)試如下:

這里存在一個(gè)bug,開啟下拉刷新和picker組件的下拉會(huì)重疊了,不知道是開發(fā)工具原因,還是還為修改的bug。。。只能等微信方面更新消息給反饋了
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
使用xml2js庫(kù)進(jìn)行XML數(shù)據(jù)解析
微信小程序 合法域名校驗(yàn)出錯(cuò)詳解及解決辦法
網(wǎng)頁(yè)里控制圖片大小的相關(guān)代碼
詳解微信小程序如何實(shí)現(xiàn)類似ChatGPT的流式傳輸
微信小程序 循環(huán)及嵌套循環(huán)的使用總結(jié)
JavaScript的模塊化開發(fā)框架Sea.js上手指南

