影城项目DAY08

文章介绍了Vue中使用Vuex进行状态管理的辅助函数,如mapState,mapGetters等,以及如何在登录后保持用户状态,使用自定义存储工具API如sessionStorage。同时,讨论了只有登录后才能访问特定页面和发送HTTP请求的实现,涉及路由守卫和请求拦截器。最后,提到了HTTP状态管理和Token机制在认证授权中的作用。
摘要由CSDN通过智能技术生成

目录

1.辅助函数

2.登录后,刷新用户状态不消失的实现

3.自定义存储工具API

4.只有在登录之后,才可以看到除登录之外的页面(全局前置守卫)

5.只有在登录之后,才可以发送其他的http增删改查的请求

6.总结


1.vue辅助函数

知识点:

vue的辅助函数有:1、mapState,将全局状态管理的state值映射到组件的计算属性;2、mapGetters,将全局状态管理的getters值映射到组件的计算属性;3、mapActions;4、mapMutations。

Vuex提供了一些辅助函数,可以简化访问Store中数据的代码:

computed: state  getter

methods: mutations actions

import {mapState, mapMutations, mapActions} from 'vuex'

.....
data(){
    return {
        user: ''
    }  
},
computed: {
    ...mapState(['user', 'token']), 
    ...mapGetters(['....'])
},
methods: {
	...mapMutations(['updateUser', 'saveToken'])
    ...mapActions(['login'])
}

使用辅助函数前:

this.$store.state.user.nickname

使用了辅助函数后:

user.nickname

  store/index.js

  // 状态: vuex的单一状态树,用于存储全局共享的数据信息。
  state: {
    // 该user对象就是存储在vuex中的可以供组件直接访问的全局状态信息

    user: null,
    city: '北京',
    token: 'tokenxxxxx',
    data: []
  },

Homeview     全部简写 去掉this.$store.state.user.xxxxxx

知识点:computed  method 的区别

1.computed是响应式的,methods并非响应式。

2.调用方式不一样,computed定义的成员是像属性一样访问,methods定义的成员必须以函数形式调用。

3.computed是带缓存的,只有依赖数据发生改变,才会重新进行计算,而methods里的函数在每次调用时都要执行。

      <!-- 显示用户信息 -->
          <div v-if="$store.state.user">
          <div v-if="user">
            <i class="el-icon-user"></i>&nbsp;
           
            <span>{{user.nickname}}</span>
            &nbsp;&nbsp;
            <i class="el-icon-phone-outline"></i>&nbsp;
           
            <span>{{user.phone}}</span>
            &nbsp;&nbsp;
            <i class="el-icon-chat-dot-round"></i>&nbsp;
        
            <span>{{user.email}}</span>
          </div>
          

        </el-header>

        <el-main>
<script>
import {mapState, mapMutations} from 'vuex'  // 辅助函数

export default {
  data() {
    return {
      isCollapse: false
    }
  },
  
  // 如下写法, this.user 就是 vuex中state里的user
  // computed: mapState(['user', 'token'])
  computed: {
    ...mapState(['user', 'token']), 
    getTotal(){
      return 100
    }
  },

  methods: {
    // 以下写法相当于将vuex的mutations中声明的updateUser方法引入
    // 调用this.updateUser(参数对象),即可执行vuex中的mutations
    ...mapMutations(['updateUser'])
  },
};
</script>

2.登录后,刷新用户状态不消失的实现

实现思路:

  1. 当登录成功,向vuex中存储用户对象,同时也需要向sessionStorage中存一份。

  2. 当vuex初始化时,直接从sessionStorage中加载初始化数据。例子:

    state:{
        user: sessionStorage.getItem(xx)
    }

     修改store/index.js   state

    state: {
          // 该user对象就是存储在vuex中的可以供组件直接访问的全局状态信息
          // user: sessionStorage.getItem('USER')?JSON.parse(sessionStorage.getItem('USER')): null,

  3. 3.自定义存储工具API: 

    新建utils/Storage .js

    export const KEYS = {
         TOKEN:'TOKEN',
        USER_INFO : 'USER_INFO',
        CITY_NAME :'CITY_NAME'
    }
    export const set = (key,data)=>{
      sessionStorage.setItem(key,JSON.stringify(data))
      
    }
    export const get = (key)=>{
       let data = sessionStorage.getItem(key)
        if(data){
            return JSON.parse(data)
        }else{
            return null
        }
      }
    import {KEYS, set, get} from '@/utils/Storage'
    state: {
        // 该user对象就是存储在vuex中的可以供组件直接访问的全局状态信息
        user: get(KEYS.USER_INFO),
    },
    import {KEYS, set, get} from '@/utils/Storage'
    // 存数据
    set(KEYS.USER_INFO, res.data.data.user)

4.只有在登录之后,才可以看到除登录之外的页面(全局前置守卫) 

**业务需求:**若已经登录,则可以访问普通页面;若没有登录的前提下访问普通页面,应直接跳转到登录页面。

实现思路:在项目的VueRouter对象中添加路由的全局前置守卫。前置守卫将会在路由跳转到目标页之前执行,那么就可以在此处进行判断用户的登录状态。

1.若已经登录,则可以访问普通页面。

2.若没有登录的前提下访问普通页面,应直接跳转到登录页面。

// 全局的前置路由守卫,将会在每一次路由跳转时执行(目标显示之前)
router.beforeEach((to, from, next)=>{
  console.log('from:', from)
  console.log('to:', to)
  next() // 调用next()方法才可以继续原本的跳转业务流程
})

每个守卫方法接收三个参数:

  • to: Route: 即将要进入的目标 路由对象
  • from: Route: 当前导航正要离开的路由
  • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。

完整的导航解析流程

  • 导航被触发。
  • 在失活的组件里调用 beforeRouteLeave 守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  • 在路由配置里调用 beforeEnter
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter
  • 调用全局的 beforeResolve 守卫 (2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

5.只有在登录之后,才可以发送其他的http增删改查的请求

如果想要实现该功能,则需要服务端进行用户验证(鉴权),验证当前请求中是否包含用户的身份信息。如果该用户有访问该资源的权限,则执行相应业务;如果用户没有处理请求的权限,则直接驳回,返回错误消息:您没有权限

实现思路:

登录成功后,将token字符串保存下来。Vuex+Storage。

以后每次发请求,都应该修改axios的代码,添加一个消息头。带着authorization消息头一起发送请求即可。

此处可以借助axios的请求拦截器来实现,统一添加消息头。

 mutations: {



       saveToken(state,token){
             state.token = token
       },
       /** 此处声明方法,该方法将被vuex所管理
     *  方法用于修改state中的用户数据,如果需要修改用户数据。
     *  state:   vuex自动传入的state对象
     *  payload: 用户调用当前方法时传递的自定义参数
     */
        updateUser(state, payload){
          state.user = payload
        }
  },
  actions: {
      /**
     * 执行异步登录业务,登录成功后将用户对象存入state(调用mutations)
     * @param  store   vuex自动传入  Store对象
     * @param  params  用户传递的参数   {username:xx, password:xx}
     */
       login(store, params){
        httpApi.adminApi.login(params).then(res=>{
          if(res.data.code==200){ // 登录成功
            store.commit('updateUser', res.data.data.user)
            store.commit('saveToken', res.data.data.token)
            // 
            set(KEYS.USER_INFO,res.data.data.user)
            set(KEYS.TOKEN,res.data.data.token)
            Notification.success({
              message: '登录成功'
            })
            router.replace('/home/index')
            
          }else {  // 登录失败
            Notification.error({ message:res.data.msg })
          }
        })
      }
  },
  modules: {
  }
})

MyAxios  添加请求拦截器,对config进行操作

  const instance = axios.create()

  //添加请求拦截器
  instance.interceptors.request.use(function(config){
    //对config进行操作
    let token =store.state.token
    if(token){
      config.headers['Authorization'] = token
      
    }
    return config;
  })

bmdstudios-server  修改index.js
  // 测试环境中,不做token拦截,直接执行后续业务
  // if(1==1){
  //   next();
  //   return;
  // }


  // 执行token验证
  let token = req.headers["authorization"];
  try {
    let payload = jwt.verify(token, JWT_SECRET_KEY);
    req.tokenPayload = payload  // 将token中存储的数据,直接复制给req,这样在后续业务中就可以使用req.tokenPayload获取这些信息
  } catch (error) {
    resp.send(Response.error(401, '用户验证失败,请重新登录'))
    return;
  }
  next(); // 继续后续业务的执行
};

6.总结

  1. 什么时候用vuex?

  2. 怎么用?

虽然vuex很好用,可以方便的实现SPA单页面应用的状态数据的统一集中管理,但是不能刷新,一旦用户刷新了浏览器,就会重新加载整个vue环境,vuex中的数据也将会初始化。

所以在使用vuex存储数据时,都需要思考一个问题:这些数据是否需要持久化存储?

如果需要,则应借助于html5提供的sessionStorage与localStorage来完成。当向vuex中存储数据时,还需要向webStorage存一份(这个地方可以长久存储),当用户f5刷新页面时,vuex中数据可以从webstorage中读取并初始化。

3.为什么不直接使用Storage存储数据呢?能不能就不用vuex了?

Storage虽然有持久化存储的特点,但是存储在Storage中的数据没有响应式的特点。如果修改了Storage中的数据,UI是不会及时更新的。所以一般情况下,都需要二者配合在一起使用,配合的方式都雷同:

  1. 存的时候,顺便 存入storage。
  2. vuex的state中初始化时,要从storage中加载并初始化。

发现了一个大bug,好像不登录也能进行数据的增删改查。 实际上,应实现如下业务场景:

  1. 只有在登录之后,才可以看到除登录之外的页面。
  2. 只有在登录之后,才可以发送其他的http增删改查的请求,否则发送的所有请求都应该被服务端驳回:不登录就没有操作数据的权限
知识点:
HTTP状态管理方式

短连接通信模式:客户端与服务端建立连接,通信完毕后,连接断开。

长连接通信模式:客户端与服务端建立连接,通信完毕后,连接不断开。

由于HTTP请求属于短连接模式的请求,所以每个http请求都是独立的,互不相关。所以http协议也称为“无状态的通信协议”。

http的状态管理:将同一个客户端的多次请求当做一个整体来看待;将同一个客户端发送请求时涉及到的状态数据保存下来,每次发请求时要让服务端知道。

基于Token机制实现http状态管理

当登录成功后,服务端将会返回登录用信息,并且还会返回一个token字符串。

客户端保存这些数据。user token。

以后同一个客户端发送后续所有请求时,都需要携带该token字符串一起发送请求。这样服务端才知道该客户端的登录信息,用户拥有什么权限。因为所有的信息都在这个加了密的token字符串里,服务端可以对该字符串进行解密,从而获取上一次保存的信息,完成相应业务。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值