功能有:地址列表,新增,修改,左滑删除地址
image.png
效果图
地址列表
image.png
新增地址
image.png
编辑地址
image.png
左滑删除
image.png
在app.json里引入weui
"useExtendedLib": {
"weui": true
},
在使用左滑功能的页面json里引入组件
"usingComponents": {
"mp-slideview": "weui-miniprogram/slideview/slideview"
},
地址列表代码:
<view class="addr_wrap">
<!--没有地址-->
<view wx:if="{{!address.length}}" class="no_addr_wrap">
<navigator url="/pages/address_manage/address_manage" hover-class="none">新增地址</navigator>
</view>
<!--有地址-->
<view wx:else class="have_addr_wrap">
<view wx:for="{{address}}" wx:key="index" class="slideview_wrap">
<mp-slideview buttons="{{slideButtons}}" data-index="{{index}}" bindbuttontap="slideButtonTap">
<view class="addr_item">
<view class="checkbox_wrap">
<radio-group bindchange="handleAddress" data-index="{{index}}">
<radio checked="{{item.checked}}" value="{{item.userName}}" color="#eb4450"></radio>
</radio-group>
</view>
<view class="addr_detail">
<view class="addr_name">
<text class="name_txt">{{item.userName}}</text>
<text class="tel_txt">{{item.telNumber}}</text>
</view>
<view class="addr_txt_wrap">
<view class="addr_txt">地址:</view>
<view class="detail_txt">{{item.all}}</view>
</view>
</view>
<navigator
url="/pages/address_manage/address_manage?id={{index}}"
hover-class="none"
class="edit_wrap icon-xiugai iconfont">
</navigator>
</view>
</mp-slideview>
</view>
</view>
</view>
<view class="add_addr_tool">
<navigator url="/pages/address_manage/address_manage" hover-class="none" class="tool_wrap">
<view class="add_icon">+</view>
<view class="add_txt">新增个人地址</view>
<view class="jiantou_icon">></view>
</navigator>
</view>
Page({
data: {
address: [], // 所有地址数组
slideButtons: [{ // 左滑按钮配置
type: 'warn',
text: '删除'
}],
},
onShow() {
this.getAddress()
},
// 获取地址信息
getAddress() {
const addressList = wx.getStorageSync('addressList') || [] // 用户自己在新增地址页面添加的
addressList.map(v => {
if (!v.checked) { // 如果没有checked就添加一个
v.checked = false
}
}) // 给地址添加一个是否选中的标识
this.setData({address: addressList})
},
// 选择地址
handleAddress(e) {
const {index} = e.currentTarget.dataset
let {address} = this.data
address.forEach((v, i) => i === index ? v.checked = true : v.checked = false)
this.setData({
address
})
wx.setStorageSync('addressList', address)
},
slideButtonTap(e) {
const {index} = e.detail // index对应的是slideButtons数组的索引 index为多少就表示点击的是数组的第几个
const currentIndex = e.currentTarget.dataset.index // 点击当前的索引
let {address} = this.data
if (index === 0) { // 删除
wx.showModal({
content: '确认删除吗',
success: (res) => {
if (res.confirm) { // 用户点击了确定
address.splice(currentIndex, 1) // 删除当前索引对应的数据
this.setData({address})
wx.setStorageSync('addressList', address)
} else {
console.log('用户点击了取消')
}
}
})
}
}
})
css
page {
background-color: #dddddd;
height: 100vh;
padding-bottom: 90rpx;
}
.no_addr_wrap {
display: flex;
justify-content: center;
align-items: center;
padding-top: 20rpx;
navigator {
color: #06ae56;
font-size: 40rpx;
width: 70%;
border-radius: 15rpx;
height: 90rpx;
border: 1px solid #06ae56;
display: flex;
justify-content: center;
align-items: center;
font-weight: bold;
}
}
.have_addr_wrap {
padding: 20rpx;
.slideview_wrap {
margin-top: 15rpx;
&:first-child {
margin-top: 0;
}
/deep/ .weui-slideview__btn {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.addr_item {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
padding: 30rpx 10rpx;
}
.checkbox_wrap {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
radio {
transform: scale(0.7);
}
}
.addr_detail {
flex: 8;
margin-left: 15rpx;
.addr_name {
color: #666666;
}
.tel_txt {
margin-left: 20rpx;
}
.addr_txt_wrap {
color: #666666;
margin-top: 15rpx;
display: flex;
.addr_txt {
flex-shrink: 0;
}
}
}
.edit_wrap {
flex: 1;
color: #666666;
font-size: 30rpx;
display: flex;
justify-content: center;
}
}
.add_addr_tool {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
height: 90rpx;
padding: 0 20rpx;
.tool_wrap {
display: flex;
align-items: center;
justify-content: space-between;
height: 100%;
.add_icon {
width: 30rpx;
height: 30rpx;
border-radius: 50%;
line-height: 29rpx;
text-align: center;
background-color: var(--themeColor);
color: #ffffff;
}
.add_txt {
flex: 30;
margin-left: 15rpx;
color: #666666;
}
.jiantou_icon {
flex: 1;
color: #acacac;
font-size: 36rpx;
}
}
}
编辑地址页面address_manage
<form bindsubmit="submitForm">
<view class="addr_manage">
<view class="addr_ma_item">
<view class="addr_ma_txt">姓名</view>
<view class="addr_ma_input">
<input placeholder="请填写收货人姓名" value="{{form.userName}}" name="userName" placeholder-class="placeholder_class"/>
</view>
</view>
<view class="addr_ma_item">
<view class="addr_ma_txt">电话</view>
<view class="addr_ma_input">
<input placeholder="请填写收货电话" value="{{form.telNumber}}" name="telNumber" placeholder-class="placeholder_class"/>
</view>
</view>
<view class="addr_ma_item province_select">
<view class="picker_wrap">
<view class="addr_ma_txt">省市区</view>
<picker mode="region" bindchange="bindRegionChange" value="{{form.region}}" name="region" custom-item="{{customItem}}">
<view class="{{form.region[1]?'':'default_picker'}}">
{{form.region[0]}}
{{form.region[1]?'-':''}}
{{form.region[1]}}
{{form.region[1]?'-':''}}
{{form.region[2]}}
</view>
</picker>
</view>
<view class="addr_ma_icon">></view>
</view>
<view class="addr_ma_item">
<view class="addr_ma_txt">详细信息</view>
<view class="addr_ma_input">
<input placeholder="街道、楼牌号等" value="{{form.addrDetail}}" name="addrDetail" placeholder-class="placeholder_class"/>
</view>
</view>
</view>
<!--提交按钮-->
<view class="submit_btn_wrap">
<button type="primary" formType="submit">提交</button>
<button type="warn" bindtap="restForm" plain>取消</button>
</view>
</form>
const app = getApp()
Page({
data: {
form: {
userName: '',
telNumber: '',
addrDetail: '',
region: ['请选择省市区/县', '', ''], // 省市区数据 第一个可以当placeholder
},
customItem: '', // 自定义picker显示的内容
},
Postcode: '', // 邮编
AddressId: -1,
onShow() {
const {id} = app.getPage(1).options
if (id >= 0) {
this.AddressId = id
this.getEditAddress(id)
}
},
// 省市区选择事件
bindRegionChange(e) {
const {value, code, postcode} = e.detail
// console.log(code) // 统计用区划代码
// postcode 是邮政编码
this.Postcode = postcode
this.setData({
'form.region': value
})
},
// 提交表单
submitForm(e) {
if (!this.validateForm(e)) return
// userName,telNumber...对应的是input的name属性
const {userName, telNumber, region, addrDetail} = e.detail.value
const addressList = wx.getStorageSync('addressList') || []
if (this.AddressId >= 0) { // 编辑地址
addressList[this.AddressId].userName = userName
addressList[this.AddressId].telNumber = telNumber
addressList[this.AddressId].postalCode = this.Postcode
addressList[this.AddressId].provinceName = region[0]
addressList[this.AddressId].cityName = region[1]
addressList[this.AddressId].countyName = region[2]
addressList[this.AddressId].detailInfo = addrDetail
addressList[this.AddressId].all = region[0] + region[1] + region[2] + addrDetail
} else { // 新增地址
const address = {
userName,
telNumber,
postalCode: this.Postcode,
provinceName: region[0],
cityName: region[1],
countyName: region[2],
detailInfo: addrDetail,
all: region[0] + region[1] + region[2] + addrDetail
}
addressList.push(address)
}
wx.setStorageSync('addressList', addressList)
wx.showToast({
title: '提交成功',
})
wx.navigateBack({
delta: 1
})
},
// 验证form
validateForm(e) {
const telReg = app.regExps.mobile
const {userName, telNumber, region, addrDetail} = e.detail.value
if (!userName.trim()) {
wx.showToast({
title: '请先填写姓名',
icon: "none"
})
return false
}
if (!telNumber.trim() || !telReg.test(telNumber)) {
wx.showToast({
title: '请先填正确的手机号',
icon: "none"
})
return false
}
if (!region.length) {
wx.showToast({
title: '请先选择省市区',
icon: "none"
})
return false
}
if (!addrDetail.trim()) {
wx.showToast({
title: '请先填写详细信息',
icon: "none"
})
return false
}
return true
},
// 编辑地址获取需要编辑的地址信息
getEditAddress(id) {
const addressList = wx.getStorageSync('addressList') || []
const address = addressList[id]
this.setData({
'form.userName': address.userName,
'form.telNumber': address.telNumber,
'form.addrDetail': address.detailInfo,
'form.region': [address.provinceName, address.cityName, address.countyName],
})
},
// 重置表单
restForm() {
this.setData({
'form.userName': '',
'form.telNumber': '',
'form.addrDetail': '',
'form.region': []
})
wx.navigateBack({
delta: 1
})
}
})
page {
background-color: #f9f9f9;
}
.addr_manage {
.addr_ma_item {
display: flex;
border-bottom: 1px solid #ececec;
padding: 20rpx;
align-items: center;
color: #666666;
.addr_ma_txt {
display: 2;
}
.addr_ma_input {
flex: 4;
margin-left: 30rpx;
padding-right: 20rpx;
}
}
.province_select {
display: flex;
justify-content: space-between;
align-items: center;
.picker_wrap {
display: flex;
flex: 5;
.addr_ma_txt {
margin-right: 20rpx;
}
picker {
width: 70%;
}
.default_picker {
color: #acacac;
}
}
.addr_ma_icon {
font-size: 30rpx;
color: #acacac;
}
}
}
.submit_btn_wrap {
margin-top: 20rpx;
padding: 0 20rpx;
width: 100%;
button {
font-weight: normal;
width: 100% !important;
margin-top: 20rpx;
}
}
app.js
// app.js
App({
onLaunch() {
// 将是否iphoneX 信息缓存到全局公众数据中
this.globalData.isIphoneX = this.isIphoneX()
},
// iphoneX兼容 有刘海屏
isIphoneX() {
let mobile = wx.getSystemInfoSync()
if (mobile.model.indexOf("iPhone X") >= 0) {
return true
} else {
return false
}
},
// 常用正则表达式集
regExps: {
email: /^[0-9a-zA-Z_]+@[0-9a-zA-Z_]+[\.]{1}[0-9a-zA-Z]+[\.]?[0-9a-zA-Z]+$/, //邮箱
mobile: /^(?:1\d{2})-?\d{5}(\d{3}|\*{3})$/, //手机号码
qq: /^[1-9][0-9]{4,9}$/, //QQ
befitName: /^[a-z0-9A-Z\u4e00-\u9fa5]+$/, //合适的用户名,中文,字母,数字
befitPwd: /^[a-z0-9A-Z_]+$/, //合适的用户名,字母,数字,下划线
allNumber: /^[0-9]+.?[0-9]$/ //全部为数字
},
// 获取上一页路由
getPage(index) {
const pages = getCurrentPages()
const prevPage = pages[pages.length - index]
return prevPage
},
globalData: {
isIphoneX: false
},
})