Vuex实现组件全局状态(数据)管理

873 阅读2分钟

Vuex

是什么

实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享。

使用 Vuex 管理数据的好处:

A.  vuex 集中管理共享的数据,便于开发和后期进行维护;

B. 高效实现组件之间的数据共享,提高开发效率;

C. 存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新;

Vuex 的基本使用

一、终端命令步骤

1、打开终端,输入命令:vue ui

 

2、设置手动配置项目

 

 

 

 

 3、设置功能项

 

 

 4、创建项目

 

 二、mian.js输入

1、安装 Vuex 依赖包

npm i vuex 

2、导入 Vuex 包

 import Vuex from 'vuex';

Vue.use(Vuex); 

3、创建 store 对象

1 const store = new Vuex.Store({
2   // state 中存放的就是全局共享的数据
3   state: {
4     count: 0,
5   },
6 });

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

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

Vuex 的核心特性

00.png

State

概念: 存储共享状态中的数据

访问方式

方式一、原始方式
main.js
 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import Vuex from 'vuex'
 4 // 注册vuex的功能,Vue.use的方法实际上是调用了vuex中的一个install的方法
 5 Vue.use(App)
 6 Vue.use(Vuex)  7 // 实例化一个Vuex
 8 
 9 const store = new Vuex.Store({
10   // 实例化vuex的构造函数,state mutations actions
11  state: {
12     // 存储状态
13     count: 0,
14   15   },
16 })
17 
18 Vue.config.productionTip = false
19 
20 new Vue({
21   render: (h) => h(App),
22   // 将创建的共享数据对象,挂载到 Vue 实例中
23   // 所有的组件,就可以直接从 store 中获取
24  store, 25 }).$mount('#app')
方式一:原始方式访问

App.vue

 1 <template>
 2   <div id="app">
 3       <!-- 1、原始形式获取 -->
 4     <p>原始形式获取state状态:{{ this.$store.state.count }}</p>
 5     <!-- 2.0 -->
 6     <p>计算属性的状态:{{ count }}</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 export default {
12   name: 'App',
13  computed: {
14     // 2.1 监听count变化
15 count() { 16       return this.$store.state.count 17     },
18   },
19 }
20 </script>
21 
22 <style>
23 </style>
方式二、辅助函数形式

1、按需导入 mapState 函数 : import { mapState } from 'vuex'

2、然后数据映射为计算属性:computed:{ ...mapState(['全局数据名称']) }

 1 <template>
 2   <div id="app">
 3     <!-- 获取数据状态 -->
 4     <h2>state 获取数据状态</h2>
 5     <!-- 3辅助函数获取状态 -->
 6     <p>辅助函数获取状态:{{ count }}</p>
 7   </div>
 8 </template>
 9 
10 <script>
11 
12 
13 // 辅助函数
14 //  导入vuex中的方法mapState
15 import { mapState } from 'vuex'
16 export default {
17   name: 'App',
18   components: {
19     Addition,
20   },
21   // 把state中数据,定义在组件内的计算属性中
22   // 作用,减轻在模板中的代码量
23   computed: {
24    ...mapState(['count']), 25   },
26 }
27 </script>
28 <style>
29 </style>

 

 

Mutation

一次mutations的执行,立刻得到一种视图状态,因为是立刻,所以必须是同步

访问方式

方式一、原始形式

main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import Vuex from 'vuex'
 4 // 注册vuex的功能,Vue.use的方法实际上是调用了vuex中的一个install的方法
 5 Vue.use(App)
 6 Vue.use(Vuex)
 7 // 实例化一个Vuex
 8 
 9 const store = new Vuex.Store({
10   // 实例化vuex的构造函数,state mutations actions
11   state: {
12     // 存储状态
13     count: 0,
14   },
15   // 功能二、mutations修改state的值
16   // 数据快照:修改state,必须通过mutations且mutations必须是同步更新,目的是形成数据快照
17   // mutations是一个对象,对象中存放修改state的方法
18  mutations: {
19     // 修改mutations的方法
20     // 方法名是自定义,不一定叫updateStae,
21     // 方法里参数,第一个参数是当前store的state属性
22     // payload载荷 运输参数,调用mutations的时候,可以传递参数,传递载荷
23     // updateStae(state) {
24     //   state.count += 1
25     // },
26     // 传参,
27  updateStae(state, payload) {
28       state.count += payload 29     },
30   },
31  
32 })
33 
34 Vue.config.productionTip = false
35 
36 new Vue({
37   render: (h) => h(App),
38   // 将创建的共享数据对象,挂载到 Vue 实例中
39   // 所有的组件,就可以直接从 store 中获取
40   store,
41 }).$mount('#app')

 

方式二、辅助函数形式
 1 //按需导入mapMutations 
 2 import { mapMutations } from "vuex";

 3 <!--方式二--2.4 绑定mutations对象中的自定义函数setMutations并传参-->
 4   <button @click="setMutations(3)">+1(辅助函数形式)</button>
 5 export default {
 6   methods: {
 7 
 8 // 方式二--2.1展开运算符将mutations对象中的自定义函数setMutations映射到当前组件
 9     ...mapMutations(["setMutations"]), 10 
11 }
12 }
打印结果:

Action

mutations 中不能编写异步的代码,会导致 vue 调试器的显示出错,Action 来执行异步操作

异步修改数据,将数据提交到mutations中,进而修改数据

mian.js

 1 import Vue from "vue";
 2 import App from "./App.vue";
 3 
 4 import Vuex from "vuex";
 5 
 6 Vue.use(App);
 7 Vue.use(Vuex);
 8 
 9 const store = new Vuex.Store({
10   // state存储共享数据状态
11   state: {
12     // 存储状态
13     count: 0,
14     15   },
16   mutations: {
17     // setMutations自定义函数,可任意起名
18     // mutations中的自定义函数setMutations接收参数
19     // 方式二--2.3在mutations中设置自定义函数setMutations,接收state共享数据中的值及传参过来的数据
20     setMutations(state, a) {
21       state.count += a;
22     },
23   },
   //actions 执行异步操作,自定义函数,接收
24  actions: {
25  setActions(context, params) {
26       setTimeout(() => {
27         context.commit("setMutations", params);
28       }, 1000);
29     },
30   },  
31 });
32 
33 Vue.config.productionTip = false;
34 
35 new Vue({
36   store,
37   render: (h) => h(App),
38 }).$mount("#app");
方式一、原始方式

child.vue

1 <button @click="btnAsynchronous">异步提交(原始方式)</button>
2  
3 btnAsynchronous() {
4 //actions中的自定义函数名,传值
5       this.$store.dispatch("setActions", 111);
6     },
 方式二、辅助函数形式
1 <button @click="setActions(222)">辅助方式</button>
2 export default {
3   methods: {
4 
5 ...mapActions(["setActions"]),
6 }
7 }
打印结果 

点击之后1s之后打印的结果

Getter

Getter 它只会包装 Store 中保存的数据,并不会修改 Store 中保存的数据,当 Store 中的数据发生变化时,Getter 生成的内容也会随之变化

main.js

 1 import Vue from "vue";
 2 import App from "./App.vue";
 3 
 4 import Vuex from "vuex";
 5 
 6 Vue.use(App);
 7 Vue.use(Vuex);
 8 
 9 const store = new Vuex.Store({
10   // state存储共享数据状态
11   state: {
12     // 存储状态
13     count: 0,
14    list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 15   },
16   mutations: {
17     
18     setMutations(state, a) {
19       state.count += a;
20     },
21   },
22   actions: {
23     setActions(context, params) {
24       setTimeout(() => {
25         context.commit("setMutations", params);
26       }, 1000);
27     },
28   },
29  getters: {
30     filtersList(state) {
31       return state.list.filter((item) => item > 5);
32     },
33   },
34 });
35 
36 Vue.config.productionTip = false;
37 
38 new Vue({
39   store,
40   render: (h) => h(App),
41 }).$mount("#app");

方式一、原始方式

 1 

getters原始方式:{{ $store.getters.filtersList }}

 

方式二、辅助函数形式

 1 <p>getters辅助方式:{{ filtersList }}</p>
 2 //按需导入mapGetters 
 3 import { mapGetters } from "vuex";
 4 
 5 export default {
 6   methods: {
 7 
 8  computed: {
 9     ...mapGetters(["filtersList"]),
10   },
11 
12 }}
打印结果:

modules

作用: 拆分模板,把复杂的场景按模块来拆开

格式

 1 export default new Vuex.Store({
 2   // state: 用来保存所有的公共数据
 3   state: {},
 4   getters: {},
 5   mutations: {},
 6   actions: {},
 7   modules: {
 8       模块名1: {
 9             // namespaced为true,则在使用mutations时,就必须要加上模块名
10           namespaced: true, 
11             state: {},
12               getters: {},
13               mutations: {},
14               actions: {},
15               modules: {}
16       },
17     模块名2: {
18         // namespaced不写,默认为false,则在使用mutations时,不需要加模块名
19             state: {},
20               getters: {},
21               mutations: {},
22               actions: {},
23          modules: {}
24       }  
25   }
26 })

main.js

 1 import Vue from 'vue'
 2 import App from './App.vue'
 3 import Vuex from 'vuex'
 4 // 注册vuex的功能,Vue.use的方法实际上是调用了vuex中的一个install的方法
 5 Vue.use(App)
 6 Vue.use(Vuex)
 7 // 实例化一个Vuex
 8 
 9 const store = new Vuex.Store({
10   // 实例化vuex的构造函数,state mutations actions
11   state: {
12     // 存储状态
13     count: 0,
14     list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
15   },
16   // 功能二、mutations修改state的值
17   // 一次mutations的执行,立刻得到一种视图状态,因为是立刻,所以必须是同步
18   // 数据快照:修改state,必须通过mutations且mutations必须是同步更新,目的是形成数据快照
19   // mutations是一个对象,对象中存放修改state的方法
20   mutations: {
21     // 修改mutations的方法
22     // 方法名是自定义,不一定叫updateStae,
23     // 方法里参数,第一个参数是当前store的state属性
24     // payload载荷 运输参数,调用mutations的时候,可以传递参数,传递载荷
25 
26     // updateStae(state) {
27     //   state.count += 1
28     // },
29     // 传参,
30     updateStae(state, payload) {
31       console.log(state)
32       state.count += payload
33     },
34   },
35   // actions做异步更新
36   // 从后端获取一个数,更新到state的count中
37   actions: {
38     // 存放的也是一个个的方法
39     // 第一个参数 执行的上下文对象
40     // context相当于组件中的this.$store store的运行实例
41     getAsyancCount(context, parmas) {
42       //做异步请求,模拟异步请
43       setTimeout(() => {
44         context.commit('updateStae', parmas)
45       }, 1000)
46     },
47   },
48   getters: {
49     // 防止所有的vuex的计算属性
50     filterList(state) {
51       return state.list.filter((item) => item > 5)
52     },
53     token: (state) => state.user.token,
54     name: (state) => state.setting.name,
55   },
56  modules: {
57     // 设置模块的子属性
58     user: {
59       // 设置namespace的:true,命名锁 坑:此时报错,会导致所有文件都能访问,没有隐私不安全
60       // vuex.esm.js?2f62:460 [vuex] unknown mutation type: updateToken
61       namespaced: true,
62       state: {
63         token: '12345',
64       },
65       mutations: {
66         updateToken(state) {
67           state.token = '67890'
68         },
69       },
70     },
71     setting: {
72       state: {
73         name: 'vuex实例',
74       },
75     },
76   },
77 })
78 
79 Vue.config.productionTip = false
80 
81 new Vue({
82   render: (h) => h(App),
83   // 将创建的共享数据对象,挂载到 Vue 实例中
84   // 所有的组件,就可以直接从 store 中获取
85   store,
86 }).$mount('#app')

subraction.vue

 1 <template>
 2   <div>
 3     <h3>modules模块化</h3>
 4     <!-- $store.state.子模块.属性 -->
 5     <p>用户的token:{{ $store.state.user.token }}</p>
 6     <p>快捷访问方式:{{ token }}</p>
 7     <p>网站名称:{{ $store.state.setting.name }}</p>
 8     <!-- 方式二、快捷访问方式 -->
 9     <p>快捷访问方式:{{ name }}</p>
10     <hr />
11     <button @click="updateToken">更新子模块的token</button>
12     <button @click="updateToken">辅助函数形式token</button>
13     <!-- <button @click="text">调用子模块的mapMutations</button> -->
14   </div>
15 </template>
16 <script>
17 // mapMutations这个是全局的
18 // import { mapGetters, mapMutations, createNamespacedHelpers } from 'vuex'
19 import { mapGetters, createNamespacedHelpers } from 'vuex'
20 //mapMutations这个是 user中的
21 const { mapMutations } = createNamespacedHelpers('user')
22 export default {
23   computed: {
24     ...mapGetters(['token', 'name']),
25   },
26   methods: {
27     // updateToken() {
28     //   // this.$store.commit('updateToken')
29     //   // 解决方案,采用路径方式
30     //   this.$store.commit('user/updateToken')
31     // },
32     // // 解决方式2:采用展开运算符方式
33     // ...mapMutations(['user/updateToken']),
34     // // 解决方式3:采用关联数组形式
35     // text() {
36     //   this['user/updateToken']()
37     // },
38     ...mapMutations(['updateToken']),
39   },
40 }
41 </script>
42 <style scoped>
43 button {
44   margin: 10px;
45 }
46 </style>