直接进入正题
首先在项目中同级创建一个components文件夹,在文件夹下创建region-picker文件夹,在该文件夹点击右键新建Component就会创建名为
region-picker.js
region-picker.json
region-picker.wxml
region-picker.wxss
下面我们来写我们的组件
region-picker.wxml
<view class="mask-layer" hidden="{{isShowToast}}"></view>
<view class="goodsdetail" hidden="{{isShowToast}}">
<view class="seclection-title">请选择所在地区</view>
<image class="close" src="../../img/icon/icon-cancel.png" bindtap="hideGoodsDetail"></image>
<view class="state">
<view>中国大陆</view>
<view class="state-active"></view>
</view>
<view class="hot-city" hidden="{{!isClick}}">
<view class="hot-title">热门城市</view>
<view class="hot-city-list">
<view wx:for="{{hotcityList}}" wx:key='item' data-item='{{item.city}}' data-index='{{item.id}}' bindtap='provinceChange'>{{item.city}}</view>
</view>
</view>
<!-- <view class='goodsdetail-title'></view> -->
<view class='goodsdetail-top' hidden="{{isClick}}">
<view wx:for='{{nameArr}}' wx:key="index" class='{{currentTab == index ? "goodsdetail-top-l-o":"goodsdetail-top-l"}}' style='{{item == "" ? "display: none;":""}}' bindtap="navbarTap" data-index='{{index}}'>
<view>{{item}}</view>
</view>
</view>
<swiper class="swiper-box">
<swiper-item wx:if='{{currentTab == 0}}' catchtouchmove='catchTouchMove'>
<scroll-view scroll-y class="swiper-box-scr">
<view class='swiper-box-item {{nameArr[0] == item ? "active":""}}' wx:for='{{provinceArr}}' wx:key='item' data-item='{{item}}' data-index='{{index}}' bindtap='provinceChange'>
<block wx:if="{{nameArr[0] == item}}">
<image class="select" src="{{nameArr[0] == item? '../../img/icon/icon-select.png': ''}}"></image>
</block>
<view>{{item}}</view>
</view>
</scroll-view>
</swiper-item>
<swiper-item wx:if='{{currentTab == 1}}' catchtouchmove='catchTouchMove'>
<scroll-view scroll-y class="swiper-box-scr">
<view class='swiper-box-item {{nameArr[1] == item ? "active":""}}' wx:for='{{cityArr}}' wx:key='item' data-item='{{item}}' data-index='{{index}}' bindtap='cityChange'>
<block wx:if="{{nameArr[1] == item}}">
<image class="select" src="{{nameArr[1] == item? '../../img/icon/icon-select.png': ''}}"></image>
</block>
<view>{{item}}</view>
</view>
</scroll-view>
</swiper-item>
<swiper-item wx:if='{{currentTab == 2}}' catchtouchmove='catchTouchMove'>
<scroll-view scroll-y class="swiper-box-scr">
<view class='swiper-box-item {{nameArr[2] == item ? "active":""}}' wx:for='{{countryArr}}' wx:key='item' data-item='{{item}}' data-index='{{index}}' bindtap='districtChange'>
<block wx:if="{{nameArr[2] == item}}">
<image class="select" src="{{nameArr[2] == item? '../../img/icon/icon-select.png': ''}}"></image>
</block>
<view>{{item}}</view>
</view>
</scroll-view>
</swiper-item>
</swiper>
</view>
region-picker.wxss
/*弹窗*/
.goodsdetail {
position: fixed;
left: 5rpx;
bottom: 10rpx;
width: 740rpx;
height: 1000rpx;
background: #fff;
z-index: 99;
overflow: hidden;
border-radius: 20rpx;
}
.goodsdetail-top {
width: 750rpx;
box-sizing: border-box;
display: flex;
position: relative;
margin: 81rpx 34rpx;
}
.goodsdetail-top-l {
box-sizing: border-box;
font-size: 28rpx;
font-weight: bold;
font-family: "PingFang-SC-Bold";
color: #f73c41;
margin-right: 74rpx;
}
.goodsdetail-top-l-o {
box-sizing: border-box;
font-size: 28rpx;
font-weight: bold;
font-family: "PingFang-SC-Bold";
margin-right: 74rpx;
}
.goodsdetail-top-c {
height: 80rpx;
padding: 0 20rpx 0 20rpx;
line-height: 80rpx;
box-sizing: border-box;
font-size: 26rpx;
}
.goodsdetail-top-c-o {
height: 80rpx;
padding: 0 20rpx 0 20rpx;
line-height: 80rpx;
box-sizing: border-box;
font-size: 26rpx;
border-bottom: 1rpx solid #e22e1f;
}
.goodsdetail-top-r {
height: 80rpx;
padding: 0 20rpx 0 20rpx;
line-height: 80rpx;
box-sizing: border-box;
font-size: 26rpx;
}
.goodsdetail-top-r-o {
height: 80rpx;
padding: 0 20rpx 0 20rpx;
line-height: 80rpx;
box-sizing: border-box;
font-size: 26rpx;
border-bottom: 1rpx solid #e22e1f;
}
.goodsdetail-top-cancel {
position: absolute;
right: 0;
top: 0;
color: #aaa;
height: 80rpx;
padding: 0 40rpx 0 20rpx;
line-height: 80rpx;
box-sizing: border-box;
font-size: 26rpx;
}
.swiper-box {
width: 740rpx;
height: 620rpx;
box-sizing: border-box;
}
.swiper-box-scr {
width: 740rpx;
height: 620rpx;
box-sizing: border-box;
}
.swiper-box-item {
height: 85rpx;
line-height: 85rpx;
font-size: 28rpx;
font-weight: Medium;
font-family: "PingFang-SC-Medium";
border-bottom: 1rpx solid #EEEEEE;
box-sizing: border-box;
display: flex;
position: relative;
margin: 0 30rpx;
padding: 0 5rpx;
align-items: center;
}
.seclection-title {
text-align: center;
margin-top: 40rpx;
font-size: 32rpx;
font-weight: bold;
font-family: "PingFang-SC-Bold";
color: #000000;
margin-bottom: 83rpx;
}
.state {
font-size: 30rpx;
color: #f73c41;
font-weight: bold;
font-family: "PingFang-SC-Bold";
margin-left: 35rpx;
margin-right: 35rpx;
}
.state view:nth-child(1) {
margin-bottom: 11rpx;
}
.close {
width: 32rpx;
height: 31rpx;
position: absolute;
right: 39rpx;
top: 41rpx;
}
.state-active {
height: 6rpx;
width: 20.4rpx;
background: #f73c41;
border-radius: 2.5rpx;
margin-left: 48rpx;
}
.hot-city {
margin: 68rpx 35rpx 64rpx;
}
.hot-city .hot-title {
font-size: 28rpx;
color: #999999;
}
.hot-city .hot-city-list {
display: flex;
font-size: 28rpx;
color: #000000;
justify-content: space-between;
margin-top: 42rpx;
}
.hot-city view:nth-child(2) view:nth-child(1) {
margin-left: 28rpx;
}
.hot-city view:nth-child(2) view:last-child {
margin-right: 28rpx;
}
.active {
font-size: 28rpx;
font-weight: bold;
font-family: "PingFang-SC-Bold";
color: #f73c41;
}
.mask-layer {
width: 100%;
height: 100%;
background: #000;
opacity: 0.5;
position: fixed;
z-index: 99;
top: 0;
left: 0;
overflow: hidden;
}
.swiper-box-item image {
width: 35rpx;
height: 27rpx;
margin-right: 22rpx;
}
region-picker.js
var city = require('../../utils/city.js')
Component({
/**
* 组件的属性列表
*/
properties: {
locationArr: {
type: Array,
value: '',
observer: function(newVal, oldVal) {
console.log('我是传递进入的省', newVal)
}
},
},
/**
* 组件的初始数据
*/
data: {
// 弹窗显示控制
isShowToast: true,
isShowToasts: false,
isClick: true,
nameArr: ['请选择', '', ''],
currentTab: 0, // tab切换
provinceArr: [],
provinceIndex: 0,
cityArr: [],
cityIndex: 0,
countryArr: [],
countryIndex: 0,
hotcityList: [{
id: 0,
city: '北京'
}, {
id: 8,
city: '上海'
}, {
id: 1,
city: '天津'
}, {
id: 18,
city: '广东'
}]
},
/**
* 组件的方法列表
*/
methods: {
//隐藏
hideGoodsDetail: function() {
var that = this
that.setData({
isShowToast: true
})
},
//显示
showsGoodsDetail: function() {
var that = this
var tempLocalArr = that.properties.locationArr //传入的省市区
var tempNameArr = that.data.nameArr //顶部省市区
that.setData({
isShowToast: false
})
// console.log('我是传入的值')
// console.log(tempLocalArr)
this.setData({
provinceArr: city.getProvince()
});
// console.log(city.getProvince())
//是否传入地址 传入则显示当前地址 为传入则显示之前地址
if (tempLocalArr[0] == '' || tempLocalArr[1] == '' || tempLocalArr[2] == '') {
console.log('我是未传入地址')
} else {
// console.log('我是传入了地址')
tempNameArr[0] = tempLocalArr[0]
tempNameArr[1] = tempLocalArr[1]
tempNameArr[2] = tempLocalArr[2]
var tempProvinceIndex = that.data.provinceArr.indexOf(tempLocalArr[0]) //省索引
//在这里对不存在的地址进行兼容
if (tempProvinceIndex == -1) {
// console.log('我是省没有 找到')
tempProvinceIndex = 0
tempNameArr[0] = that.data.provinceArr[0]
}
var tempCityArr = city.getCity(that.data.provinceArr[tempProvinceIndex]) //市
var tempCityIndex = tempCityArr.indexOf(tempLocalArr[1]) //市索引
//在这里对不存在的地址进行兼容
if (tempCityIndex == -1) {
// console.log('我是市没有 找到')
tempCityIndex = 0
tempNameArr[1] = tempCityArr[0]
}
var tempCountryArr = city.getArea(that.data.provinceArr[tempProvinceIndex], tempCityArr[tempCityIndex]) //区
var tempCountryIndex = tempCountryArr.indexOf(tempLocalArr[2]) //区索引
//在这里对不存在的地址进行兼容
if (tempCountryIndex == -1) {
// console.log('我是区没有 找到')
tempCountryIndex = 0
tempNameArr[2] = tempCountryArr[0]
}
that.setData({
nameArr: tempNameArr,
provinceIndex: tempProvinceIndex,
cityArr: tempCityArr,
cityIndex: tempCityIndex,
countryArr: tempCountryArr,
countryIndex: tempCountryIndex,
currentTab: 0,
})
}
},
//改变省
provinceChange: function(e) {
var that = this
var tempNameArr = that.data.nameArr
console.log(e.currentTarget.dataset.index)
console.log(e.currentTarget.dataset.item)
tempNameArr[0] = that.data.provinceArr[e.currentTarget.dataset.index]
tempNameArr[1] = '请选择'
tempNameArr[2] = ''
that.setData({
provinceIndex: e.currentTarget.dataset.index,
nameArr: tempNameArr,
countryArr: [],
countryIndex: 0,
})
//获取市
this.setData({
cityArr: city.getCity(that.data.provinceArr[that.data.provinceIndex]),
currentTab: 1,
isClick: false,
});
console.log(that.data.cityArr)
},
//改变市
cityChange: function(e) {
var that = this
var tempNameArr = that.data.nameArr
tempNameArr[0] = that.data.provinceArr[that.data.provinceIndex]
tempNameArr[1] = that.data.cityArr[e.currentTarget.dataset.index]
tempNameArr[2] = '请选择'
that.setData({
cityIndex: e.currentTarget.dataset.index,
nameArr: tempNameArr
})
//获取区
this.setData({
countryArr: city.getArea(that.data.provinceArr[that.data.provinceIndex], that.data.cityArr[that.data.cityIndex]),
currentTab: 2
});
},
//改变区区/县
districtChange: function(e) {
var that = this
var tempNameArr = that.data.nameArr
tempNameArr[0] = that.data.provinceArr[that.data.provinceIndex]
tempNameArr[1] = that.data.cityArr[that.data.cityIndex]
tempNameArr[2] = that.data.countryArr[e.currentTarget.dataset.index]
that.setData({
countryIndex: e.currentTarget.dataset.index,
nameArr: tempNameArr,
isShowToast: true,
currentTab: 0
})
//关闭并返回
this.triggerEvent('resultEvent', {
nameArr: that.properties.nameArr
})
console.log(that.data.provinceArr[that.data.provinceIndex])
// console.log(that.data.cityArr[that.data.cityIndex])
// console.log(that.data.countryArr[that.data.countryIndex])
//关闭并返回 省市区
},
// 截获竖向滑动 2018年7月5日19:55:40 刘宣亮
catchTouchMove: function(res) {
return false
},
// 点击tab切换 2018年7月5日19:59:30 刘宣亮
navbarTap: function(e) {
var that = this
that.setData({
currentTab: e.currentTarget.dataset.index,
})
console.log(e.currentTarget.dataset.index)
},
}
})
region-picker.json
{
"component": true,
"usingComponents": {}
}
以上就完成了组件
下面来看看怎么来调用吧
在需要调用的页面添加
"usingComponents": {
"region-picker": "../../components/region-picker/region-picker"
}
顺便补充一点吧,我添加页面调用的效果
这样没什么问题吧,my-add-address就是一个文件夹,index是我的习惯,你也可以直接my-add-address.wxml,最后会给大家看一下我的目录结构
my-add-address/index.wxml
<view class="redact-address">
<view class="possess-layout">
<view class="mains">
<view class="address-msg">
<view class="item-msg">收货人</view>
<view class="section">
<input type="text" placeholder="请填写收货人姓名" value="{{consigneeName}}" bindblur="consigneeNameInput" placeholder-class="phcolor"></input>
</view>
<view class="address-right">
<image src="../../../img/icon/icon-add-address-user.png"></image>
</view>
</view>
<view class="address-msg">
<view class="item-msg">手机号码</view>
<view class="section">
<input type="number" placeholder="请填写收货人手机号码" value="{{phone}}" maxlength="11" bindblur="phoneInput" placeholder-class="phcolor"></input>
</view>
</view>
<view class="address-msg" bindtap='chooseAddress'>
<view class="item-msg">所在地区</view>
<view class="section" bindtap='select'>
<input disabled="disabled" placeholder="省市区县、乡镇等" value="{{locationArr[0] + locationArr[1] + locationArr[2]}}" bindblur="consigneeRegionInput" placeholder-class="phcolor"></input>
</view>
<view class="address-rights" bindtap='select'>
<image src="../../../img/icon/icon-site-location.png"></image>
<view>定位</view>
</view>
</view>
<view class="address-msg">
<view class="item-msg">详细地址</view>
<view class="section">
<input type="text" placeholder="街道、楼牌号等" value="{{detailedAddress}}" bindblur="detailedAddressInput" placeholder-class="phcolor"></input>
</view>
</view>
<view class="label">
<view class="label-title">标签</view>
<view class="label-list">
<block wx:for="{{labelList}}" wx:key="index">
<view class="labels {{labelDefault==index? 'labels-active': ''}}" data-index="{{index}}" bindtap="chooseLabelSelect">{{item}}</view>
</block>
</view>
</view>
<view class="default-setting">
<view class="defaul-setting-left">
<view>设置默认地址</view>
<view>提醒:每次下单会默认推荐使用该地址</view>
</view>
<image class="defaul-setting-right" src="{{defaults? '../../../img/icon/icon-off-by-default.png': '../../../img/icon/icon-off-by-default-red.png'}}" bindtap="chooseDefault"></image>
</view>
</view>
</view>
</view>
<view class="btn" bindtap="submit">保存</view>
<!-- 城市选择 S -->
<scroll-view scroll-y style="height: {{windowHeight}}px;width: 100%;" class='body'>
<region-picker id='getAddress' locationArr="{{locationArr}}" bind:resultEvent="resultEvent">
</region-picker>
</scroll-view>
<!-- 城市选择 E -->
my-add-address/index.wxss
.redact-address {
background: white;
margin-bottom: 20rpx;
}
.address-msg {
height: 128rpx;
display: flex;
align-items: center;
background: #fff;
border-top: 2rpx solid #efefef;
font-size: 28.68rpx;
color: #333;
padding: 0 20rpx;
}
.address-right image {
width: 32rpx;
height: 32rpx;
}
.address-rights {
display: flex;
align-items: center;
}
.address-rights image {
width: 26rpx;
height: 32rpx;
margin-right: 13rpx;
}
.address-rights view {
font-size: 28.68rpx;
}
.address-msg:last-child {
border-bottom: none;
}
.section {
width: 58%;
}
.phcolor {
color: #999;
}
.item-msg {
width: 25%;
margin-right: 25rpx;
}
.img {
width: 35rpx;
height: 35rpx;
align-self: center;
}
.address-right {
width: 100rpx;
display: flex;
flex-direction: row-reverse;
}
/* 标签 */
.label {
display: flex;
height: 128rpx;
align-items: center;
margin-top: 73rpx;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
padding: 0 20rpx;
}
.label-title {
font-size: 28.68rpx;
color: #333;
margin-right: 83rpx;
}
.label .label-list {
display: flex;
}
.label .label-list .labels {
height: 40rpx;
width: 96rpx;
border: 1px solid #eee;
margin-right: 37rpx;
text-align: center;
line-height: 40rpx;
font-size: 24rpx;
color: #000;
border-radius: 20rpx;
}
.labels-active {
background: #f73c41 !important;
color: #fff !important;
}
/* 默认设置 */
.default-setting {
display: flex;
justify-content: space-between;
align-items: center;
height: 160rpx;
padding: 0 20rpx;
}
.defaul-setting-left view:nth-child(1) {
font-size: 28.68rpx;
color: #333;
margin-bottom: 25rpx;
}
.defaul-setting-left view:nth-child(2) {
font-size: 20rpx;
color: #333;
}
.defaul-setting-right {
height: 64rpx;
width: 105rpx;
}
.btn {
width: 680rpx;
height: 88rpx;
background: #f73c41;
color: #fff;
position: fixed;
bottom: 55rpx;
left: 35rpx;
border-radius: 41.5rpx;
font-size: 36rpx;
text-align: center;
line-height: 88rpx;
}
/* 城市选择 */
.body {
display: block;
/* border: 1rpx solid #000; */
box-sizing: border-box;
}
.choose_address{
height: 90rpx;
width: 750rpx;
box-sizing: border-box;
padding: 0 40rpx 0 40rpx;
font-size: 32rpx;
line-height: 90rpx;
border-bottom: 1rpx solid #aaa;
}
my-add-address/index.js
var app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
addressMenuIsShow: false,
consigneeName: "",
phone: "",
detailedAddress: "",
labelList: ["家", "公司", "学校"], //标签
labelDefault: 0, // 标签默认,
defaults: 0, // 默认
// 城市选择
windowHeight: 0,
// locationArr: ['山东省', '青岛市', '黄岛区']
locationArr: ['', '', '']
},
consigneeNameInput: function(e) { //获取收货人
this.setData({
consigneeName: e.detail.value
})
},
phoneInput: function(e) { //获取手机号
this.setData({
phone: e.detail.value
})
},
consigneeRegionInput: function(e) { //获取所在地址
this.setData({
consigneeRegion: e.detail.value
})
},
detailedAddressInput: function(e) { //获取详细地址
this.setData({
detailedAddress: e.detail.value
})
},
chooseLabelSelect: function(e) { //获取标签
var index = e.currentTarget.dataset.index;
this.setData({
labelDefault: index
})
},
submit: function() {
var consigneeName = this.data.consigneeName;
var phone = this.data.phone;
var consigneeRegion = this.data.consigneeRegion;
var detailedAddress = this.data.detailedAddress
if (consigneeName == "") {
wx: wx.showToast({
title: '请输入姓名',
image: "../../../img/icon/icon-reminder.png"
})
return false
}
else if (phone == "") {
wx: wx.showToast({
title: '请输入手机号码',
image: "../../../img/icon/icon-reminder.png"
})
return false
}
else if (consigneeRegion == "") {
wx: wx.showToast({
title: '请选择所在地区',
image: "../../../img/icon/icon-reminder.png"
})
return false
}
else if (detailedAddress == "") {
wx: wx.showToast({
title: '请输入详细地址',
image: "../../../img/icon/icon-reminder.png"
})
return false
}
else {
wx.navigateTo({
url: '../../my/my-delivery-address/index',
})
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function(options) {
var _this = this
//获得dialog组件
this.getAddress = this.selectComponent("#getAddress");
wx.getSystemInfo({
success: function (res) {
// console.log(res.pixelRatio) //设备像素比
// console.log(res.windowWidth) //可使用窗口宽度
// console.log(res.windowHeight) //可使用窗口高度
_this.setData({
windowWidth: res.windowWidth, //可使用窗口宽度
windowHeight: res.windowHeight, //可使用窗口高度
})
}
})
},
/**
* 是否选择默认
*/
chooseDefault: function() {
this.setData({
defaults: this.data.defaults
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function() {
},
//选择地址 点击所在地区弹出选择框
chooseAddress: function (e) {
var _this = this
_this.getAddress.showsGoodsDetail();
},
//组件回调
resultEvent: function (e) {
var _this = this
// console.log(e)
// console.log(e.detail.nameArr)
_this.setData({
locationArr: e.detail.nameArr
})
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function() {
}
})
my-add-address/index.json
{
"navigationBarTitleText": "添加收货地址",
"usingComponents": {
"region-picker": "../../components/region-picker/region-picker"
}
}
以上就是所有代码
上图
目录结构
最后来张效果图
可扫码自行下载city.js文件
city.js文件可自行下载:微信小程序实现城市选择效果city.js文件_微信小程序城市选择器-互联网文档类资源-CSDN下载