微信小程式-收貨地址 省市區聯動 元件

十月在冬天發表於2020-10-20

簡單記錄直接上程式碼思路自己理:

addressEditor.wxml

    <!--pages/my/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/shop/icon/jiantou-right.png"></image>
            </view>
          </view>
		   <view class="address-msg">
            <view class="item-msg"></view>
            <view class="section">
				<view class="sex flex" wx:if="{{sexType==0}}" data-index="{{1}}" bindtap="chooseSexType">
					<view class="sex-btn flex">
						<image src="../../img/shop/icon/choice-b.png"></image>
						<text>男</text>
					</view>
					<view class="sex-btn flex">
						 <image src="../../img/shop/icon/choice.png"></image>
						 <text>女</text>
					</view>
				</view>
				<view class="sex flex" wx:if="{{sexType==1}}" data-index="{{0}}" bindtap="chooseSexType">
					<view class="sex-btn flex">
						<image src="../../img/shop/icon/choice.png"></image>
						<text>男</text>
					</view>
					<view class="sex-btn flex">
						 <image src="../../img/shop/icon/choice-b.png"></image>
						 <text>女</text>
					</view>
				</view>
			</view>
			<view class="address-right">
			  <image src="../../img/shop/icon/jiantou-right.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 class="address-right">
			  <image src="../../img/shop/icon/jiantou-right.png"></image>
			</view>
          </view>
          <view class="address-msg">
            <view class="item-msg">收貨地址</view>
            <view class="section" bindtap='select'>
              <input disabled="disabled" placeholder="省市區縣、鄉鎮等" value="{{consigneeRegion}}" bindblur="consigneeRegionInput" placeholder-class="phcolor"></input>
            </view>
            <view class="address-right" bindtap='select'>
              <image src="../../img/shop/icon/jiantou-right.png"></image>
            </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="../../../img/icon/icon-off-by-default.png"></image>
          </view> -->
        </view>
      </view>
    </view> 
    <view class="btn" bindtap="submit">儲存</view> 
    <view class="picker" animation="{{animationAddressMenu}}" style="visibility:{{addressMenuIsShow ? 'visible':'hidden'}}">
      <view class="picker-view" animation="{{animationAddressMenu}}" style="visibility:{{addressMenuIsShow ? 'visible':'hidden'}}">
        <!-- 確認取消按鈕 -->
        <view class='gangedBtn'>
          <text class="city-cancel" catchtap="cityCancel">取消</text>
          <text style="float: right" catchtap="citySure">確定</text>
        </view>
        <!-- 選擇地址 -->
        <picker-view class='cont' bindchange="cityChange" value="{{value}}" wx:key="">
          <!-- 省 -->
          <picker-view-column>
            <view wx:for="{{provinces}}" class="picker-item" wx:key="index">{{item.name}}</view>
          </picker-view-column>
          <!-- 市 -->
          <picker-view-column>
            <view wx:for="{{citys}}" class="picker-item" wx:key="index">{{item.name}}</view>
          </picker-view-column>
          <!-- 區 -->
          <picker-view-column>
            <view wx:for="{{areas}}" class="picker-item" wx:key="index">{{item.name}}</view>
          </picker-view-column>
        </picker-view>
      </view>
    </view>

addressEditor.wxss

/* pages/my/my-add-address/index.wxss */
.redact-address {
  background: white;
  margin-bottom: 20rpx;
}
 
.address-msg {
  height: 100rpx;
  display: flex;
  align-items: center;
  background: #FFFFFF;
  border-top: 2rpx solid #efefef;
  font-size: 28.68rpx;
  color: #333333;
  margin: 0 20rpx;
}
.address-right image {
  width: 15rpx;
  height: 25rpx;
}
.address-rights {
  display: flex;
  align-items: center;
  width: 100rpx;
  flex-direction: row-reverse;
}
.address-rights image {
  width: 22rpx;
  height: 32rpx; 
}
.address-rights view {
  font-size: 28.68rpx;
}
.address-msg:last-child {
  border-bottom: none;
}
 
.section {
  width: 58%;
}
.phcolor {
  color: #999999;
}
.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 #EEEEEE;
  border-bottom: 1px solid #EEEEEE;
  margin: 0 20rpx;
}
.label-title {
  font-size: 28.68rpx;
  color: #333333;
  margin-right: 83rpx;
}
.label .label-list {
  display: flex;
}
.label .label-list .labels{
  height: 40rpx;
  width: 96rpx;
  border: 1px solid #efefef;
  margin-right: 37rpx;
  text-align: center;
  line-height: 40rpx;
  font-size: 24rpx;
  color: #343434; 
  border-radius: 10rpx;
}
.label .label-list .labels.labels-active{
  background: #FFF7E5;
  color:  #FF8808;
}
/* 預設設定 */
.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: #333333;
  margin-bottom: 25rpx;
}
.defaul-setting-left view:nth-child(2) {
  font-size: 20rpx;
  color: #333333;
}
.defaul-setting-right {
  height: 64rpx;
  width: 105rpx;
}
 
.btn {
  width: 680rpx;
  height: 88rpx;
  background: #4396F7;
  color: #FFFFFF;
  position: fixed;
  bottom: 55rpx;
  left: 35rpx;
  border-radius: 41.5rpx;
  font-size: 36rpx;
  text-align: center;
  line-height: 88rpx;
}
 
/* 城市選擇 */
.picker {
  width: 100%;
  height: 100%;
  display: flex;
  z-index: 12;
  background-color: #fff;
  background: rgba(0, 0, 0, 0.2);
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: fixed;
  bottom: 0;
  left: 0rpx;
}
.picker-view {
  width: 100%;
  display: flex;
  z-index: 12;
  background-color: #fff;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: fixed;
  bottom: 0;
  left: 0rpx;
  height: 40vh;
  border-top-left-radius: 30rpx;
  border-top-right-radius: 30rpx;
}
 
.gangedBtn {
  border-top: 1px solid #efefef;
  border-top-left-radius: 30rpx;
  border-top-right-radius: 30rpx;
  width: 100%;
  height: 90rpx;
  padding: 0 66rpx;
  box-sizing: border-box;
  line-height: 90rpx;
  text-align: center;
  color: black;
  font-size: 0.8rem;
  display: flex;
  background: white;
  justify-content: space-between;
}
 
.cont {
  width: 100%;
  height: 389rpx;
}
 
.picker-item {
  line-height: 70rpx;
  margin-left: 5rpx;
  margin-right: 5rpx;
  text-align: center;
}
 
.address {
  width: 100%;
  height: 90rpx;
  line-height: 90rpx;
  text-align: center;
  border-bottom: 1rpx solid #f1f1f1;
}
.city-cancel {
  color: gray;
}

.sex-btn image{
	width: 30rpx;
	height: 30rpx;
	margin-right: 10rpx;
}

.sex{
	align-items: center;
	justify-content: space-between;
	padding-right: 40%;
}

.sex-btn{
	align-items: center; 
}

addressEditor.js
 

const address = require('../../../utils/mock.js')//換成自己的地址
Page({
  /**
    * 控制元件當前顯示的資料
    * provinces:所有省份
    * citys 選擇省對應的所有市,
    * areas 選擇市對應的所有區
    * consigneeRegion:點選確定時選擇的省市縣結果
    * animationAddressMenu:動畫
    * addressMenuIsShow:是否可見
    */
  /**
   * 頁面的初始資料
   */
  data: {
    animationAddressMenu: {},
    addressMenuIsShow: false,
    value: [0, 0, 0],
    provinces: [],
    consigneeName: "張三", 
    phone: "13552598553",
    consigneeRegion: "北京市海淀區",
    detailedAddress: "中關村軟體園一期",
    labelList: ["家", "公司", "學校"],            //標籤
    labelDefault: 0,              // 標籤預設
	sexType:0
    
  },
  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
    })
  },
  chooseSexType: function(e) {
    var index = e.currentTarget.dataset.index;
    this.setData({
      sexType: index
    })
  },
 submit: function() {
   var acceptName = this.data.consigneeName; 
   var mobile = this.data.phone; 
 	var sexType = this.data.sexType; 
 	var latitude = getApp().globalData.latitude;
 	var longitude = getApp().globalData.longitude;
   var positionName = this.data.consigneeRegion; 
   var address = this.data.detailedAddress;
 	
   if (acceptName == "") {
     wx: wx.showToast({
       title: '請輸入姓名',
 		icon: 'none'
     })
     return false
   }
   else if (mobile == "") {
     wx: wx.showToast({
       title: '請輸入手機號碼',
 		icon: 'none'
     })
     return false
   }
   else if (positionName == "") {
     wx: wx.showToast({
       title: '請選擇所在地區',
 		icon: 'none'
     })
     return false
   }
   else if (address == "") {
     wx: wx.showToast({
       title: '請輸入詳細地址',
 		icon: 'none'
     })
     return false
   }
   else {
	   //提交ajax
   }
 },
  /**
   * 生命週期函式--監聽頁面載入
   */
  onLoad: function (options) {
    // 預設聯動顯示北京
    var id = address.provinces[0].id
    this.setData({
      provinces: address.provinces,
      citys: address.citys[id],
      areas: address.areas[address.citys[id][0].id],
    })
  },
  // 點選所在地區彈出選擇框
  select: function (e) {
    // 如果已經顯示,不在執行顯示動畫
    if (this.data.addressMenuIsShow) {
      return false
    } else {
      // 執行顯示動畫
      this.startAddressAnimation(true)
    }
  },
  // 執行動畫
  startAddressAnimation: function (isShow) {
    if (isShow) {
      // vh是用來表示尺寸的單位,高度全屏是100vh
      this.animation.translateY(0 + 'vh').step()
    } else {
      this.animation.translateY(40 + 'vh').step()
    }
    this.setData({
      animationAddressMenu: this.animation.export(),
      addressMenuIsShow: isShow,
    })
  },
  // 點選地區選擇取消按鈕
  cityCancel: function (e) {
    this.startAddressAnimation(false)
  },
  // 點選地區選擇確定按鈕
  citySure: function (e) {
    var that = this
    var city = that.data.city
    var value = that.data.value
    this.startAddressAnimation(false)
    // 將選擇的城市資訊顯示到輸入框
    var consigneeRegion = that.data.provinces[value[0]].name + '-' + that.data.citys[value[1]].name + '-' + that.data.areas[value[2]].name
    that.setData({
      consigneeRegion: consigneeRegion,
    })
  },
  // 處理省市縣聯動邏輯
  cityChange: function (e) {
    var value = e.detail.value
    var provinces = this.data.provinces
    var citys = this.data.citys
    var areas = this.data.areas
    var provinceNum = value[0]
    var cityNum = value[1]
    var countyNum = value[2]
    // 如果省份選擇項和之前不一樣,表示滑動了省份,此時市預設是省的第一組資料,
    if (this.data.value[0] != provinceNum) {
      var id = provinces[provinceNum].id
      this.setData({
        value: [provinceNum, 0, 0],
        citys: address.citys[id],
        areas: address.areas[address.citys[id][0].id],
      })
    } else if (this.data.value[1] != cityNum) {
      // 滑動選擇了第二項資料,即市,此時區顯示省市對應的第一組資料
      var id = citys[cityNum].id
      this.setData({
        value: [provinceNum, cityNum, 0],
        areas: address.areas[citys[cityNum].id],
      })
    } else {
      // 滑動選擇了區
      this.setData({
        value: [provinceNum, cityNum, countyNum]
      })
    }
  },
  /**
   * 生命週期函式--監聽頁面初次渲染完成
   */
  onReady: function () {
 
  },
 
  /**
   * 生命週期函式--監聽頁面顯示
   */
  onShow: function () {
    var animation = wx.createAnimation({
      duration: 500,
      timingFunction: 'linear',
    })
    this.animation = animation
  },
 
  /**
   * 生命週期函式--監聽頁面隱藏
   */
  onHide: function () {
 
  },
 
  /**
   * 生命週期函式--監聽頁面解除安裝
   */
  onUnload: function () {
 
  },
 
  /**
   * 頁面相關事件處理函式--監聽使用者下拉動作
   */
  onPullDownRefresh: function () {
 
  },
 
  /**
   * 頁面上拉觸底事件的處理函式
   */
  onReachBottom: function () {
 
  },
 
  /**
   * 使用者點選右上角分享
   */
  onShareAppMessage: function () {
 
  }
})

 

mock.js

 

 

相關文章