Vuex详解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

Vuex的五个属性:state,getters,mutations,actions,modules和四个辅助函数mapState,mapGetters,mapMutations,mapActions。


提示:以下是本篇文章正文内容,下面案例可供参考

vuex在这里插入图片描述

状态管理,多个组件有共享数据的时候,就叫状态管理
什么情况下会用到vuex , 如果你不知道vuex的情况也能完成你的需求,就说你的项目中不需要用到状态管理。
组件层级比较复杂的时候,还是用组件传值的方式来传值,那么就会很不方便,给我们的开发造成一些不必要的麻烦,使用了vuex之后,提供统一的api, 管理起来也很放方便,提高了开发效率。
状态管理,可以看做是一个仓库。 这个仓库可以是所有的组件都可以去这个仓库里面去数据。(就消除了层级的问题)
官网:官网Vuex
现在版本是vuex4.x,它是支持vue3的
如果是vue2的版本,使用是vuex3.x
但是4.x也不是最新的版本。 pinia是最新版(网称:大菠萝)官网链接
我们使用脚手架创建项目的时候,已经选择vuex,就可以直接在项目中使用。
但是如果在创建项目的时候,没有选择上,就需要我们手工安装。

npm i vuex

vuex也是一个插件,所以需要在main.js 使用use()来加载插件。

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

const app = createApp(App)
app.use(store)   // vuex
app.use(router)
app.mount('#app')

使用方式

router/index.js
// 1.从vuex导入了一个创建仓库的方法
import { createStore } from 'vuex'

// 2.然后使用了这个方法创建了一个仓库对象,然后导出
const store = createStore({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

export default store
main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'   //  ./store/index.js


const app = createApp(App)
app.use(store)  // 3.在vue实例中挂载了这个仓库.
app.use(router)
app.mount('#app')

state

用来存放共享的数据的,类似全局的data

store/index.js

const store = createStore({
  state: {  // 用来存放共享的数据的,类似全局的data
    count: 18,
    list: [2,3,3,4,5,88,22,33,11],
    age: 20,
    name: 'young'
  },
})

几种取的方式

直接取

<div>{{ $store.state.count }}</div>

通过计算属性取

computed:{ 
    // 当前页面要多次调用仓库的数据. 还用上面的方法的话,就重复的代码太多了,不方便维护
    // 可以结合计算属性来调用. 把仓库中要取的值,当做计算属性的依赖就可以了.
    // 虽然结合计算属性可以方便的一点的调用,但是还是有代码冗余,所以vuex中就提供了辅助函数给我们更方便的调用数据
    // 具体的使用方法看AboutView.vue
    count(){
      return this.$store.state.count
    },
    list(){
      return this.$store.state.list
    },
    age(){
      return this.$store.state.age
    },
    name(){
      return this.$store.state.name
    }
  },

通过辅助函数mapState取
mapState是一个函数,可以接收一个数组参考 ,数组里面的每一项就是要取仓库中字段

<script>
  // 要在这个组件中取到多个共享数据
  // 可以使用mapState()来帮助我们生成计算属性
  // 1. 先导入mapState方法
  import { mapState } from 'vuex'
  export default {
    data(){
      return {
        count: 0
      }
    },
    computed:{
      // mapState是一个函数
      // 可以接收一个数组参考 
      // 数组里面的每一项就是要取仓库中字段
      ...mapState(['count','list','age','name'])
    }
  }
</script>

getters

提供统一取数据的方法 // 如果取都有相同的操作就可以定义在这里(就像是以全局的computed)

store/index.js

const store = createStore({
  state: {  // 用来存放共享的数据的,类似全局的data
    list: [2,3,3,4,5,88,22,33,11],
  },
  getters: {  // 提供统一取数据的方法  // 如果取都有相同的操作就可以定义在这里(就像是以全局的computed)
    // 把list过滤一遍里面呢只有偶数
    getevenList(state){
      const oulist = state.list.filter(item=>{
        return item%3 == 0
      })
      return oulist
    }
  }
})

在组件中使用
直接使用

this.$store.getters.getevenList
使用辅助函数 mapGetters

<script>
  // 导入 mapGetters 方法
  import { mapGetters } from 'vuex'
  export default {
    computed:{
      ...mapGetters(['getevenList']),
    }
  }
</script>

mutations

修改数据的方法 (只能写同步代码,不能写异步)

const store = createStore({
  state: {  // 用来存放共享的数据的,类似全局的data
    count: 18,
    age: 20,
  },
  mutations: { // 修改数据的方法
    changeCount(state){   // 提供了一个修改state.count的方法
      state.count++
    },
    changeAge(state){
      state.age++
    }
  },
})

直接通过$store.commit()调用

methods:{
    changecount(){
      // 虽然可以这么改,但是不建议这么做, (不好追踪的修改)
      // 既然是仓库中的数据,就要使用仓库中的方法去修改

      // this.$store.state.count = 100      
      // console.log(this.$store.state.count)

      // 要使用$store的commit() 来触发mutations
      this.$store.commit('changeCount')
    },
    changeage(){
      this.$store.commit('changeAge')
    }
  },

通过mapMutations 辅助函数生成对应的方法来调用

<div>
  <button @click="changeCount">修改count</button>
  <button @click="changeAge">修改age</button>
</div>
    
<script>
  import { mapGetters } from 'vuex'

  // 导入 mapMutations 的方法
  import { mapMutations } from 'vuex'

  export default {
    methods:{
      ...mapMutations(['changeCount','changeAge'])
      // 就相当于是在方法中定义了这两个方法来触发mutations
    },
  }
</script>

actions

异步修改数据的方法
虽然是异步,但是也要通过mutations去修改

import myaxios from '@/utils/axios'

// 1.从vuex导入了一个创建仓库的方法
import { createStore } from 'vuex'

const store = createStore({
  state: {  // 用来存放共享的数据的,类似全局的data
    age: 20,
    mylist: []   // 定义数组保存数据
  },
  mutations: { // 修改数据的方法  (同步)
    changeAge(state){
      state.age++
    },
    setList(state,list){  
      // 定义一个mutations 来修改数组, 转进来什么就修改什么
      state.mylist = list
    }
  },
  actions: {   // 异步修改数据的方法
    // 虽然是异步,但是也要通过mutations去修改
    asyncChangeAge(context){    // context就是相当于仓库对象 , $store   
      console.log(context)
      // 3秒后再修改age
      setTimeout(()=>{
        context.commit('changeAge')
      },3000)
    },
    asyncSetList(context){
      // 需求: 要请求接口拿到数据后,再给state, 这个请求是异步, 所以就要写在actions中
      myaxios.get('city').then(res=>{
        // console.log(res)
        if(res.status==0){
          context.commit('setList', res.data.cities)
        }
      })
    }
  },
})

通过$store.dispatch() 调用

this.$store.dispatch('asyncChangeAge')

this.$store.dispatch('asyncSetList')

modules

把仓库分成一个一个小仓库(模块化)

小仓库都可以写vuex特有的4个属性: state getters mutations action

state 得是函数然后返回一个对象

store/user.js 专门用于存放用户信息的仓库

const user = {   // 用来保存用户的一个小仓库
  namespaced: true,    // 命名空间, 调用里面的方法就要通过仓库名称
  state(){
    return {
      name:'young',
      age: 18
    }
  },
  mutations: {
    changName(state){
      state.name = 'yyds'
    },
    changeAge(state){
      state.age++
    }
  }
}

export default user

store/index.js 挂载这个user仓库

import { createStore } from 'vuex'
import user from './user'

const store = createStore({
  modules: {    // 仓库模块化
    // 在这个modules中加载一个小仓库
    user:user
  },
})
export default store
在 组件中使用小仓库的数据

要通过小仓库的名称

{{this.$store.state.user.name}}--{{ this.$store.state.user.age}}
小仓库有命名空间,调用方法的时候也要加上小仓库的名称

 this.$store.commit('user/changName')
 this.$store.commit('user/changeAge')

plugins

插件: 就是一个函数

仓库初始化好了之后会调用一次,修改的时候也会调用subscribe()

import { createStore } from 'vuex'
const store = createStore({
  state: {
    count: 0
  },
  mutations:{
    changeCount(state){
      state.count++
    },
    setCount(state,num){
      state.count = num
    }
  },
  plugins: [(store)=>{   
    /*
      1.先判断再storage中没有存的值
        有 - 赋值给state.count
        没有  -  把默认值存在storage中

      2. 修改的时候同步更新到storage
    */
    // vuex 初始化好了之后就会触发这个方法
    // console.log(store.state.count)
    const local = localStorage.getItem('vuex')
    // console.log(local)
    if(local){
      const s  = JSON.parse(local)
      // console.log(s)
      // store.state = s
      store.commit('setCount',s.count)
    }else{
      localStorage.setItem('vuex',JSON.stringify(store.state))  
    }

    store.subscribe((mutation, state)=>{
      // 只要有修改了就会触发这个方法
      // console.log(state)
      localStorage.setItem('vuex',JSON.stringify(state)) 
    })
  }]
})

export default store

vuex持久化插件(vuex-persist)

1.安装

npm i vuex-persist

2.使用插件

import { createStore } from 'vuex'

// 1. 导入vuex-persist的插件

import VuexPersistence from 'vuex-persist'

// 2. 创建vuex-persist插件的实例

const vuexLocal = new VuexPersistence({
  storage: window.localStorage   // 指定用那种储存方式
})

const store = createStore({
  state: {
    count: 0,
    name: 'young'
  },
  mutations:{
    changeCount(state){
      state.count++
    },
    setCount(state,num){
      state.count = num
    }
  },
  // 3. 使用插件
  plugins: [vuexLocal.plugin]
})
export default store

Vuex持久化插件(vuex-persistedstate)

1.安装

npm i vuex-persistedstate

2.使用

import { createStore } from 'vuex'
// 引入vuex持久化方法createPersistedState
import createPersistedState from 'vuex-persistedstate'
import user from './modules/user'
import cart from './modules/cart'
 
export default createStore({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {
    // 模块化数据
    user,
    cart,
  },
  plugins: [
    // veux持久化配置
    createPersistedstate({
      key: 'rabbitstore-client', // 在localStorage中存值的键名
      paths: ['user', 'cart'] // 需要持久化的模块数据,,如果是模块下具体的数据需要加上模块名称,如user.token
    })
  ]
})

总结

提示:以上是本篇Vuex的大致内容

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抬头第一眼,是天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值