VueX状态管理

目录总览:

一、VueX概念

1. VueX的概念

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新
  • VueX里面所有数据都可以全局使用。

2. 状态管理的概念

可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。

将这个对象放在顶层的Vue实例中,让其他组件可以使用。

二、单界面的状态管理

在单文件组件中进行状态管理:

图片中的三种东西如下:

  • State:状态
  • View:视图层,可以针对 State 的变化,显示不同的信息
  • Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的变化
//单文件组件内部代码
<template>
  <div>
    <div>当前计数:{{counter}}</div>
      <button @click="counter+=1">+1</button>    
      <button @click="counter-=1">-1</button>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
      return {
          counter: 0
      }
  }
}
</script>

<style scoped>

</style>

上述案例中,需要管理的状态:个数counter

  1. counter需要某种方式被记录下来,也就是我们的State。

  2. counter目前的值需要被显示在界面中,也就是我们的View部分。

  3. 界面发生某些操作时(我们这里是用户的点击,也可以是用户的input),需要去更新状态,也就是我们的Actions

三、多界面状态管理

3.1 单个文件的组件状态管理清晰明了,那多个单文件组件的状态管理呢?(出现的问题)

  • 多个组件都依赖同一个状态(一个状态改了,多个组件界面需要进行更新)
  • 不同界面的 组件Actions 都想修改同一个状态(Home.vue 需要修改,Profile.vue 也需要修改这个状态)

3.2 VueX背后的基本思想:(解决方法)

1. 将多个组件共享的状态抽取出来,交给我们的大管家VueX,统一进行管理。

2. 每个组件视图,按照VueX的规则定,进行访问和修改等操作。

四、VueX 基本用法

1. 安装VueX

  • 方式1:通过命令行npm进行安装。
npm install vuex --save
  • 方式2:Vue-cli3脚手架生成 Vue 项目基础架构时候,进行配置选择。

2. 使用步骤

我们创建一个文件夹 src/store,并且在其中创建一个 store.js 文件,代码如下:

import Vuex from 'vuex'
import Vue from 'vue'

// 1.安装插件
Vue.use(Vuex)
// 2.创建对象
const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state){
            state.count++
        },
        decrement(state){
            state.count--
        }
    },
    actions: {
        
    },
    getters: {
        
    },
    modules: {
        
    }
})

// 导出store对象
export default store

其次,我们让所有的Vue组件都可以使用这个store对象

  • 来到 src/main.js文件,导入store对象,并且挂载到new Vue中
import Vue from 'vue'
import App from './App'
// 1.导入store对象
import store from './store'


new Vue({
    el: '#app',
    // 2.挂载 store
    store,
    render: h => h(App)
})
  • 这样,在其他Vue组件中,我们就可以通过 this.$store的方式,获取到这个store对象了
//app.vue根组件
<template>
  <div id="app">
      <p>
      <button @click="increment">+1</button>
      <button @click="decrement">-1<</button>
  </div>
</template>
//行为层
<script>
export default {
    name: 'App',
    components: {
        
    },
    computed: {
        count: function() {
            return this.$store.state.count
        }
    },
    methods: {
        increment: function() {
            this.$store.commit('increment')
        },
        decrement: function() {
            this.$store.commit('decrement')
        }
    }
}

</script>

使用步骤小结:

  1. 提取出一个公共的 store 对象,用于保存在多个组件中共享的状态
  2. 将 store 对象放置在 new Vue 对象中,这样可以保证在所有的组件中都可以使用到
  3. 在其他组件中使用 store 对象中保存的状态即可
    • 通过 this.$store.state 属性的方式来访问状态
    • 通过 this.$store.commit('mutation中方法') 来修改状态
  4. 我们通过提交 mutation 的方式,而非直接改变 store.state.count
  5. 这是因为 Vuex 可以更明确的追踪状态的变化,所以不要直接改变 store.state.count 的值

五、VueX核心概念🔥

🔥🔥🔥强调:VueX的store.js定义方式固定,获取方式有两种:

  • $store 当作全局对象直接进行访问
  • import 作为模块导入为组件内部属性或方法

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'])
}

2. Mutation状态更新(函数修改变量)

  • Mutation 用于变更 Store中 的数据。

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

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

2.1 Mutation用法🔥

调用方式一:

调用方式二:

2.2 Mutation传参🔥

调用方式一:

调用方式二:

1.store.js内定义函数

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
//store.js内定义函数
export default new Vuex.Store({
  state: {
    count: 0
  },
  // 只有 mutations 中定义的函数,才有权利修改 state 中的数据
  mutations: {
    subN(state, step) {
      state.count -= step
    }
  },
}

2.在组件文件内导入函数 绑定函数

//组件文件内导入函数 绑定函数
<template>
  <div>
    <h3>当前最新的count值为:{{count}}</h3>
    //引入的函数进行绑定
    <button @click="subN(3)">-N</button>
  </div>
</template>

<script>
import { mapState, mapMutations } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    //将指定的state变量,映射为当前组件的computed计算属性
    ...mapState(['count']),
  },
  methods: {
    //将指定的 mutations 函数,映射为当前组件的 methods 函数
    ...mapMutations(['sub', 'subN']),
  }
}
</script>

3. Action异步任务(异步函数调用mutation)

  • Action 用于处理异步任务。

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

3.1 Action用法🔥

调用方式一:

  • actions 异步任务(不带参)
  • 触发 actions 异步任务时携带参数:
3.2 Action传参🔥

调用方式二:

  • actions 异步任务(不带参)
//store.js内定义函数
export default new Vuex.Store({
  state: {
    count: 0
  },
 // 只有 mutations 中定义的函数,才有权利修改 state 中的数据
 mutations: {
    sub(state) {
      state.count--
    }
 actions: {
    subAsync(context) {
      setTimeout(() => {
        context.commit('sub')
      }, 1000)
    }
//组件文件内导入函数 绑定函数
<template>
  <div>
    <h3>当前最新的count值为:{{count}}</h3>
    //引入的函数进行绑定
    <button @click="subAsync">-1 Async</button>
  </div>
</template>

<script>
//导入store.js里面的acion、mutation函数,acion内部调用mutation 
import { mapState, mapMutations, mapActions } from 'vuex'

export default {
  data() {
    return {}
  },
  computed: {
    //将指定的state变量,映射为当前组件的computed计算属性
    ...mapState(['count']),
  },
  methods: {
    //将指定的 action 函数,映射为当前组件的 methods 函数
    ...mapMutations(['sub']),
    ...mapActions(['subAsync'])
  }
}
</script>
  • 触发 actions 异步任务时携带参数:

1.store.js内定义函数

2.在组件文件内导入函数 绑定函数

4. Getters基本使用(变量加工)

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

① Getter 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。

② Store 中数据发生变化,Getter 的数据也会跟着变化。

1.store.js内定义函数

2.调用VueX

调用方式1:当作全局对象直接进行调用

调用方式2:在组件文件内导入模块 绑定属性和函数

5. Module模块化

Module 是模块的意思,为什么在 Vuex 中我们要使用模块呢?

  • Vue 使用单一状态树,那么也意味着很多状态都会交给 Vuex 来管理
  • 当应用变得非常复杂时, store 对象就有可能变得相当臃肿
  • 为了解决这个问题,Vuex 允许我们将 store 分割成某块,而每个模块拥有自己的 state、mutations、action、getters等
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 的状态
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容