vuex相关汇总

# 状态管理基本

# vuex是什么

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

# 怎么使用vuex

第一步安装

npm install vuex -S
1

第二步创建store

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
//不是在生产环境debug为true
const debug = process.env.NODE_ENV !== 'production';
//创建Vuex实例对象
const store = new Vuex.Store({
    strict:debug,//在不是生产环境下都开启严格模式
    state:{
    },
    getters:{
    },
    mutations:{
    },
    actions:{
    }
})
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

第三步注入vuex

import Vue from 'vue';
import App from './App.vue';
import store from './store';
const vm = new Vue({
    store:store,
    render: h => h(App)
}).$mount('#app')
1
2
3
4
5
6
7

# vuex中有几个核心属性,分别是什么?

一共有5个核心属性,分别是:

  • state 唯一数据源,Vue 实例中的 data 遵循相同的规则
  • getters 可以认为是 store 的计算属性,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值.
const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,非常类似于事件,通过store.commit 方法触发
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++ // 变更状态
    }
  }
})
store.commit('increment')
1
2
3
4
5
6
7
8
9
10
11
  • action Action 类似于 mutation,不同在于Action 提交的是 mutation,而不是直接变更状态,Action 可以包含任意异步操作
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • module 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。
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 的状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 你使用过 Vuex 吗?

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

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

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

主要包括以下几个模块

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
  • Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
  • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
  • Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。

# Vuex 的原理以及自己的理解

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

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。

b025e120ca3d0bd2ded3d038d58cacf4.jpg Vuex为Vue Components建立起了一个完整的生态圈,包括开发中的API调用一环。

(1)核心流程中的主要功能:

  • Vue Components 是 vue 组件,组件会触发(dispatch)一些事件或动作,也就是图中的 Actions;
  • 在组件中发出的动作,肯定是想获取或者改变数据的,但是在 vuex 中,数据是集中管理的,我们不能直接去更改数据,所以会把这个动作提交(Commit)到 Mutations 中;
  • 然后 Mutations 就去改变(Mutate)State 中的数据;
  • 当 State 中的数据被改变之后,就会重新渲染(Render)到 Vue Components 中去,组件展示更新后的数据,完成一个流程。

(2)各模块在核心流程中的主要功能:

  • Vue Components∶ Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
  • dispatch∶操作行为触发方法,是唯一能执行action的方法。
  • actions∶ 操作行为处理模块。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
  • commit∶状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutations∶状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
  • state∶ 页面状态管理容器对象。集中存储Vuecomponents中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
  • getters∶ state对象读取方法。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。

# mutation和action有什么区别【要点】

从下面三个方面说;

  • action 提交的是 mutation,而不是直接变更状态。mutation可以直接变更状态;action 可以包含任意异步操作。mutation只能是同步操作

  • 提交方式不同

    • mutation是用this.$store.commit('SET_NUMBER',10)来提交;
    • action 是用this.$store.dispatch('ACTION_NAME',data)来提交;
  • 接收参数不同,mutation第一个参数是state,而action第一个参数是context, [store自己],其包含了

{
    state,      // 等同于 `store.state`,若在模块中则为局部状态
    rootState,  // 等同于 `store.state`,只存在于模块中
    commit,     // 等同于 `store.commit`
    dispatch,   // 等同于 `store.dispatch`
    getters,    // 等同于 `store.getters`
    rootGetters // 等同于 `store.getters`,只存在于模块中
}
1
2
3
4
5
6
7
8

示范:

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
  },

  actions: {
    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        login(userInfo).then(response => {
          const result = response.result
          storage.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
          commit('SET_TOKEN', result.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# Vuex中action和mutation的区别

mutation中的操作是一系列的同步函数,用于修改state中的变量的的状态。当使用vuex时需要通过commit来提交我们需要操作的内容。mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++      // 变更状态
    }
  }
})
1
2
3
4
5
6
7
8
9
10

# ajax请求代码应该写在组件的methods中还是vuex的actions中

如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。

如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用

# 从vuex中获取的数据能直接更改吗?

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

# vuex中的数据在页面刷新后数据消失

用sessionstorage 或者 localstorage 存储数据

  • 存储: sessionStorage.setItem( '名', JSON.stringify(值) )
  • 使用: sessionStorage.getItem('名') ---得到的值为字符串类型,用JSON.parse()去引号;

也可以引入插件vuex-persist,使用方法如下:

  • 安装
npm install --save vuex-persist
or
yarn add vuex-persist
1
2
3
  • 引入 import VuexPersistence from 'vuex-persist'

  • 先创建一个对象并进行配置

const vuexLocal = new VuexPersistence({
    storage: window.localStorage
})
1
2
3
  • 引入进vuex插件
const store = new Vuex.Store({
  state: { ... },
  mutations: { ... },
  actions: { ... },
  plugins: [vuexLocal.plugin]
}) 
1
2
3
4
5
6

通过以上设置,在图3中各个页面之间跳转,如果刷新某个视图,数据并不会丢失,依然存在,并且不需要在每个 mutations 中手动存取 storage 。

# 自己实现plugin插件

实现VuexPersistencelogger

class VuexPersistence {
  constructor({ storage }) {
    this.storage = storage;
    this.localName = "VUEX-MY";
  }
  plugin = (store) => {
    let localState = JSON.parse(this.storage.getItem(this.localName));
    if (localState) store.replaceState(localState);
    store.subscribe((mutationName, state) => {
      // 这里需要做一个节流  throttle lodash
      this.storage.setItem(this.localName, JSON.stringify(state));
    });
  };
}
// 自己实现logger插件
const logger = () => (store) => {
  let prevState = JSON.stringify(store.state);
  store.subscribe((mutationName, state) => {
    // 监听变化的 ,每次数据变化都会执行此方法 commit 的时候会执行此方法
    console.log("prev" + prevState);
    console.log(mutationName);
    prevState = JSON.stringify(state);
    console.log("next", prevState);
  });
};

const vuexLocal = new VuexPersistence({
  storage: window.localStorage,
});

Vue.use(Vuex); // 使用这个插件  内部会调用Vuex中的install方法
const store = new Vuex.Store({
  // strict: true,
  plugins: [
    // 插件从上到下执行
    vuexLocal.plugin, // 放在这里 插件默认就会显执行一次
    logger(),
  ],
 })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

# Vuex的严格模式是什么,有什么作用,怎么开启?

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

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

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

# 怎么在组件中批量使用Vuex的getter属性

使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中

import {mapGetters} from 'vuex'
export default{
    computed:{
        ...mapGetters(['total','discountTotal'])
    }
}
1
2
3
4
5
6

# 组件中重复使用mutation

使用mapMutations辅助函数,在组件中这么使用

import { mapMutations } from 'vuex'
methods:{
    ...mapMutations({
        setNumber:'SET_NUMBER',
    })
}

computed: {
  // 直接取出状态中的结果
  ...mapState(['lesson']),
    // 给状态起名字
    ...mapState({lesson1:'lesson'}),
    // 通过函数的方式获取结果
    ...mapState({lesson2:state=>state.lesson})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

然后调用this.setNumber(10)相当调用this.$store.commit('SET_NUMBER',10)

export * from './helpers';
import {createNamespacedHelpers} from 'vuex';
//import {mapState,mapGetters, mapMutations, mapActions} from 'vuex';
let {mapState as mapState1 ,mapGetters} = createNamespacedHelpers('samy');
export default {
    computed: {
        // 直接取出状态中的结果
        ...mapState(['lesson']),
        // 给状态起名字
        ...mapState({lesson1:'lesson'}),
        // 通过函数的方式获取结果
        ...mapState({lesson2:state=>state.lesson})
        
         // getName(){
        //     return this.$store.getters.getLessonName
        // }
        ...mapGetters(['getLessonName'])//通过辅助函数可以简写很多;
    },
    methods: {
        //this.$store.dispatch('SET_LESSON_NAME');
       ...mapMutations(['SET_LESSON_NAME']), //mapMutations简化方法;
       ...mapActions(['Login', 'Logout']),
       changeName(){
          this['SET_LESSON_NAME']({number:10});
       },
       stepCaptchaCancel () {
        this.Logout().then(() => {
        this.loginBtn = false
        this.stepCaptchaVisible = false
      })
    },
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 在v-model上怎么用Vuex中state的值?

需要通过computed计算属性来转换。 get/set处理

<input v-model="message">
// ...
computed: {
    message: {
        get () {
            return this.$store.state.message
        },
        set (value) {
            this.$store.commit('updateMessage', value)
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
上次更新: 2022/04/15, 05:41:33
×