vue2人力资源项目3主页

本文详细介绍了如何在Vue应用中使用路由前置和后置守卫进行权限验证,涉及token检查、白名单管理、登录状态下的用户信息获取以及表单验证流程,包括Vuex状态管理、axios请求和Vue组件交互。
摘要由CSDN通过智能技术生成

主页权限验证

前置守卫开启进度条,后置守卫关闭进度条

import router from '@/router'
import nProgress from 'nprogress'// 导入进度条(模板自带)
import 'nprogress/nprogress.css'// 导入进度条样式(模板自带)
// 前置守卫
// 到哪里,去哪里,做什么
router.beforeEach((to, from, next) => {
  // 开启进度条
  nProgress.start()
})

// 后置守卫
router.afterEach(() => {
  // 关闭进度条
  nProgress.done()
})

如果有token,如果跳转登录页面情况

// 前置守卫
// 到哪里,去哪里,做什么
router.beforeEach((to, from, next) => {
  // 开启进度条
  nProgress.start()
  if (// 存在token
    store.getters.token) {
    if (to.path === '/login') {
      // 跳转首页
      next('/')
    } else {
      next()// 到其他页面,放行
    }
  } else {
    // 没有token
    next()
  }
})

没有token

声明白名单

// 声明白名单
const whiteList = ['/login', '404']
// 到哪里,去哪里,做什么
router.beforeEach((to, from, next) => {
  // 开启进度条
  nProgress.start()
  if (// 存在token
    store.getters.token) {
    if (to.path === '/login') {
      // 跳转到主页
      next('/') // 中转到主页
      // next(地址)并没有执行后置守卫
      nProgress.done()
    } else {
      next()// 到其他页面,放行
    }
  } else {
    // 没有token
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login') // 中转到登录页
      nProgress.done()
    }
  }
})

总结

登录后获取用户资料

index.vue里有token的前提下调用action异步方法

  created() {
    // 调用action
    this.$store.dispatch('user/getUserInfo')
  }
}

store/user.js里存放action

1.先导入接口,并声明一个对象来存储用户基本资料状态

import { login,getUserInfo } from '@/api/user'
// 用来存放数据
const state = {
  token: getToken(),// 调用加括号,从缓存中读取初始值
  userInfo:{}//声明一个对象来存储用户基本资料状态
}

2.利用mutations修改userInfo的值

// 用来修改数据,要修改state里的数据,必须通过mutations
const mutations = {
  setToken(state, token) {
    state.token = token
    // 同步到缓存
    setToken(token)
  },
  removeToken() {
    // 删除vuex的token
    state.token = null
    removeToken()
  },
  setUserInfo(state,userInfo){
    state.userInfo = userInfo
  }
}

3.actions调用接口,获取数据并通过context提交给mutation

const actions = {
  // context上下文,传入参数
  async login(context, data) {
    console.log(data)
    // 点击调用登录接口,成功执行await后的内容
    const token = await login(data)
    // 提交mutations里的数据,调用context里的默认方法
    context.commit('setToken', token)
  },
  // action
  async getUserInfo(context) {
    // 获取接口信息
    const result = await getUserInfo()
    context.commit('setUserInfo', result)
  }
}

api/user.js里封装接口

export function getUserInfo() {
  return request({
    url: '/sys/profile'
  })
}

调整action位置

getter.js里封装userId

const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  userId: state => state.user.userInfo.userId,
  avatar: state => state.user.avatar,
  name: state => state.user.name
}
export default getters

permission.js

   if (!store.getters.userId) { await store.dispatch('user/getUserInfo') }
      next()// 到其他页面,放行
    }
  } else {
    // 没有token
    if (whiteList.includes(to.path)) {
      next()
    } else {
      next('/login') // 中转到登录页
      nProgress.done()
    }
  }

显示用户头像、名称

根据传过来的数据显示头像和名称

1.通过getters向外暴露用户头像和信息

const getters = {
  sidebar: state => state.app.sidebar,
  device: state => state.app.device,
  token: state => state.user.token,
  userId: state => state.user.userInfo.userId,
  avatar: state => state.user.userInfo.avatar, // 用户头像
  name: state => state.user.userInfo.name// 用户名称
}
export default getters

2.找组件

先引入

import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'

export default {
 computed: {
    ...mapGetters([
      'sidebar',
      'avatar',
      'name'
    ])
  }

使用

    <!--头像-->
          <img :src="avatar" class="user-avatar">
          <!--用户名称-->
          <span>{{ name }}</span>

调整样式

 .avatar-wrapper {
        margin-top: 5px;
        position: relative;
        display: flex;
        align-items: center;
        .name{
margin-right: 10px;
font-size: 16px;
      }
      .el-icon-setting{
font-size: 20px;
      }

处理用户头像为空

1.v-if 和v-else

2.设置样式

 .username{
        width: 30px;
        height: 30px;
        line-height: 30px;
        align-items: center;
        background-color: aqua;
        color: #fff;
        border-radius: 50%;
        margin-right: 4px;
      }

3.当用户姓名为空时,使用可选链(需要升级版本)

处理token失效

store/user.js声明一个提出登录的actions

logout(context) {
    context.commit('removeToken')
    // 调用setUserInfo,传进去空对象,以清除用户信息
    context.commit('setUserInfo', {})
  }

request.js跳转

if (error.response.status === '401') {
    Message({ type: 'warning', message: 'token超时' })
    store.dispatch('user/logout')// 调用action退出登录
    // 主动跳转到登录页
    router.push('/login')
    return Promise.reject(error)
  }
  Message({ type: 'error', message: error.message })
  return Promise.reject(error)

退出登录

async logout() {
      this.$store.dispatch('user/logout')
      this.$router.push('/login')
    }

显示修改密码弹层

 <!--放置dialog-->
  <!--.sync,可以接收子组件传过来的事情和值-->
  <el-dialog width="500px" title="修改密码" :visible.sync="showDialog">
    <el-form />
  </el-dialog>

表单结构

   <el-dialog width="500px" title="修改密码" :visible.sync="showDialog">
      <!--放置表单-->
      <el-form label-width="120px">
        <el-from-item label="旧密码">
          <el-input show-password size="small" />
        </el-from-item>
        <el-from-item label="新密码">
          <el-input show-password size="small" />
        </el-from-item>
        <el-from-item label="重置密码">
          <el-input show-password size="small" />
        </el-from-item>
        <el-form-item>
          <el-button type="primary" size="mini">确认</el-button>
          <el-button size="mini">取消</el-button>
        </el-form-item></el-form>
    </el-dialog>

表单校验(prop与rules有关,v-model与数据绑定有关)

   <el-dialog width="500px" title="修改密码" :visible.sync="showDialog">
      <!--放置表单-->
      <el-form ref="passForm" label-width="120px" :rules="rules" :model="passForm">
        <el-from-item label="旧密码" prop="oldPassword">
          <el-input v-model="passForm.oldPassword" show-password size="small" />
        </el-from-item>
        <el-from-item label="新密码" prop="newPassword">
          <el-input v-model="passForm.newPassword" show-password size="small" />
        </el-from-item>
        <el-from-item label="重置密码" prop="confirmPassword">
          <el-input v-model="passForm.confirmPassword" show-password size="small" />
        </el-from-item>
        <el-form-item>
          <el-button type="primary" size="mini">确认</el-button>
          <el-button size="mini">取消</el-button>
        </el-form-item></el-form>
    </el-dialog>

变量准备(rules在data里)

data() {
    return {
      showDialog: false,
      passForm: {
        oldPassword: '',
        newPassword: '',
        confirmPassword: ''
      },
      rules: {
        oldPassword: [],
        newPassword: [],
        confirmPassword: []
      }
    }
  },

校验规则

判断两次密码是否相同:用了自定义校验,注:必须使用箭头函数,否则this不能指向组件实例

rules: {
        oldPassword: [{ required: true, message: '旧密码不能为空', trigger: 'blur' }], // 旧密码
        newPassword: [{ required: true, message: '新密码不能为空', trigger: 'blur' }, {
          trigger: 'blur',
          min: 6,
          max: 16,
          message: '新密码的长度为6-16位之间'
        }], // 新密码
        confirmPassword: [{ required: true, message: '重复密码不能为空', trigger: 'blur' }, {
          trigger: 'blur',
          validator: (rule, value, callback) => {
            // value
            if (this.passForm.newPassword === value) {
              callback()
            } else {
              callback(new Error('重复密码和新密码输入不一致'))
            }
          }
        }] // 确认密码字段
      }
    }
  },

总结

确认按钮

先绑定事件,之后调用接口(传参时就多不就少,注意async)

 btnOk() {
      this.$refs.passForm.validator(async(isOk) => {
        if (isOk) {
          // 调用接口
          // 传收集来的值
          await updatePassword(this.passForm)
          // 成功后执行重置表单,不成功不用管
          this.$refs.passForm.resetFields()
          // 关闭弹层
          this.showDialog = false
        }
      })
    }

优化:

this.$refs.passForm.resetFields()

      // 关闭弹层

      this.showDialog = false

这两句代码与关闭按钮的一致,所以直接调用关闭按钮

btnOk() {
      this.$refs.passForm.validator(async(isOk) => {
        if (isOk) {
          // 调用接口
          // 传收集来的值
          await updatePassword(this.passForm)
          // 成功后执行重置表单,不成功不用管
          this.$refs.passForm.resetFields()
          // 关闭弹层
          // this.showDialog = false
          // this.$message.success('修改成功')
          this.btnCancel()
        }
      })
    }

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值