目前学习小程序更多的是看看能否二次封装其它组件,利于以后能快速开发各种小程序应用。目前发现picker的selector模式只有一级下拉,那么我们是否可以通过3个picker来实现三级联动模板的形式来引入其它页面中呢?答案是肯定可以的。那么我的思路是这样的:
1、使用template模板语法进行封装,数据从页面传入
2、根据picker组件的语法,range只能是一组中文地区数组,但是我们需要每个地区的唯一码来触发下一级联动数据。这样,我的做法是通过一个对象里面的两组数据分表存储中文名和唯一码的两个对象数组。格式【province:{code:['110000', '220000'...], name: ['北京市', '天津市'...]}】,这个格式是固定的,需要服务端配合返回
3、通过picker的bindchange事件来获取下一级的数据,每个方法都写入函数中在暴露出来供页面调用
然后讲下我demo的目录结构:
common
-net.js//wx.request请求接口二次整合
-cityTemplate.js//三级联动方法
page
-demo
-demo.js
-demo.wxml
template
-cityTemplate.wxml
app.js
app.json
app.wxss
然后,使用phpstudy搭建了简单的服务端供测试。不要问我服务端的为啥是这样的,我也不懂,刚入门我只要数据...
当然你可以省掉这一步,将数据直接固定在demo.js里面进行测试...
代码如下:【服务端的返回数据格式是遵循了下面的retArr的规范的】
- <?php
- header("Content-type: text/html; charset=utf-8");
- $type=$_REQUEST["type"];//获取省市区的标志
- $fcode=$_GET["fcode"];
- $retArr=[
- "status"=>true,
- "data"=>[],
- "msg"=>""
- ];
- if($type!="province" && $type!="city" && $type!="county"){
- $retArr["status"]=false;
- $retArr["msg"]="获取地区类型错误,请检查";
- echo json_encode($retArr);
- exit;
- }
- function getProvince(){
- $province=[];
- $code=["110000", "350000", "710000"];
- $province["code"]=$code;
- $name=["北京市", "福建省", "台湾省"];
- $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=["东城区", "西城区", "崇文区", "宣武区", "朝阳区", "丰台区", "石景山区"];
- $fcode=$P_fcode;
- }
- if($P_fcode=="350100"){
- $code=["350102", "350103", "350104"];
- $name=["鼓楼区", "台江区", "苍山区"];
- $fcode=$P_fcode;
- }
- if($P_fcode=="350200"){
- $code=["350203", "350205", "350206"];
- $name=["思明区", "海沧区", "湖里区"];
- $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);
- ?>
接下来是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}}"> --二级市区-- </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}}"> --三级地区-- </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
- /**
- * 获取三级联动的三个函数
- * that: 注册页面的this实例 必填
- * p_url: 一级省份url 必填
- * p_data:一级省份参数 选填
- */
- 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 ) {
- //获取一级省份数据
- console.log(p_url+JSON.stringify(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 );
- //点击一级picker触发事件并获取市区方法
- var changeProvince = function( e ) {
- that.setData( {
- 'city.city': {},
- 'city.county': {},
- 'city.provinceIndex': e.detail.value,
- 'city.cityIndex': 0,
- 'city.countyIndex': 0
- });
- var _fcode = that.data.city.province.code[ e.detail.value ];
- if( !_fcode ) {
- _fcode = 0;
- }
- var _cityUrl = e.target.dataset.cityUrl;
- g_url = _cityUrl + _fcode;
- console.log("province:"+g_url);
- g_cbSuccess = function( res ) {
- console.log(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;
- //点击二级picker触发事件并获取地区方法
- var changeCity = function( e ) {
- that.setData( {
- 'city.county': {},
- 'city.cityIndex': e.detail.value,
- 'city.countyIndex': 0
- });
- 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;
- //点击三级picker触发事件
- 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
- }
- <style type="text/css">
- p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Times; color: #999999; -webkit-text-stroke: #999999}
- span.s1 {font-kerning: none}
- </style>
- <p class="p1"><span class="s1"><font color="#000000">顺道net.js方法:</font></span></p><p class="p1"><span class="s1">
- </span></p>
核心代码就是上面这三个文件,接下来是demo文件做测试:
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;
- //创建三级联动数据对象 ---- 这个city对象是固定的,只有请求的url是根据各自的服务端地址来更改的
- _that.setData( {
- city: {
- province: {},//格式province:{code: ["11000", "12000"], name: ["北京市", "上海市"]},只能固定是name和code,因为模板需要根据这俩参数显示
- city: {},
- county: {},
- provinceIndex: 0,
- cityIndex: 0,
- countyIndex: 0,
- cityUrl: "https://localhost:8282/phpserver/areas.php?type=city&fcode=",//type表示获取地区 fcode是一级code码,到时具体根据后端请求参数修改
- countyUrl: "https://localhost:8282/phpserver/areas.php?type=county&fcode="
- }
- })
- var _url = "https://localhost:8282/phpserver/areas.php";
- var _data = { 'type': 'province', 'fcode': '0' };
- city.initCityFun( _that, _url, _data );
- }
- })
这里存在一个bug,开启下拉刷新和picker组件的下拉会重叠了,不知道是开发工具原因,还是还为修改的bug。。。只能等微信方面更新消息给反馈了
今天更新的0.10.102700这个版本后,发现使用text组件触发不了picker组件了,经过一番测试后需把picker组件内的text标签换成view标签才能正常执行业务。
以上实例的cityTemplate.wxml文件里面text标签请自行更换成view标签。在进行测试~