闲云旅游项目开发-(第三篇:实现注册功能/发送验证码/使用vuex的store管理数据/nuxt错误拦截/剩余参数(属性语法))

5 篇文章 0 订阅
5 篇文章 0 订阅

目录

一 退出功能

二 注册功能

        1. 思路

2. 实现步骤

2.1 新建注册表单组件

2.2 表单数据绑定

2.3 表单验证

2.4 发送手机验证码

2.5 注册接口

2.6 注册成功后的 用户体验操作

3.总结

三 错误拦截

1.nuxt 的插件机制

 

2.新建axios拦截错误插件插件

2.1 新建文件plugins/axios.js ,添加一下内容

2.2 调用插件

3.小结

4.补充:使用原版 axios 封装时的拦截器写法

 

5.拦截器封装的作用


本章任务:

  • 退出登录功能
  • 注册功能 表单布局 数据绑定 数据校验 更灵活的函数式校验 自定义一个校验函数 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. 思路

  1. components/user中新建RegisterForm.vue表单组件

  2. 使用Element-ui的表单组件布局排版

  3. 表单数据绑定 v-model

    1. 要看一共有多少数据

    2. 参考最终 api 接口要求

  4. 表单验证

    表单 model / rules

    表单项 prop

    第二次确认密码的验证方式(新方式)

  5. 发送手机验证码

  6. 注册接口对接 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 表单数据绑定

修改dataform数据,然后使用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 响应拦截插件的步骤

  1. 创建文件

  2. 在nuxt.config.js 配置引入文件

  3. 在插件文件当中 暴露一个函数, 这个函数会被 nuxt 自动触发, 并且可以获得 整个nuxt 对象作为参数

  4. 通过解构, 取得 $axios 之后就可以创建拦截器了

  5. nuxt axios 插件 提供了一个方便的函数进行拦截器创建 onError

  6. 在里面进行判断并且弹窗等操作

 

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.拦截器封装的作用

  • 不封装, 功能依旧可以实现

  • 如果需要错误弹窗每个页面请求都要做一遍

  • 可以通过统一的拦截, 判断到有错误, 就弹窗

  • 接口写的时候就只需要关注成功逻辑即可

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值