2. 定义 chooseAddress 事件处理函数,调用小程序提供的 chooseAddress() API 实现选择收货地址的功能:
methods: { async chooseAddress() { // 这个是调用地理位置的封装方法: 返回的结果是,第一个是错误信息,第二个是成功的结果 const [err, succ] = await uni.chooseAddress().catch(err => err); if (err === null && succ.errMsg === "chooseAddress:ok") { // 加入说err为空且errMsg为chooseAddress:ok。 console.log(succ) // 赋值到我们的address this.address = succ } } }
- 定义收货详细地址的计算属性:
computed: { // 收货详细地址的计算属性 addstr() { // 字符串为空布尔值为false 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>
(4).将 address 信息存储到 vuex 中
- 在
store
目录中,创建用户相关的vuex
模块,命名为user.js
1. 创建js文件 (1).export default{} (2).定义命名空间 (3).state()=>({}) (4).mutations:{} (5).getters:{} 2. 引入到store.js (1). import {moduleUser} from "@/store/user.js" (2). 'm_user': moduleUser 3. 引入到main.js (1).import store from "@/store/store.js" (2).const app = new Vue({ ...App,store})
user.js
import {} from "vuex" export default { // 开启命名空间 namespaced: true, // 数据 state: () => ({ address: {} }), // 方法 mutations: { // 更新收获地址 updateAddress(state, address) { state.address = address } }, getters: { } }
store.js
切记: 引入的时候不要带花括号,否则会失败
// 1. 导入 Vue 和 Vuex import Vue from 'vue' import Vuex from 'vuex' import moduleCart from '@/store/cart.js' import moduleUser from "@/store/user.js" // 2. 将 Vuex 安装为 Vue 的插件 Vue.use(Vuex) // 3. 创建 Store 的实例对象 const store = new Vuex.Store({ // TODO:挂载 store 模块 modules: { 'm_cart': moduleCart, 'm_user': moduleUser }, }) // 4. 向外共享 Store 的实例对象 export default store
main.js
// #ifndef VUE3 import Vue from 'vue' import App from './App' // 创建store import store from "@/store/store.js" // 1.导入网络请求的包 import { $http } from '@escook/request-miniprogram' // 2.在 uni-app 项目中,可以把 $http 挂载到 uni 顶级对象之上,方便全局调用 uni.$http = $http // ⭐ 设置根路径目的是为了防止 网址混乱 $http.baseUrl = 'https://api-hmugo-web.itheima.net' // 3.请求开始之前做一些事情 (请求拦截器) $http.beforeRequest = function(options) { // do somethimg... uni.showLoading({ title: '数据加载中...' }) } // 4.请求完成之后做一些事情 (响应拦截器) $http.afterRequest = function() { // do something... uni.hideLoading() } // 封装的展示消息提示的方法 uni.$showMsg = function(title = '数据加载失败!', duration = 1500) { uni.showToast({ title, duration, icon: 'success', }) } Vue.config.productionTip = false App.mpType = 'app' const app = new Vue({ ...App, store }) app.$mount() // #endif // #ifdef VUE3 import { createSSRApp } from 'vue' import App from './App.vue' export function createApp() { const app = createSSRApp(App) return { app } } // #endif
- 改造
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 }, }, }
(5).将 Store 中的 address 持久化存储到本地
user.js
export default { // 开启命名空间 namespaced: true, // 数据 state: () => ({ // 假如说左边的为空字符串(假)就执行右侧 address: JSON.parse(uni.getStorageSync('address') || '{}') }), // 方法 mutations: { // 更新收获地址 updateAddress(state, item) { state.address = item // 2. 通过 this.commit() 方法,调用 m_user 模块下的 saveAddressToStorage 方法将 address 对象持久化存储到本地 // 调用方法 ⭐⭐ this.commit('m_user/saveAddressToStorage') }, // 声明方法 ⭐ saveAddressToStorage(state) { uni.setStorageSync('address', JSON.stringify(state.address)) } }, getters: { }, }
(6).将 addstr 抽离为 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']), }, }
(7).重新选择收货地址
- 为 class 类名为 address-info-box 的盒子绑定 click 事件处理函数如下:
<!-- 渲染收货信息的盒子 --> <view class="address-info-box" v-else @click="chooseAddress"> <!-- 省略其它代码 --> </view>