Vuex和Vuex-persistedstate

死了也要PY / 2023-06-11 / 原文

Vuex

Vuex是Vue框架生态的一环,用于实现全局数据状态的统一管理。

官方地址:https://next.vuex.vuejs.org/zh/index.html

cd ~/Desktop/luffycity/luffycityweb
# 在客户端项目根目录下执行安装命令
yarn add vuex@next
npm install vuex

开始使用

在main.js导入并且使用use方法启用

import { createApp } from 'vue'
import { createStore } from 'vuex'

// 创建一个新的 store 实例
const store = createStore({
  state () {
    return {
      count: 0
    }
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

核心的五个属性

state

该属性等同于vue中的data属性,用来存储全局的对象

const state={
  user:{name:"alex"}
}

getters

唯一的获取state中值的方法,计算属性

const state={
  user:{name:"alex"}
}

const getters={
  getUser(state){
  return state.user.name
  }

}

mutations 相当于vue中的methos

唯一的修改state中值的方法,同步阻塞

const state={
  user:{name:"alex"}
}

const mutations={
  updateUser(state,new_user){
  state.user = new_user
  }

}

actions

异步阻塞,也可以修改state值,但是底层还是调用mutations,而不是直接变更。
并且调用mutations还要通过commit方法,传入函数名进行调用

const state={
  user:{name:"alex"}
}

const mutations={
  updateUser(state,new_user){
  state.user = new_user
  }

const actions={
// 和mutations不同,不用传state,可以通过上下文context,
// 这个context 可以获取整个代码文件中的属性和方法
// 调mutations的方法通过commit调用,而调用actions的要用dispatch调用
  asyncUpdateUser(context,new_user){ //这个context参数可以不显示传
  context.commit("updateUser",new_user)
    }
  }
}

Module

用来对vuex下面进行模块化切分组合,看下官网例子https://vuex.vuejs.org/zh/guide/modules.html

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

登录小案例

父组件 home.vue
子组件 login.vue
vuex全局的代码 login.js
子组件中输入用户名,如果是aa或者bb则登录成功,成功后的用户显示在父组件的标签中作为全局显示.
未登录成功则显示未登录

main.js代码

import { createApp } from 'vue'
// import './style.css'
import App from './App.vue'
import store from './components/login.js'
createApp(App).use(store).mount('#app')

home.vue代码

<script setup>
import { ref } from 'vue'
import login from "./login.vue"
import store from "./login.js"
</script>

<template>
  <p>用户信息>>{{store.state.user}}</p>
  <login></login>
</template>

<style scoped>

</style>

login.vue代码

<script setup>
import { ref,reactive } from 'vue'
import store from "./login.js"

const user =ref("")
// 同步阻塞 执行mutations
const submit =()=>{
  if (user.value==="aa"){
      store.commit("login_success",user)
  }

}
  // 异步调用 执行actions
  const submit2 =()=>{
  if (user.value==="bb"){
      store.dispatch("asyncUpdateUser",user)
  }
}
</script>

<template>
  <label>用户登录</label>
  <!-- <input type="" name="" v-model="userinfo.user"> -->
  <input type="" name="" v-model="user">
  <button @click="submit">commit同步阻塞</button>
  <button @click="submit2">action异步阻塞</button>
</template>

login.js代码

import { createStore } from 'vuex'

export default createStore({
  // 也可以用函数形式写
// state(){
// // state:{
//   return{user:"未登录"}
// // }
// },

state:{user:"未登录"},

mutations:{
  login_success(state,newuser){
    state.user = newuser
    console.log(state.user)
  }
},
actions:{
// 和mutations不同,不用传state,可以通过上下文context,
// 这个context 可以获取整个代码文件中的属性和方法
// 调mutations的方法通过commit调用,而调用actions的要用dispatch调用
  asyncUpdateUser(context,new_user){ //这个context参数可以不显示传
  context.commit("login_success",new_user)
    }
  }

})


vuex-persistedstate

因为vuex默认是保存数据在内存中的,所以基于浏览器开发的网页,如果在F5刷新网页时会存在数据丢失的情况。所以我们可以把store数据永久存储到localStorage中。这里就需要使用插件vuex-persistedstate来实现。
在前端项目的根目录下执行安装命令

cd ~/Desktop/luffycity/luffycityweb
yarn add vuex-persistedstate
npm install vuex-persistedstate --save

在vuex的store/index.js文件中导入此插件。

import {createStore} from "vuex"
import createPersistedState from "vuex-persistedstate"

// 实例化一个vuex存储库
export default createStore({
    // 调用永久存储vuex数据的插件,localstorage里会多一个名叫vuex的Key,里面就是vuex的数据
    plugins: [createPersistedState()],
    state(){  // 相当于组件中的data,用于保存全局状态数据
        return {
            user: {}
        }
    },
    getters: {
        getUserInfo(state){
            // 从jwt的载荷中提取用户信息
            let now = parseInt( (new Date() - 0) / 1000 );
            if(state.user.exp === undefined) {
                // 没登录
                state.user = {}
                localStorage.token = null;
                sessionStorage.token = null;
                return null
            }

            if(parseInt(state.user.exp) < now) {
                // 过期处理
                state.user = {}
                localStorage.token = null;
                sessionStorage.token = null;
                return null
            }
            return state.user;
        }
    },
    mutations: { // 相当于组件中的methods,用于操作state全局数据
        login(state, payload){
            state.user = payload; // state.user 就是上面声明的user
        }
    }
})

完成了登录功能以后,我们要防止用户FQ访问需要认证身份的页面时,可以基于vue-router的导航守卫来完成。