个人名片:
🐼作者简介:一名大二在校生,讨厌编程🎋
🐻❄️个人主页🥇:小新爱学习.
🐼个人WeChat:见文末
🕊️系列专栏:🖼️
- 零基础学Java——小白入门必备
- 重识C语言——复习回顾
- 计算机网络体系———深度详讲
- 微信小程序开发——实战开发
- 基于黑马优选的小程序开发实战教程
🐓每日一句:🍭努力的意义是给所爱之人一个美好的未来!
文章目录
- 🌴9.2 收货地址区域
- ☘️9.2.1 创建收货地址组件
- ☘️9.2.2 实现收货地址区域的按需展示
- ☘️9.2.3 实现选择收货地址的功能
- ☘️9.2.4 将 address 信息存储到 vuex 中
- ☘️9.2.5 将 Store 中的 address 持久化存储到本地
- ☘️9.2.6 将 addstr 抽离为 getters
- ☘️9.2.7 重新选择收货地址
- ☘️9.2.8 解决收货地址授权失败的问题
- ☘️9.2.9 解决 iPhone 真机上无法重新授权的问题
🌴9.2 收货地址区域
☘️9.2.1 创建收货地址组件
- 在
components
目录上鼠标右键,选择 新建组件,并填写组件相关的信息:
- 渲染收货地址组件的基本结构:
<view>
<!-- 选择收货地址的盒子 -->
<view class="address-choose-box">
<button type="primary" size="mini" class="btnChooseAddress">请选择收货地址+</button>
</view>
<!-- 渲染收货信息的盒子 -->
<view class="address-info-box">
<view class="row1">
<view class="row1-left">
<view class="username">收货人:<text>escook</text></view>
</view>
<view class="row1-right">
<view class="phone">电话:<text>158XXXX1234</text></view>
<uni-icons type="arrowright" size="16"></uni-icons>
</view>
</view>
<view class="row2">
<view class="row2-left">收货地址:</view>
<view class="row2-right">地址地址地址xxx xx省xx市xx区xxx xx
省xx市xx区xxx xx省xx市xx区xxx </view>
</view>
</view>
<!-- 底部的边框线 -->
<image src="/static/cart_border@2x.png" class="address-border"></image>
</view>
- 美化收货地址组件的样式:
// 底部边框线的样式
.address-border {
display: block;
width: 100%;
height: 5px;
}
// 选择收货地址的盒子
.address-choose-box {
height: 90px;
display: flex;
align-items: center;
justify-content: center;
}
// 渲染收货信息的盒子
.address-info-box {
font-size: 12px;
height: 90px;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 5px;
// 第一行
.row1 {
display: flex;
justify-content: space-between;
.row1-right {
display: flex;
align-items: center;
.phone {
margin-right: 5px;
}
}
}
// 第二行
.row2 {
display: flex;
align-items: center;
margin-top: 10px;
.row2-left {
white-space: nowrap;
}
}
}
☘️9.2.2 实现收货地址区域的按需展示
- 在
data
中定义收货地址的信息对象:
export default {
data() {
return {
// 收货地址
address: {},
}
},
}
- 使用
v-if
和v-else
实现按需展示:
<!-- 选择收货地址的盒子 -->
<view class="address-choose-box" v-if="JSON.stringify(address) === '{}'">
<button type="primary" size="mini" class="btnChooseAddress">请选择收货地址+</button>
</view>
<!-- 渲染收货信息的盒子 -->
<view class="address-info-box" v-else>
<!-- 省略其它代码 -->
</view>
☘️9.2.3 实现选择收货地址的功能
- 为
请选择收货地址+
的button
按钮绑定点击事件处理函数:
<!-- 选择收货地址的盒子 -->
<view class="address-choose-box" v-if="JSON.stringify(address) === '{}'">
<button type="primary" size="mini" class="btnChooseAddress" @click="chooseAddress">请选择收货地址+</button>
</view>
- 定义
chooseAddress
事件处理函数,调用小程序提供的chooseAddress()
API
实现选择收货地址的功能:
methods: {
// 选择收货地址
async chooseAddress() {
// 1. 调用小程序提供的 chooseAddress() 方法,即可使用选择收货地址的功能
// 返回值是一个数组:第 1 项为错误对象;第 2 项为成功之后的收货地址对象
const [err, succ] = await uni.chooseAddress().catch(err => err)
// 2. 用户成功的选择了收货地址
if (err === null && succ.errMsg === 'chooseAddress:ok') {
// 为 data 里面的收货地址对象赋值
this.address = succ
}
}
}
- 定义收货详细地址的计算属性:
computed: {
// 收货详细地址的计算属性
addstr() {
if (!this.address.provinceName) return ''
// 拼接 省,市,区,详细地址 的字符串并返回给用户
return this.address.provinceName + this.address.cityName + this.address.countyName + this.address.detailInfo
}
}
- 渲染收货地址区域的数据:
<!-- 渲染收货信息的盒子 -->
<view class="address-info-box" v-else>
<view class="row1">
<view class="row1-left">
<view class="username">收货人:<text>{{address.userName}}</text></view>
</view>
<view class="row1-right">
<view class="phone">电话:<text>{{address.telNumber}}</text></view>
<uni-icons type="arrowright" size="16"></uni-icons>
</view>
</view>
<view class="row2">
<view class="row2-left">收货地址:</view>
<view class="row2-right">{{addstr}}</view>
</view>
</view>
☘️9.2.4 将 address 信息存储到 vuex 中
- 在
store
目录中,创建用户相关的vuex
模块,命名为user.js
:
export default {
// 开启命名空间
namespaced: true,
// state 数据
state: () => ({
// 收货地址
address: {},
}),
// 方法
mutations: {
// 更新收货地址
updateAddress(state, address) {
state.address = address
},
},
// 数据包装器
getters: {},
}
- 在
store/store.js
模块中,导入并挂载user.js
模块:
// 1. 导入 Vue 和 Vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 导入购物车的 vuex 模块
import moduleCart from './cart.js'
// 导入用户的 vuex 模块
import moduleUser from './user.js'
// 2. 将 Vuex 安装为 Vue 的插件
Vue.use(Vuex)
// 3. 创建 Store 的实例对象
const store = new Vuex.Store({
// TODO:挂载 store 模块
modules: {
// 挂载购物车的 vuex 模块,模块内成员的访问路径被调整为 m_cart,例如:
// 购物车模块中 cart 数组的访问路径是 m_cart/cart
m_cart: moduleCart,
// 挂载用户的 vuex 模块,访问路径为 m_user
m_user: moduleUser,
},
})
// 4. 向外共享 Store 的实例对象
export default store
- 改造
address.vue
组件中的代码,使用vuex
提供的address
计算属性 替代data
中定义的本地address
对象:
// 1. 按需导入 mapState 和 mapMutations 这两个辅助函数
import { mapState, mapMutations } from 'vuex'
export default {
data() {
return {
// 2.1 注释掉下面的 address 对象,使用 2.2 中的代码替代之
// address: {}
}
},
methods: {
// 3.1 把 m_user 模块中的 updateAddress 函数映射到当前组件
...mapMutations('m_user', ['updateAddress']),
// 选择收货地址
async chooseAddress() {
const [err, succ] = await uni.chooseAddress().catch((err) => err)
// 用户成功的选择了收货地址
if (err === null && succ.errMsg === 'chooseAddress:ok') {
// 3.2 把下面这行代码注释掉,使用 3.3 中的代码替代之
// this.address = succ
// 3.3 调用 Store 中提供的 updateAddress 方法,将 address 保存到 Store 里面
this.updateAddress(succ)
}
},
},
computed: {
// 2.2 把 m_user 模块中的 address 对象映射当前组件中使用,代替 data 中 address 对象
...mapState('m_user', ['address']),
// 收货详细地址的计算属性
addstr() {
if (!this.address.provinceName) return ''
// 拼接 省,市,区,详细地址 的字符串并返回给用户
return this.address.provinceName + this.address.cityName + this.address.countyName + this.address.detailInfo
},
},
}
☘️9.2.5 将 Store 中的 address 持久化存储到本地
- 修改
store/user.js
模块中的代码如下:
export default {
// 开启命名空间
namespaced: true,
// state 数据
state: () => ({
// 3. 读取本地的收货地址数据,初始化 address 对象
address: JSON.parse(uni.getStorageSync('address') || '{}'),
}),
// 方法
mutations: {
// 更新收货地址
updateAddress(state, address) {
state.address = address
// 2. 通过 this.commit() 方法,调用 m_user 模块下的 saveAddressToStorage 方法将 address 对象持久化存储到本地
this.commit('m_user/saveAddressToStorage')
},
// 1. 定义将 address 持久化存储到本地 mutations 方法
saveAddressToStorage(state) {
uni.setStorageSync('address', JSON.stringify(state.address))
},
},
// 数据包装器
getters: {},
}
☘️9.2.6 将 addstr 抽离为 getters
目的:为了提高代码的复用性,可以把收货的详细地址抽离为 getters,方便在多个页面和组件之间实现复用。
- 剪切
my-address.vue
组件中的addstr
计算属性的代码,粘贴到user.js
模块中,作为一个getters
节点:
// 数据包装器
getters: {
// 收货详细地址的计算属性
addstr(state) {
if (!state.address.provinceName) return ''
// 拼接 省,市,区,详细地址 的字符串并返回给用户
return state.address.provinceName + state.address.cityName + state.address.countyName + state.address.detailInfo
}
}
- 改造
my-address.vue
组件中的代码,通过mapGetters
辅助函数,将m_user
模块中的addstr
映射到当前组件中使用:
// 按需导入 mapGetters 辅助函数
import { mapState, mapMutations, mapGetters } from 'vuex'
export default {
// 省略其它代码
computed: {
...mapState('m_user', ['address']),
// 将 m_user 模块中的 addstr 映射到当前组件中使用
...mapGetters('m_user', ['addstr']),
},
}
☘️9.2.7 重新选择收货地址
- 为
class
类名为address-info-box
的盒子绑定click
事件处理函数如下:
<!-- 渲染收货信息的盒子 -->
<view class="address-info-box" v-else @click="chooseAddress">
<!-- 省略其它代码 -->
</view>
☘️9.2.8 解决收货地址授权失败的问题
如果在选择收货地址的时候,用户点击了取消授权,则需要进行特殊的处理,否则用户将无法再次选择收货地址!
- 改造
chooseAddress
方法如下:
// 选择收货地址
async chooseAddress() {
// 1. 调用小程序提供的 chooseAddress() 方法,即可使用选择收货地址的功能
// 返回值是一个数组:第1项为错误对象;第2项为成功之后的收货地址对象
const [err, succ] = await uni.chooseAddress().catch(err => err)
// 2. 用户成功的选择了收货地址
if (succ && succ.errMsg === 'chooseAddress:ok') {
// 更新 vuex 中的收货地址
this.updateAddress(succ)
}
// 3. 用户没有授权
if (err && err.errMsg === 'chooseAddress:fail auth deny') {
this.reAuth() // 调用 this.reAuth() 方法,向用户重新发起授权申请
}
}
- 在
methods
节点中声明reAuth
方法如下:
// 调用此方法,重新发起收货地址的授权
async reAuth() {
// 3.1 提示用户对地址进行授权
const [err2, confirmResult] = await uni.showModal({
content: '检测到您没打开地址权限,是否去设置打开?',
confirmText: "确认",
cancelText: "取消",
})
// 3.2 如果弹框异常,则直接退出
if (err2) return
// 3.3 如果用户点击了 “取消” 按钮,则提示用户 “您取消了地址授权!”
if (confirmResult.cancel) return uni.$showMsg('您取消了地址授权!')
// 3.4 如果用户点击了 “确认” 按钮,则调用 uni.openSetting() 方法进入授权页面,让用户重新进行授权
if (confirmResult.confirm) return uni.openSetting({
// 3.4.1 授权结束,需要对授权的结果做进一步判断
success: (settingResult) => {
// 3.4.2 地址授权的值等于 true,提示用户 “授权成功”
if (settingResult.authSetting['scope.address']) return uni.$showMsg('授权成功!请选择地址')
// 3.4.3 地址授权的值等于 false,提示用户 “您取消了地址授权”
if (!settingResult.authSetting['scope.address']) return uni.$showMsg('您取消了地址授权!')
}
})
}
☘️9.2.9 解决 iPhone 真机上无法重新授权的问题
问题说明:在
iPhone
设备上,当用户取消授权之后,再次点击选择收货地址按钮的时候,无法弹出授权的提示框!
-
导致问题的原因 - 用户取消授权后,再次点击
“选择收货地址”
按钮的时候:-
在模拟器和安卓真机上,错误消息
err.errMsg
的值为chooseAddress:fail auth
deny
-
在
iPhone
真机上,错误消息err.errMsg
的值为chooseAddress:fail authorize
no response
-
-
解决问题的方案 - 修改
chooseAddress
方法中的代码,进一步完善用户没有授权时的 if 判断条件即可:
async chooseAddress() {
// 1. 调用小程序提供的 chooseAddress() 方法,即可使用选择收货地址的功能
// 返回值是一个数组:第1项为错误对象;第2项为成功之后的收货地址对象
const [err, succ] = await uni.chooseAddress().catch(err => err)
// 2. 用户成功的选择了收货地址
if (succ && succ.errMsg === 'chooseAddress:ok') {
this.updateAddress(succ)
}
// 3. 用户没有授权
if (err && (err.errMsg === 'chooseAddress:fail auth deny' || err.errMsg === 'chooseAddress:fail authorize no response')) {
this.reAuth()
}
}