vuex

243 阅读4分钟

1. Vuex 总结

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store (仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。

(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。 
     这样使得我们可以方便地跟踪每一个状态的变化。
     this.$store.commit('updateBusinessobj', obj);

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

2. Getter => 从基本数据派生的数据,允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅
   是将 store 中的 getter 映射到局部计算属性, 不会改变 源数据。

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

4. Action => 像一个装饰器,包裹 mutations,使之可以异步。用于提交 mutation,而不是直接
   变更状态,可以包含任意异步操作。

5. Module => 模块化Vuex,允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

 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))
        })
},

2. mutation 和 action 的详细区别

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
1、流程顺序
“相应视图—>修改State”拆分成两部分,视图触发Action,Action再触发Mutation。

2、角色定位
基于流程顺序,二者扮演不同的角色。
Mutation:专注于修改 State,理论上是修改  。
Action:业务代码、异步请求。

3、限制
角色不同,二者有不同的限制。
Mutation:必须同步执行。
Action:可以异步,但不能直接操作 State。

总结:
action 的功能和 mutation 是类似的,都是去变更 store 里的 state


action 和 mutation 有两点不同:

1、action 主要处理的是异步的操作,mutation 必须同步执行,而 action 就不受这样的限制,也就是说 action 中我们既可以处理同步,也可以处理异步的操作

2、action 改变状态,最后是通过提交 mutation

3. 使用 Vuex 统一管理状态的好处、和用处

Vuex 统一管理状态的好处:

能够在 vuex 中集中管理共享的数据,易于开发和后期维护

能够高效地实现组件之间的数据共享,提高开发效率

存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步

用处:什么样的数据适合存储到 Vuex 中:

一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;

对于组件中的私有数据,依旧存储在组件自身的data中即可。

4. vuex 的安装

1.安装 vuex 依赖包

npm i vuex - save

2.在 store.js 中 导入 vuex 包

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

3.创建 store 对象

const store = new Vuex.Store({
    // state 中存放的就是全局共享的数据
    state: {

    },
    mutations: {

    },
    actions: {

    },
    getters: {

    }
})
// 导出 store
export default store

4.main.js 引入 store

import store from './store/index.js'

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

5. 组件访问 state 中的数据的两种方式

1.通过 this.$store.state 访问

6b62d2240833bf58f6a2ff2a559d0c5.png

2.mapState 函数访问

a1056720a8e787ed33308f70974a99a.png

6. Mutations 用于变更 state 中的数据

Mutation 用于变更 Store 中的数据。

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

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

1. 触发 Mutations 函数 无参数

// 定义 Mutation
const store = new vuex.store({
    state: { 
        count: 0
    },
    mutations: {
        add(state) {
            // 变更状态 
            state.count++
        }
    }
})

methods: {
    // 触发mutation 
    handle1() {
        // 触发 mutations 的第一种方式
        this.$store.commit('add')
    }
}

2. 触发 Mutations 函数 有参数

// 定义 Mutation
const store = new vuex.store({
    state: { 
        count: 0
    },
    mutations: {
        add(state, params) {
            // 变更状态 
            state.count += params;
        }
    }
})

methods: {
    // 触发mutation 
    handle1() {
        // 触发 mutations 时在第二个参数里传递要的值
        // commit 的作用,专门用来触发 某个 mutation 函数
        this.$store.commit('add', 3)
    }
}

3. mapMutations 来调用

this.$store.commit() 是触发 mutations 的第一种方式,触发 mutations 的第二种方式:

// 1.从vuex 中按需导入 mapMutations函数
import { mapMutations } from 'vuex!

通过刚才导入的mapMutations函数,将需要的mutations函数,映射为当前组件的methods 方法:

methods:{
    // 将指定的 mutations 函数,映射为当前组件的 methods 函数 
    ...mapMutations(['add', 'addn']),
    addHandle() {
        this.add()
    }
}

4. Mutation 为什么不能使用异步函数

image.png 重点事情: 为什么必须是同步更新?

Mutation 异步函数 会 造成状态改变的不可追踪

造成状态改变的不可追踪
造成状态改变的不可追踪

可以看到在 Mutation 中使用异步和同步最终页面的总和都是正确的,也就是说在Mutation 中使用异步不会对数据造成丢失和其他影响。然而我们注意 Vue Devtools 显示结果,当我们去查看多次 Mutation 状态时,发现同步的显示 Ok,异步的 Count 显示为 0 和我们预期结果不一致,所以会造成状态改变的不可追踪,所以官方说我们Mutation 是同步的!

5.Mutation 才能修改 state 中的数据

5.只有 mutations 中定义的函数,才有权利来变更 state 中的函数.jpg

7.actions 异步任务用于辅助 mutations 来异步执行变更 state 中的数据

1.actions 定义

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

// 定义 Action
const store = new Vuex.store({
    //...省略其他代码
    mutations: {
        add(state) {
            state.count++
        }
    },

    actions: {
        addAsync(context) {
            setTimeout(() => {
                context.commit('add')
            }, 1000);
        }
    }
})

// 触发 Action 
methods: {
    handle(){
        // 触发 actions 的第一种方式, dispatch 函数,专门用来触发 action
        this.$store.dispatch('addAsync')
    }
}

2.actions 中,不能直接更改 state 中的数据

actions: {
    addAsync(context){
        setTimeout(() => {
            // 在 actions 中,不能直接修改 state 中的数据;
            // 必须通过 context.commit()触发某个 mutation 才行 I 
            context.commit('add')
        }, 1000)
    }
}

3. 触发 action 异步任务 携带参数

// 定义 Action
const store = new Vuex.Store({
    // ...省略其他代码
    mutations: {
        addNumN(state, params) {
            state.count += params;
        },
    },
    actions: {
        addNAsync(context, params) {
            setTimeout(() => {
                context.commit('addNumN', params)
            }, 1000);
        },
    },
})

// 触发 Aciton
methods: {
    addHandle4() {
        // 触发 Aciton时,第二个参数为要的 值
        this.$store.dispatch('addNAsync', 3)
    },
}

4. mapActions 触发 actions

this.$store.dispatch() 是触发 actions 的第一种方式,触发 actions 的第二种方式:

1.从 vuex 中按需导入 mapActions 函数

import { mapActions } from 'vuex'

2.通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法: 将指定的 actions 函数,映射为当前组件的 methods 函数

methods:{
    ...mapActions(['addasync', 'addnAsync']),
    subHandle2() {
        this.addasync(3)
    }
}

8. getters

Getter 用于对 Store 中的数据进行加工处理形成新的数据。

Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。 Store 中数据发生变化,Getter 的数据也会跟着变化。Getter 不会影响 state 中的源数据

1.定义 getter

// 定义 Getter
const store = new vuex.store({
    state: {
        count: 0
    },
    getters: {
        showNum: state => {
            return `当前最新的数量是【' + state.count + '】!`
        }
    }
})

2.使用getters的第一种方式

this.$store.getters.名称
例如:this.$store.getters.showNum

3.使用getters的第二种方式:

import { mapgetters } from 'vuex'
computed:{
    ...mapGetters(['showNum'])
}