于Nuxt中使用Vuex

1、何为 Vuex

Vuex  是一个专为  Vue.js  应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
但是在 Nuxt.js  内置引用了  vuex  模块,所以不需要额外安装。
Nuxt.js  会尝试找到应用根目录下的  store  目录,无需配置 nuxt.config.js,如果该目录存在,它将做以下的事情:
引用  vuex  模块 将  vuex  模块 加到  vendors  构建配置中去 设置  Vue  根实例的  store  配置项

2、引用 Vuex

Nuxt.js  支持两种使用  store  的方式,你可以择一使用:
普通方式: store/index.js  返回一个  Vuex.Store  实例 模块方式: store  目录下的每个  .js  文件会被转换成为状态树指定命名的子模块 (当然,index  是根模块)

2.1 普通方式

使用普通方式的状态树,需要添加  store/index.js  文件,并对外暴露一个  Vuex.Store  实例:

1
2
3
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = ()
=> new Vuex.Store({ state: { count: 1 }, mutations: { add(state) { state.count
++; } } }) export default store;

在组件中就可以直接调用:<span>{{$store.state.count}}</span><button ``[@click](https://github.com/click)``="$store.commit('add')">+1</button>

2.2 模块方式

状态树还可以拆分成为模块,store  目录下的每个  .js  文件会被转换成为状态树指定命名的子模块
使用状态树模块化的方式,store/index.js  不需要返回  Vuex.Store  实例,而应该直接将  state、mutations  和  actions  暴露出来:

1
2
export const state = () => ({ scount: 0 }) export const mutations = {
addScount(state) { state.scount += 2 } } // 模块模式状态树

在页面组件调用:
<span>{{$store.state.index2.scount}}</span> <button @click="$store.commit('index2/addScount')">+2</button>

3、规范案例

在 Nuxt 项目的 store 目录下新建一个 index.js 文件作为主入口,这样项目就启用了 vuex

1
2
3
4
import Vue from 'vue'; import Vuex from 'vuex'; import counter_add from
'./counter_add'; import filter from './filter'; Vue.use(Vuex); const store = ()
=> new Vuex.Store({ state: {}, mutations: {}, modules: { counter_add, filter }
}) export default store

其他的业务代码分模块来写,在 store 文件夹里再新建一个 filter.js 文件,在 index.js 中引入一下。

1
2
3
4
5
const state = ({ value: 'Hello World', list: [1, 2, 3, 4, 5] }); const getters =
{ include: (state) => (val) => { return state.list.indexOf(val) > -1; } } ;
const mutations = { SET_VALUE(state, value) { state.value = value; } }; const
actions = { async getInfo({state, commit}, val) { commit('SET_VALUE', val); } };
export default { namespaced: true, state, getters, actions, mutations };

这个文件中输出时候的 namespaced 属性,如果为 true 时,使用这个文件的方法时,需要标注 namespace,不写或为 false 时,则可以直接使用,这里建议使用 namespaced,因为大型项目可能有很多复杂的业务,可能命名冲突,使用 namespaced 可以把方法区分开,避免很多问题

现在,我们在 vue 文件中使用 vuex

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
<template>
<section class="p-10">
<h1>{{ value }}</h1>
<h1>{{ result }}</h1>
<el-button type="danger" @click="change">点击</el-button>
</section>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from "vuex";
export default {
data() {
return {
result: false,
};
},
computed: {
...mapGetters("filter", ["include"]),
...mapState({
value: (state) => state.filter.value,
}),
},
methods: {
...mapMutations("filter", ["SET_VALUE"]),
...mapActions("filter", ["getInfo"]),
change() {
this.result = this.include(1);
this.getInfo("你好");
this.SET_VALUE("HELLO");
},
},
mounted() {},
beforeDestroy() {},
};
</script>

在 vue 文件中,首先通过 import { mapState, mapMutations, mapActions, mapGetters } from ‘vuex’ 来引入我们需要的模块,按需引用,只需要引入本页面用到的模块即可
mapGetters 和 mapState 需要在页面的计算属性 computed 中引入, mapMutations 和 mapActions 需要在 methods 中引入,此时要注意模块的命名空间,如果 vuex 文件导出时标注了 namespaced,我们使用时也需要写出才可以找到,反之则不需要
首先是 mapState,使用 mapState 时,我有两种方法来取,两种方式都可以,这个方法是从 store 中取出这个变量,然后显示在此页面上,store 变动的话,此页面也会跟着动态改变
1.1 实例

1
...mapState({ value: state => state.filter.value })

1.2 实例

1
...mapState('filter', { value: state => state.value })

MapMutation 是更改 store 中状态的唯一方法,Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
mapAction 类似于 mutation, 但是 Action 提交的是 mutation,而不是直接变更状态,Action 可以包含任意异步操作,我们一般把异步获取数据的方法都放在这里,然后在回调函数里使用 mutation 里的方法把异步获取的数据保存在 store 里,然后把 store 里的数据传到页面

4、使用 QS 库

axios 默认的 content-type 是 application/json  也就是 java 后端经常让你把参数放在 body 中的那种格式 传输的样式是  requestbody

1
{ name:xxx, age:xxx }

如果使用的 qs 进行序列化
那么 content-type 就是 application/x-www-form-urlencoded
也就是常说的表单提交
传输的样式是  formdata

1
name:xxx, age:xxx

总结,实际上 urlencoding 后是  name=xxx&age=xxx
ajax 请求的 get 请求是通过 URL 传参的(以?和&符连接),而 post 大多是通过 json 传参的。 qs 是一个库。里面的 stringify 方法可以将一个 json 对象直接转为(以?和&符连接的形式)。

5、FAQ

Q:Cannot assign to read only property ‘exports’ of object

请检查您的项目是否存在  module.exports = xyz  表达,因为 webpack 2 中不允许混用 import 和 module.exports

作者

Catooilg

发布于

2020-10-15

更新于

2023-05-28

许可协议

评论