项目Demo步骤(记录)

262 阅读3分钟

一、登录模块

代码步骤:

1.表单验证

在Login->index.vue中 进行表单验证---修改data数据中username(根据接口文档命名),同时在src->utils->validate.js中修改手机号正则。

2.发送请求:

在rc->utils->request.js下,导入axios,设置基地址,导出axios实例,在src->api下的user.js页面中,发送请求并封装成函数。最后在src->views->login下的index.vue中 导入login函数,并在methods中调用函数,这里注意:可以进行二次封装,定义一个新函数doLogin,用于接收axios返回值,在新函数doLogin中调用

3.存储token:

在vuex中state中定义token变量(可读),在mutations中声明函数,注意:mutations函数可以修改state中的数据。然后在doLogin函数中通过this.$store.commit('user/getToken',res.data)传值,因为开启了命名空间,所以需要添加模块名/user

4.环境变量

在.env.development文件中,通过port= xxxx 可以修改端口号,也可以自定义设置接口,通过变量名 = 地址方式 VUE_APP_BASE_API = '/dev-api' 变量命名建议以VUE_APP为主,在src->utils->request.js文件中 ,通过process.env.VUE_APP_BASE_API 设置基地址

5.跨域

跨域出现是因为,协议、域名、端口号不一致时,而后端没有进行处理时,会出现的问题,解决方式一般为添加一个代理服务器,在vue.config.js文件中 的devServer下面添加代理服务器

6.添加请求拦截器

在src->utils->request.js文件中,通过axios官网C一份请求拦截器的代码,在发送请求之前,添加请求头Token,根据接口文档中的Authorization的格式来存储token,因为没有开启持久化,所以刷新token还是会没有,这个我们后面会做

7.添加响应拦截器

通过响应而来的数据的message的值进行判断,如果判断不通过,则抛出一个错误,而这个错误,可以通过doLogin函数的catch中的err来捕获,反之则返回一个去壳的对象,包含(token,success)等参数

8.持久化token

在src->utils->auth.js文件中,导入js-cookie,自定义token名,定义存储token、取出token、移除token三种函数,在mutations函数中导入并调用。

二、主页模块

代码步骤

1、模块化处理

在login下面的index.vue文件中,将获取用户档案信息发送请求提取在store->modules->user.js文件中的actions中,声明一个函数userLogin,将index.vue文件中的参数通过this.$store.dipatch(模块名/函数,参数)传递过来,通过userLogin函数里两个参数,context.commit进行调用mutations进行调用,在state里进行存储token,obj用于接收表单数据。

2、路由导航守卫-两个页面跳转

在src->permission.js文件中,声明一个路由守卫,beforeEach,将token拿过来进行判断,有token不让去登录页,其他页面放行,反之相反,考虑后面不止一个页面,所以定义白名单数组,用于路径地址判断,在条件判断中,通过数组.includes()方法进行筛选。

import router from './router'
import store from './store'import NProgress from 'nprogress' // progress bar  // 下载导入进度条包
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false }) // NProgress Configuration  // 取消转圈圈const whiteList = ['/login','/404']  // 存储路径的白名单数据
​
router.beforeEach( async (to,from,next)=>{
  // console.log(to.path);//去哪里
  // console.log(from.path)// 来自哪里
  // next()// 放行
  // console.log(store);
  NProgress.start() // 开启进度条
  const token = store.state.user.token
  if(token){
    // 有token
    if(to.path === '/login'){
      next('/')
      NProgress.done() // 结束进度条
    } else {
      // 跳转首页
      // 这里actions函数是异步操作,所以需要async,await修饰
     await store.dispatch('user/getuserProfile')
      next()
    }
  } else {
    // 没有token
    if(whiteList.includes(to.path)){
      // 数组.includes方法进行筛选有没有,有则true,反之false
      next()
    } else {
      next('/login')
      NProgress.done() // 结束进度条
    }
  }
})
​
// 路由跳转之后
router.afterEach((to,from)=>{
  NProgress.done() // 结束进度条
})
​

3、修改样式---见资料

image-20220606105250192.png

4、显示用户名---分析

在api->user.js文件中封装一个获取用户信息的请求(需要传id),在store->user.js文件中的 mutations中,声明一个用于存用户信息的函数,通过actions进行调用,将用户档案信息中的id传给axios请求,获得用户信息,在通过对象...方式,保存完整的用户信息资料,最后在src->components->Navbar.vue中显示用户名和图片(插值表达式和: $store.state.user.userInfo.XXXX)

 mutations: {
    // 1.定义函数,通过mutations修改state里的值
    setToken(state,newToken) {
      state.token = newToken
      // 2. token持久化处理
        setToken(newToken)
    },
    // 存用户信息
    setUserInfo(state,newUserInfo){
      state.userInfo = newUserInfo
    }
  },
  actions:{
  async getuserProfile(context){
       const {data:res} = await userProfile()
      //  console.log(res)
      // 通过context.commit方法调用,修改mutations函数里的token值
      // console.log(res);
      // 2.获取用户信息函数---需要传入参数
      const {data:resInfo} = await userInfo(res.userId)
      // console.log(resInfo.data);
      const obj = {...res,...resInfo}
      // 将用户信息传过去
      context.commit('setUserInfo',obj)
     },
  }

5、实现用户退出

image-20220606111041334.png

store/modules/user.js中,补充一个action

 // 3.定义函数,用于清空token,用户信息
     logout(context) {
      context.commit('setUserInfo',{})
      context.commit('setToken','')
     }

在Navbar.vue文件中,通过定义函数logout(){{}.then()}方法,进行退出,退出时要清空用户信息和token,实现页面跳转。可以使用thiis.store.dispatch()进行清空,this.store.dispatch()进行清空,this.router.push()进行路径跳转

logout() {
      this.$confirm('你确定要离开吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then( async ()=>{
        // 1.清除token、清空用户信息
        await this.$store.dispatch('user/logout')
        // 2.跳转到首页(登录页)------跳转到上次退出时的页面,通过地址拼接
        //  是js的内置API,用来对url进行编码,可以携带地址后面的所以参数,并转译
        this.$router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))
      })
    }

6、退出再进入能回到原来的页面

1.登录成功之后,进入指定的目标页面(不要每次都进入主页)

2.用户退出,跳入登录页时,携带目标页面地址告诉登录页

在scr->login->index.vue中,在点击登录的函数中doLogin(){},定义一个路径

async doLogin() {
      try {
        // 在组件中调用带命名空间的action
​
        // dispatch是异步的,需要加async await
        await this.$store.dispatch('user/userLogin', this.loginForm)
        // 登录成功,路由跳转
+        this.$router.push(this.$route.query.return_url || '/')
      } catch (err) {
        alert('用户登录,失败')
        console.log('用户登录,失败', err)
      }
    },

在点击退出时,在Navbar.vue文件中,在退出登录时,添加

//跳转到首页(登录页)------跳转到上次退出时的页面,通过地址拼接
//是js的内置API,用来对url进行编码,可以携带地址后面的所以参数,并转译
this.$router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))

7.token失效处理

image-20220606112458881.png

在src->request.js中,通过响应拦截器的error,进行状态码判断,可以通过console.dir来获取错误对象,从而清空用户信息,跳转页面。

// 添加响应拦截器
service.interceptors.response.use(function (response) {
   // 对响应数据做点什么
  //  console.log(response);
   // 如果响应过来的数据等于false,则抛出promise错误对象信息
   if(response.data.success === false) {
     return Promise.reject(response.data.message);
   }
   // 反之返回成功数据(通过response.data处理脱壳--在调用时,可以简写一些)
   return response.data;
}, function (error) {
  // console.dir(error)
  if(error.response.data.code === 10002){
    // 1.清除token,
    store.dispatch('user/logout')
    // 2.跳转页面
    router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))
  }
   // 对响应错误做点什么
   return Promise.reject(error);
});

\