Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

一、vuex 安装

npm install vuex --save

二、导入 vuex 包

import Vuex from 'vuex'Vue.use(Vuex)

三、创建store 对象

const store = new Vuex.Store({      state:{ count:0 }})

四、将store对象挂载到vue实例中

new vue({            el:'#app',            render:h=>h(app),            router,            // 将创建的共享数据对象,挂载到vue实例中            // 所有的组件,就可以直接从store中获取全局的数据了            store        })

五、vuex中的核心概念

1、state

state提供唯一的公共数据源,所有共享的数据都要统一放到store的state中进行存储。

// 创建store数据源,提供唯一公共数据    const store = new Vuex.Store({        state:{ count:0 }    })    //  组件访问state中数据的第一种方式:    this.$store.state.全局数据名称    //  组件访问state中数据的第二种方式(通过辅助函数):    // 1、从vuex中按需导入mapState函数    import {mapState} from 'vuex'    // 通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性    // 2、将全局数据,映射为当前组件的计算属性    computed:{        ...mapState(['count'])        // 或者        ...mapState({            current: (state) => state.tab.currentMenu,        }),    }

2、Mutation

    Mutation用于变更store中的数据

    1)、只能通过mutation变更store数据,不可以直接操作store中的数据。

    2)、通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。

// 定义Mutation    const store = new Vuex.Store({        state:{            count:0        },        mutations:{            add(state){                // 变更状态                state.count++            }        }    })    // 触发mutation    methods:{        handel(){            // 触发 mutations 的第一种方式            this.$store.commit('add')        }    }
// 可以在触发 mutations 是传递参数    // 定义Mutation    const store = new Vuex.Store({        state:{            count:0        },        mutations:{            addN(state,step){                // 变更状态                state.count += step            }        }    })    // 触发 mutation    methods:{        handel2(){            // 在调用 commit 函数,触发 mutations 时携带参数            this.$store.commit('add',3)        }    }

触发mutation的第二中方式:

// 1)、从 vuex 中按需导入 mapMutations 函数    import { mapMutations } from 'vuex'//  通过刚才导入的mapMutations函数,将需要的mutation函数,映射为当前组件的methods方法:    methods:{        ...mapMutations(['add','addN'])    }

3、Action

        Action用于处理异步任务

        如果通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在Action中还是要通过触发Mutation的方式间接变更数据。

// 定义Action        const store = new Vuex.Store({        state:{            count:0        },        mutations:{            add(state){                // 变更状态                state.count ++            }        },        actions:{            addAsyns(context){                setTimeout(()=>{                    contexxt.commit('add')                },1000)            }        }    })// 触发Action    methods:{        handel(){            // 触发 actions 的第一种方式            this.$store.dispatch('addAsync')        }    }

触发actions异步任务时携带参数:

// 定义Action        const store = new Vuex.Store({        state:{            count:0        },        mutations:{            addN(state,step){                // 变更状态                state.count += step            }        },        actions:{            addAsyns(context,step){                setTimeout(()=>{                    contexxt.commit('add',step)                },1000)            }        }    })// 触发Action    methods:{        handel(){            // 在调用 dispatch 函数,触发 actions 时携带参数            this.$store.dispatch('addAsync',5)        }    }

触发actions的第二种方式:

// 1)、从 vuex 中按需导入 mapActions 函数    import { mapActions } from 'vuex'// 2)、通过刚才导入的 mapActions 函数,将需要的actions 函数,映射为当前组件的methods方法:    methods:{        ...mapActions(['addAsync','addNAsync'])    }

4、Getter

    getter 用于对store中的数据进行加工处理形成新的数据。类似于计算属性computed

    1)、getter可以对store中已有的数据加工处理之后形成新的数据,类似vue的计算属性。

    2)、store中的数据发生变化,getter的数据也会跟着变化。

// 定义getter    const store = new Vuex.Store({        state:{            count:0        },        mutations:{            addN(state,step){                // 变更状态                state.count += step            }        },        getters:{            snowNum:state=>{                return '当前最新的数量是【'+ state.count +'】'            }        }    })
 // 使用getters的第一种方式:    this.$store.getters.名称    // 使用getters的第二种方式:    import {mapGetters} from 'vuex'    computed:{        ...mapGetters(['showNum'])    }

5、Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

    为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

const moduleA = {  state: { ... },  mutations: { ... },  actions: { ... },  getters: { ... }}const moduleB = {  state: { ... },  mutations: { ... },  actions: { ... }}const store = new Vuex.Store({  modules: {    a: moduleA,    b: moduleB  }})store.state.a // -> moduleA 的状态store.state.b // -> moduleB 的状态

在项目中 module 的使用:

2c2932088bd3a1f4cee73187fe9e0526.png

store/index.js :

import Vue from 'vue'import Vuex from 'vuex'// 引入tab.jsimport tab from './tab.js'Vue.use(Vuex)export default new Vuex.Store({  modules: {    tab  }})

store/tab.js :

export default {    state: {        menu: [],        // 点击的菜单        currentMenu: null    },    mutations: {        selectMenu(state, val) {            // state.currentMenu = val;            val.name === 'home' ? state.currentMenu = null : state.currentMenu = val;        }    },    actions: {},    modules: {}}

六、vuex 数据在页面刷新后数据丢失问题

解决方法:在APP.vue文件的created生命周期中加入以下代码即可:

//在页面加载时读取sessionStorage里的状态信息    if (sessionStorage.getItem("store")) {      this.$store.replaceState(        Object.assign(          {},          this.$store.state,          JSON.parse(sessionStorage.getItem("store"))        )      );    }    //在页面刷新时将vuex里的信息保存到sessionStorage里    window.addEventListener("beforeunload", () => {      sessionStorage.setItem("store", JSON.stringify(this.$store.state));    });

总结:

1、vuex主要包括以下几个模块:
State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。


Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。


Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。


Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。


Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

2、什么情况下使用 Vuex?
如果应用够简单,最好不要使用 Vuex,一个简单的 store 模式即可
需要构建一个中大型单页应用时,使用Vuex能更好地在组件外部管理状态

3、Vuex和单纯的全局对象有什么区别?
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

4、为什么 Vuex 的 mutation 中不能做异步操作?
Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难

5、vuex的action有返回值吗?返回的是什么?
store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
Action 通常是异步的,要知道 action 什么时候结束或者组合多个 action以处理更加复杂的异步流程,可以通过定义action时返回一个promise对象,就可以在派发action的时候就可以通过处理返回的 Promise处理异步流程。

一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。

6、为什么不直接分发mutation,而要通过分发action之后提交 mutation变更状态?
mutation 必须同步执行,我们可以在 action 内部执行异步操作
可以进行一系列的异步操作,并且通过提交 mutation 来记录 action 产生的副作用(即状态变更)

7、从vuex中获取的数据能直接更改吗?
从vuex中取的数据,不能直接更改,需要浅拷贝对象之后更改,否则报错;

8、Vuex的严格模式是什么,有什么作用,怎么开启?
在严格模式下,无论何时发生了状态变更且不是由mutation函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。

在Vuex.Store 构造器选项中开启,如下:

const store = new Vuex.Store({    strict:true,})

9、mutation和action有什么区别
action 提交的是 mutation,而不是直接变更状态。mutation可以直接变更状态
action 可以包含任意异步操作。mutation只能是同步操作
提交方式不同

action 是用this.store.dispatch('ACTION_NAME',data)来提交。mutation是用this.$store.commit('SET_NUMBER',10)来提交

接收参数不同,mutation第一个参数是state,而action第一个参数是context,其包含了

{    state,      // 等同于 `store.state`,若在模块中则为局部状态    rootState,  // 等同于 `store.state`,只存在于模块中    commit,     // 等同于 `store.commit`    dispatch,   // 等同于 `store.dispatch`    getters,    // 等同于 `store.getters`    rootGetters // 等同于 `store.getters`,只存在于模块中}

10、在v-model上怎么用Vuex中state的值?
需要通过computed计算属性来转换。

"message">// ...computed: {    message: {        get () {            return this.$store.state.message        },        set (value) {            this.$store.commit('updateMessage', value)        }    }}

ecdc83fff0674cf54c912b03fec094df.png

Logo

前往低代码交流专区

更多推荐