vue:如何携带token发送请求获取用户信息(会穿插一些关于aysnc&await执行顺序、宏任务&微任务相关知识)
上一篇文章讲到了如何应用路由监听或组件重载让登录状态保持,这篇文章主要讲解如何携带token发送请求获取用户信息,会穿插一些关于aysnc&await执行顺序、宏任务&微任务相关知识,同时对一些在该过程中出现的bug进行分析。以上就是今天要讲的内容,下一篇该系列文章会将首页渲染完成,并开始处理详情页的渲染。
文章目录
一、前言
上一篇文章讲到了如何应用路由监听或组件重载让登录状态保持,这篇文章主要讲解如何携带token发送请求获取用户信息,会穿插一些关于aysnc&await执行顺序、宏任务&微任务相关知识,同时对一些在该过程中出现的bug进行分析。
二、携带token发送请求获取用户信息
1. 请求拦截器进行处理
登录状态能够持续保持后,我们还需要传递登录用户的token值给后端,获取每个用户的数据信息来进行渲染,该逻辑我们可以写在请求拦截器中。
因此,在请求拦截器request.js
中书写代码如下:
// 请求拦截器
instance.interceptors.request.use(config => {
// 什么时候执行这个函数? 发送请求之前
// config是什么? 记录了本地请求的相关信息的一个对象
// 这个函数能用来做什么? 做一些请求之前的操作(例如:添加请求头,例如token)
let token = localStorage.getItem("x-auth-token")
if (token) {
config.headers["x-auth-token"] = token
}
// console.log("执行了 请求拦截器的代码", config);
return config
}, err => {
return Promise.reject(err)
});
说明:
两个x-auth-token
,前一个是我们自定义保存的名字,后一部分是后端要求携带的(即接口文档中拟好的名字)。
localStorage相关语法:
localStorage.getItem(key):**获取**指定key本地存储的值; // 获取指定key 本地存储数据的值。
localStorage.setItem(key,value):将value**存储**到key字段; // 获取指定value 存储到key 字段
localStorage.removeItem(key):删除指定key本地存储的值; // 删除指定key 本地存储的值
2. 书写API及API引入、调用
常规操作,按接口文档中的要求在API.js
中写好接口:
//发起获取用户信息请求
export const GetUserInfoAPI = () => instance.get("/shop/userProfiles");
在TopBar.vue
中进行引入并调用(即最外层的else作用域内):
import { WeixinLoginAPI, GetUserInfoAPI } from "@/request/api";
created() {
setTimeout(async () => {
// console.log(this.$route.query.code);
let mycode = this.$route.query.code;
if (mycode) {
// 发起微信扫码登录请求
let res = await WeixinLoginAPI({
code: mycode,
});
console.log(res);
if (res.code == 0) {
// 登录成功的逻辑
this.asyncChanIsShowToast({
msg: "登录成功!",
type: "success",
});
// 保存token到localStorage
localStorage.setItem("x-auth-token", res["x-auth-token"]);
// 登录状态的切换 (用户的头像,昵称,购物车按钮,数量等)
this.chanIsLogined(true);
// 清除浏览器上的code
this.$router.push(this.$route.path);
//登录成功也要获取用户信息
this.asyncChanuserInfo();
} else if (res.code == 400) {
// code过期的逻辑:
// 1 提示用户进行 请重新进行扫码登录
this.asyncChanIsShowToast({
msg: "请重新扫码登录!",
type: "warning",
});
// 2 弹出登录框(打开登录的模态窗口)
this.chanIsShowLoginModal(true);
} else if (res.code == 407) {
// 返回407说明: 用户扫码的这个微信, 在这个网站上没有绑定手机号
// 我们需要: 让用户绑定手机到扫码的这个微信上
// 1 弹出提示框, 提示用户, 手机号登录进行绑定微信号
this.asyncChanIsShowToast({
msg: "请进行手机号登录绑定扫码的微信!",
type: "danger",
});
// 2 弹出登录框(打开登录的模态窗口)
this.chanIsShowLoginModal(true);
// 3 保存uuid(待会用户输入手机点击登录按钮的时候,发送登录请求需要携带uuid)
localStorage.setItem("uuid", res.uuid);
}
} else {
//购物车显示方法二:组件重载
//没有code的情况
//判断有没有token,来改变用户登陆状态
let mytoken = localStorage.getItem("x-auth-token");
this.chanIsLogined(Boolean(mytoken));
if (mytoken) {
let res = await GetUserInfoAPI();
console.log(res);
}
// if (mytoken) {
// this.asyncChanuserInfo();
// } else {
// this.initUserInfo();
// }
}
}, 100);
},
说明:
let res = await GetUserInfoAPI();
中await
的作用?
将异步代码写成同步的样式,同步的代码会更加的直观,执行顺序会更加明确。
对async await的说明:
https://zhuanlan.zhihu.com/p/361262290
async await执行顺序:
https://blog.csdn.net/sunny1660/article/details/103993743
(多熟悉一下打印顺序)
宏任务、微任务:
https://blog.csdn.net/qingbaicai/article/details/111273292
https://blog.csdn.net/qq_42736311/article/details/115795953
三、将用户信息保存在vuex中
除了TopBar.vue
要用到用户信息,个人中心、商品下的评论等各种功能点都要用到用户信息,因此最好将用户信息保存在vuex中作全局使用。
在store
下新建文件夹userInfo
,其下新建index.js
。
通关观察打印出来的res信息,我们发现需要保存的用户信息有:用户信息、购物车数量等等…
index.js
中的具体代码如下:
state: {
//接口文档中可以获取到的信息
userInfo: {
nickName: "游客",
coin: "--",
headImg: require("@/assets/img/userImg.f8bbec5e.png")
//注意:图片要加require当模块渲染,否则会被识别为字符串
// ../../可以改为@/
},
cartTotal: ""
},
并在总体的index.js
中引入:
import userInfo from "./userInfo"
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
showLoginModal, loginStatus, toastStatus, userInfo
}
})
为什么vue引入图片要用require?
require 是 node 中的一个方法,他的作用是 “用于引入模块、 JSON、或本地文件”。
也就是说如果我们使用 require 来引入一个图片文件的话,那么 require 返回的就是用于引入的图片(npm 运行之后图片的编译路径)。 而如果使用字符串的话,那么则是一个 string 类型的固定字符串路径。
我们知道,src 中引入的图片应该为图片的本身路径(相对路径或者绝对路径),而 vue 项目通过 webpack 的 devServer 运行之后,默认的 vue-cli 配置下,图片会被打包成 name.hash 的图片名,在这种情况下,如果我们使用固定的 字符串路径则无法找到该图片,所以需要使用 require 方法来返回 图片的编译路径。
简单的说,使用require定义之后,你就可以动态**使用了,不用require你就只能写死的。**不用的话, :src=“’…/img/image.jpg’” 会被解析为字符串。
————————————————
参考自:https://blog.csdn.net/qq_42931285/article/details/125735283
四、将静态页面中需要渲染的信息改为插槽
1. 在TopBar.vue中使用…mapstate进行解析
computed: {
...mapState({
isLogined: (state) => state.loginStatus.isLogined,
userInfo: (state) => state.userInfo.userInfo,
cartTotal: (state) => state.userInfo.cartTotal,
}),
},
2. 书写插槽
<div class="top-bar">
<div class="wrap">
<div class="l">欢迎来到叩丁狼积分商城</div>
<div class="r">
<ul>
<li @click="hdClick">
<img width="26" src="../assets/img/userImg.f8bbec5e.png" alt="" />
用户名:{{ userInfo.nickName }}
</li>
<li>我的积分:{{ userInfo.coin }}</li>
<li>获取积分</li>
<li>叩丁狼官网</li>
<li v-show="!isLogined" class="login-btn" @click="showModal">登录</li>
<li v-show="isLogined" class="cart-btn">
<img src="../assets/img/cart.png" alt="" />
<span>{{ cartTotal }}</span>
<b>10</b>
</li>
</ul>
</div>
</div>
</div>
五、实时更新用户数据
更改vuex的store中的状态的唯一方法是提交mutations,调用实时更改数据的方法,则要放在actions中。
Action 类似于 mutation,不同在于:
-
Action 提交的是 mutation,而不是直接变更状态。
-
Action 可以包含任意异步操作。
action函数的参数:
setMenustate ({ commit }, value) {
commit(types.SET_MENUSTATE, value)
}
因此,经过分析后,在userInfo
中的index.js
书写如下代码:
import { GetUserInfoAPI } from "@/request/api"
export default {
namespaced: true,
state: {
//接口文档中可以获取到的信息
userInfo: {
nickName: "游客",
coin: "--",
headImg: require("@/assets/img/userImg.f8bbec5e.png")
},
cartTotal: ""
},
getters: {
},
mutations: {
chanuserInfo(state, payload) {
// state.userInfo = payload.userInfo;
// state.cartTotal = payload.cartTotal;
//不知道是否是没有登录的原因,不注释这两行代码会报错
},
},
actions: {
async asyncChanuserInfo({ commit }) {
let res = await GetUserInfoAPI();
console.log(res)
// commit("chanuserInfo", {
// userInfo: res.data.userInfo,
// cartTotal: res.data.cartTotal
//console.log后发现,我们要寻找的数据在res.data中
// })
//优化后代码如下:
//第二个参数的值给到payload
commit("chanuserInfo", res.data)
}
},
}
说明:
commit的格式:context.commit(‘方法名’,‘参数’)),console.log后发现,我们要寻找的数据在res.data中,因此可以将代码优化为 commit("chanuserInfo", res.data)
,第二个参数的值给到payload。
并在Topbar.vue
中应用...mapActions
进行解析
...mapMutations({
chanIsShowLoginModal: "showLoginModal/chanIsShowLoginModal",
chanIsLogined: "loginStatus/chanIsLogined",
initUserInfo: "userInfo/initUserInfo",
}),
在需要接收用户信息的2处地方(手机登录成功、微信登录成功)调用this.asyncChanuserInfo()
即可。
六、删除token后组件重载初始化用户信息
在没有token的情况下,要把属性的值修改为原来的属性,则需要修改vuex中的cartTotal
和userInfo
。
修改state中的值,需要调用方法,故写在mutations
中。
initUserInfo(state) {
state.userInfo = {
nickName: "游客",
coin: "--",
headImg: require("@/assets/img/userImg.f8bbec5e.png")
},
state.cartTotal = 0
}
说明:
这里的@是文件src的简写,我门可以用@来表示src文件。
在TopBar.vue
中用...mapMutations
解析改方法,并在需要的地方调用:
...mapMutations({
chanIsShowLoginModal: "showLoginModal/chanIsShowLoginModal",
chanIsLogined: "loginStatus/chanIsLogined",
initUserInfo: "userInfo/initUserInfo",
}),
if (mytoken) {
let res = await GetUserInfoAPI();
console.log(res);
} else {
this.initUserInfo();
}
七、bug场景分析
登录成功后信息没渲染,怎么办?
首先,在network中查看需要的信息后端有没有发送。
如果network中的请求成功发送,说明代码没问题。
同时检查vuex中的数据是否变动。如果vuex的数据没有改变,说明改变数据的代码出问题。
如果vuex没问题,说明页面组件渲染出问题。
通过一步步排查来发现出错的点。
八、总结
以上就是今天要讲的内容,下一篇该系列文章会将首页渲染完成,并开始处理详情页的渲染。最近还会开始整理一些js高级的知识点及算法题,那么感谢看到这里的你~
更多推荐
所有评论(0)