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 的核心特性
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>