在 components 目录上鼠标右键,选择 新建组件,并填写组件相关的信息:

渲染收货地址组件的基本结构:
收货人:escook 电话:138XXXX5555 收货地址: 河北省邯郸市肥乡区xxx 河北省邯郸市肥乡区xxx 河北省邯郸市肥乡区xxx 河北省邯郸市肥乡区xxx
美化收货地址组件的样式:
// 底部边框线的样式
.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;}}
}
在 data 中定义收货地址的信息对象:
export default {data() {return {// 收货地址address: {},}},
}
使用 v-if 和 v-else 实现按需展示:
实现选择收货地址的功能
为 请选择收货地址+ 的 button 按钮绑定点击事件处理函数:
定义 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}}
}
chooseAddress() 方法 解决方案uni-app项目 在项目根目录中找到 manifest.json 文件,在左侧导航栏选择源码视图,找到mp-weixin 节点,在节点后面加上:(一定要注意在setting节点同级)
"requiredPrivateInfos": [
"getLocation",
"onLocationChange",
"startLocationUpdateBackground",
"chooseAddress"]
地理位置接口新增与相关流程调整 | 微信开放社区 (qq.com)

定义收货详细地址的计算属性:
computed: {// 收货详细地址的计算属性addstr() {if (!this.address.provinceName) return ''// 拼接 省,市,区,详细地址 的字符串并返回给用户return this.address.provinceName + this.address.cityName + this.address.countyName + this.address.detailInfo}
}
渲染收货地址区域的数据:
收货人:{{address.userName}} 电话:{{address.telNumber}} 收货地址: {{addstr}}

将 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/cartm_cart: moduleCart,// 挂载用户的 vuex 模块,访问路径为 m_userm_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},},
}
将 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: {},
}
将 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']),},
}
重新选择收货地址
为 class 类名为 address-info-box 的盒子绑定 click 事件处理函数如下:
解决收货地址授权失败的问题
地址改了 现在自动授权的
如果在选择收货地址的时候,用户点击了取消授权,则需要进行特殊的处理,否则用户将无法再次选择收货地址!
改造 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('您取消了地址授权!')}})
}

思想可以学习
解决 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()}
} 