目录
2.1 新建文件plugins/axios.js ,添加一下内容
本章任务:
- 退出登录功能
- 注册功能 表单布局 数据绑定 数据校验 更灵活的函数式校验 自定义一个校验函数 validator 提交请求 (验证码, 注册请求) form数据跟 api 要求不一致, 多了一个, 使用 ... 剩余参数语法进行提取
- axios的响应错误拦截
-
nuxt 封装的 axios 利用 nuxt 插件机制, 在 plugins 下面创建文件, 在 nuxt.config.js 里面配置
-
如果我们自己封装了一个原版的 axios 直接使用以前黑马头条用过的 http.interceptors.response.use
-
一 退出功能
思路: 我们现在的主要目标, 设置我们的 vuex 用户信息为空
之前我们已经做过一次设置用户信息的动作 登录成功那里
使用 commit 将获取回来的数据设定到 userInfo 里面
如果我们强制设置一个空对象, 其实就可以实现退出登录了
this.$store.commit('user/setUserInfo', { } )
二 注册功能
1. 思路
-
在
components/user
中新建RegisterForm.vue
表单组件 -
使用
Element-ui
的表单组件布局排版 -
表单数据绑定 v-model
-
要看一共有多少数据
-
参考最终 api 接口要求
-
-
表单验证
表单 model / rules
表单项 prop
第二次确认密码的验证方式(新方式)
-
发送手机验证码
-
注册接口对接 ajax
2. 实现步骤
2.1 新建注册表单组件
在components/user
中新建RegisterForm.vue
组件,新增内容如下
<template>
<el-form
:model="form"
ref="form"
:rules="rules"
class="form">
<el-form-item class="form-item">
<el-input
placeholder="用户名手机">
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="验证码" >
<template slot="append">
<el-button @click="handleSendCaptcha">
发送验证码
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="你的名字">
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="密码"
type="password"
></el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="确认密码"
type="password">
</el-input>
</el-form-item>
<el-button
class="submit"
type="primary"
@click="handleRegSubmit">
注册
</el-button>
</el-form>
</template>
<script>
export default {
data(){
return {
// 表单数据
form: {},
// 表单规则
rules: {},
}
},
methods: {
// 发送验证码
handleSendCaptcha(){
},
// 注册
handleRegSubmit(){
console.log(this.form)
}
}
}
</script>
<style scoped lang="less">
.form{
padding:25px;
}
.form-item{
margin-bottom:20px;
}
.form-text{
font-size:12px;
color:#409EFF;
text-align: right;
line-height: 1;
}
.submit{
width:100%;
margin-top:10px;
}
</style>
注意:新增了组件后在pages/user/login.vue
中导入即可
<!-- 注册功能组件 -->
<RegisterForm v-if="currentTab == 1"/>
2.2 表单数据绑定
修改data
的form
数据,然后使用v-model
绑定到对应的表单字段
编辑components/user/RegisterForm.vue
:
data(){
return {
// 表单数据
form: {
username: "", // 登录用户名/手机
password: "", // 登录密码
checkPassword: "", // 确认密码
nickname: "", // 昵称
captcha: "" // 手机验证码
},
// 其他代码...
}
},
使用v-model
绑定到对应的表单字段 :
<el-form-item class="form-item">
<el-input
placeholder="用户名手机"
v-model="form.username">
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="验证码"
v-model="form.captcha" >
//slot="append"插槽添加
<template slot="append">
<el-button @click="handleSendCaptcha">
发送验证码
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="你的名字"
v-model="form.nickname">
</el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="密码"
type="password"
v-model="form.password"
></el-input>
</el-form-item>
<el-form-item class="form-item">
<el-input
placeholder="确认密码"
type="password"
v-model="form.checkPassword">
</el-input>
</el-form-item>
2.3 表单验证
双向数据绑定到form
字段后,我们现在可以来提交表单了,但是提交之前还需要验证下表单字段是否合法,比如不能为空。
继续编辑components/user/RegisterForm.vue
:
data(){
//在data里面定义,只在这里需要使用,外面不需要则可以在这里面定义
//在return外面定义,这样return的这个对象里面才能访问到外面的这个数据
// 确认密码,rule验证规则,value表单输入的值
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.form.password) {
callback(new Error('两次输入密码不一致!'));
} else {
//放行
callback();
}
}
return {
// 其他代码...
// 表单规则
rules: {
username: [{
required: true,
message: '请输入用户名',
trigger: 'blur'
}],
password: [{
required: true,
message: '请输入密码',
trigger: 'blur'
}],
//确认密码 validator: validatePass, 可参考element-ui里面的form表单
checkPassword: [{
validator: validatePass,
trigger: 'blur'
}],
nickname: [{
required: true,
message: '请输入昵称',
trigger: 'blur'
}],
captcha: [{
required: true,
message: '请输入验证码',
trigger: 'blur'
}],
},
}
和登录组件一样,给el-form-item
添加对应的prop
属性。
2.4 发送手机验证码
components/user/RegisterForm.vue
:
// 发送验证码
handleSendCaptcha(){
if(!this.form.username){
this.$confirm('手机号码不能为空', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'warning'
})
return;
}
if(this.form.username.length !== 11){
this.$confirm('手机号码格式错误', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'warning'
})
return;
}
//发送请求
this.$axios({
url: `captchas`,
method: "POST",
data: {
tel: this.form.username
}
}).then(res => {
//相当于res.data.data
const {code} = res.data;
this.$confirm(`模拟手机验证码为:${code}`, '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'warning'
})
})
}
2.5 注册接口
提交数据到注册接口,返回数据和登录接口是一样的。
面的示例代码当中 使用了剩余参数/属性语法
// 注册
handleRegSubmit(){
this.$refs['form'].validate((valid) => {
//如果用户输入的所有表单内容验证成功valid为true
if (valid) {
// 注册提交
//把接口需要的参数 多余的 checkPassword 提取出来,剩下的...props 拿来作为参数发送请求
const {checkPassword, ...props} = this.form;
this.$axios({
url: `/accounts/register`,
method: "POST",
data: props
}).then(res => {
console.log(res.data);
})
}
});
},
2.6 注册成功后的 用户体验操作
- 可以直接自动登录
//注册成功 就有这个数据res.data
if (res.data) {
//1. 将数据存储到vuex中,注册成功自动登录
this.$store.commit("user/setUserInfo", res.data);
this.$message.success("注册成功");
this.$router.push("/");
}
- 或者跳转到登录页让用户登录 (推荐)
注册组件components/user/RegisterForm.vue
:触发自定义事件
if (res.data) {
// 2.跳到登录页,再登录
// 当前是在注册组件,需要跳到登录页面,就是切换父组件的tab栏
this.$message.success("注册成功");
//这个是注册表单组件,跟登录表单组件同属于login
//需要通知父组件
this.$emit("login");
}
父组件user/login.vue:父组件监听,切换到登录表单
<!-- 注册功能组件 -->
<!-- 注册的子组件发送的事件,需要在父组件 使用子组件的位置接收 -->
<registerForm v-if="currentTab == 1" @login="currentTab = 0" />
3.总结
注册和登录的步骤大致上是一样的,只是接口和参数的区别,
注册表单功能实现中的重点, 自定义表单校验函数
发送请求时剩余参数用来筛选需要提交的数据
三 错误拦截
目标: 使用axios
的拦截器拦截页面的所有请求错误,并弹出对应的提示。
原版的 axios 写法是: axios.interceptors.response.use(回调函数)
1.nuxt 的插件机制
以前的拦截器都放在 main.js 入口文件当中
引入 axios 之后, 创建 vue 实例之前
nuxt 当中没有 main.js, 如何在 创建 vue 根实例之前执行某些代码
靠插件机制
其实所有在 nuxt.config.js 的 plugins 数组里面配置了路径的文件都会在 vuejs 之前执行, 相当于以前 main.js 入口文件
建议这些插件都放在 plugins 文件夹下方
2.新建axios拦截错误插件插件
这个拦截器是供 nuxt 封装的 @nuxtjs/axios 使用的
2.1 新建文件plugins/axios.js ,添加一下内容
/ 如果在插件里面需要获取到 nuxt 本身
// 需要 export default
//需要单独引入
import { Message } from 'element-ui';
export default function ({ $axios, redirect }) {
// $axios.onError 是一个 nuxt 提供的辅助拦截器函数
// 里面可以拦截到错误
$axios.onError(err => {
// 这里是每当出错的时候都会被拦截
console.log(err);
// 这个 err 是一个错误对象, log 的时候看不出来有什么用
// 用 dir 可以看到里面的内容
console.dir(err);
console.log('错误信息是: ' + err.response.data.message);
// 弹出一个提示告诉用户
// this.$message.error('') 在这里由于不是组件内部, 没有 this 可以用
// 可以单独引入element ui 当中的 Message 组件
Message.error(err.response.data.message || '系统错误')
// 如果需要跳转页面, 比如说需要跳转到登录页
// 可以从 nuxt 中拿到 redirect 函数即可
// redirect('/user/login')
})
}
2.2 调用插件
就是配置一下 nuxt.config.js:
// 其他代码...
plugins: [
'@/plugins/element-ui',
{ src: '@/plugins/localStorage', ssr: false },
'@/plugins/axios' // 调用插件
],
// 其他代码...
3.小结
创建 axios 响应拦截插件的步骤
-
创建文件
-
在nuxt.config.js 配置引入文件
-
在插件文件当中 暴露一个函数, 这个函数会被 nuxt 自动触发, 并且可以获得 整个nuxt 对象作为参数
-
通过解构, 取得 $axios 之后就可以创建拦截器了
-
nuxt axios 插件 提供了一个方便的函数进行拦截器创建 onError
-
在里面进行判断并且弹窗等操作
4.补充:使用原版 axios 封装时的拦截器写法
在utils/http.js 中封装:
/ 创建一个 axios
import axios from 'axios'
const http = axios.create({
baseURL: 'http://157.122.54.189:9095'
})
import { Message } from 'element-ui'
// 添加响应拦截器
http.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response
}, function (error) {
// 对响应错误做点什么
console.dir(error)
Message.warning(error.response.data.message || '系统错误')
})
// 暴露
export default http
5.拦截器封装的作用
-
不封装, 功能依旧可以实现
-
如果需要错误弹窗每个页面请求都要做一遍
-
可以通过统一的拦截, 判断到有错误, 就弹窗
-
接口写的时候就只需要关注成功逻辑即可