什么是Vuex ?
Vuex是专门为Vue.js应用开发的状态管理模式,采用集中式存储所有组件的状态,让组件之间可以通信
用人话说就是: vuex就是专门用来管理vue的数据的,统一在一个文件中存储公共的数据
Vuex中有个5个内容需要学习:
- state — 存储公共的数据
- mutations — 修改数据
- getters — 类似与computed(计算属性),用于计算数据后得到新的数据
- actions — 用于发起异步的请求(获取数据)
- modules — 模块化拆分
- 重点: 需要掌握state和mutations 的使用
使用步骤:
- 下载vuex (npm i vuex)
- 在src目录下创建一个文件夹统一取名为 store ,在store中创建index.js
- 新建的index.js中有如下代码:
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
state: {},
mutations: {},
getters: {},
actions: {},
modules: {}
})
注意: 别忘了向Vue实例中注入store
import store from './store'
new Vue({
store,
render: h => h(App),
}).$mount('#app')
1. state
state类似于组件中的data(){return{}} 用来存放数据
示例:
export default new vuex.Store({
// 手动定义一些数据
state:{
a: 10
}
})
接下来我们在组件中获取并使用一下这个公共的数据
<template>
<div>
{{$store.state.a}} // 页面中打印出10
</div>
</template>
2. mutations
mutations主要用于修改state中的数据
参数一: state对应 state对象
参数二: 形参- 需要传入的参数,可有可无
语法: mutations:{‘mutations名’:funtion(state,形参) }
例子: 在state中a = 10 , 我们定义一个mutations方法 对state中的a的值进行修改
代码如下:
export default new vuex.Store({
state: {
a: 10
},
mutations: {
state.a += 1 // a+1
},
})
接下来在App.vue中我们写一个button按钮用来点击并调用这个方法 点一次触发一次 让a的值每次加一
<template>
<div>
{{$store.state.a}}
// 点击一次 就调用一次 进行+1
<button @click="$store.commit('add')">a+1</button>
</div>
</template>
注:
- 在模板中: $store.commit(‘mutations名’)
- 在组件中: 要加this调用, this.$store.commit(‘mutations名’)
3. getters
语法: getters:{ ‘getters名’,function(state,形参)},用法和mutations差不多,
getters的作用是用于计算数据得到计算后的新的数据 类似于computed计算数据
示例: 例如在state中有一个值为b:[1,2,3,4,5],
用getters对这个数据进行计算 然后打印到页面中,具体代码如下:
getters: {
sum: function (state) {
return state.b.reduce((temp, item) => temp + item, 0)
}
}
在页面中渲染出来{{$store.getters.sum}} // 15
4. actions
语法: actions:{ ‘action名’,function(context,形参)}
context其实就是对应的state .
actions用于发起异步的请求,可以在actions中用axios发起数据请求,获取数据
继续看示例代码:
//
state:{
book:[ ]
},
mutations:{
updateBook:function(state,newbook){
state.book = newbook
}
}
actions: {
getBooks: function (context) {
axios({
url: 'https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books',
method: 'get'
}).then(res => {
console.log(res);
context.commit('updateBook', res.data.data)
})
}
}
注意: 在state中我定义了一个数组 book:[ ]用来接收获取到的数据 , 接收到数据res后, 想赋值给book数组, 但是要记住不能直接进行赋值,必须要在mutations中定义一个赋值的函数, 在actions获取到数据.调用mutations中的函数,进行赋值.
接着组件中写一个button按钮用来测试 触发actions发起axios请求获取数据,并赋值给book数组
调用actions的方式:
模块中: $store.dispatch(‘actions名’)
组件中: this.store.dispatch(‘actions名’)
<template>
<div>
// 点击 触发actions 并发起axios请求数据
<button @click="$store.dispatch('getBooks')">获取数据</button>
{{$store.state.book}} // 打印获取到的数据
</div>
</template>
modules
modules默认namespaced: 为false ,设置true后.,在组件中使用拆分到modules的数据和方法要加"模块名"
语法: modules:{ ‘模块名’:{state{},mutations:{},getters:{},actions:{} }}
modules用来拆分index.js中的代码, 减少index.js中代码的繁多和体积,让index.js中更简洁,把相同的需要的数据和方法都提取到同一个js中
示例: 这里我就随便的写几个进行拆分提取
前提: 在store文件中新建modules文件,把state中book数组和mutations中修改book的方法
以及actions中获取数据的相关代码剪切到,modules文件中的新建的allBook.js文件中
import axios from 'axios'
export default {
state: {
b: [1, 2, 3, 4, 5],
book: []
},
mutations: {
updateBook: function (state, newbook) {
state.book = newbook
}
},
getters: {
sum: function (state) {
return state.b.reduce((temp, item) => temp + item, 0)
}
},
actions: {
getBooks: function (context) {
axios({
url: 'https://www.fastmock.site/mock/37d3b9f13a48d528a9339fbed1b81bd5/book/api/books',
method: 'get'
}).then(res => {
console.log(res);
context.commit('updateBook', res.data.data)
})
}
}
}
抽离到allBook.js中后,在index.js中引入,并添加到modules对象中
import Vue from 'vue'
import vuex from 'vuex'
import allBook from './modules/allBook.js'
Vue.use(vuex)
export default new vuex.Store({
modules: {
allBook
}
})
注意: 抽离后.组件中调用的方式就变了, 还记得我们加了namespaced: true这句话, 加了之后,引用数据和方法时都必须要加上模块名了
示例: 如何调用
以及其他三个调用方式:
// 例子:
1. // 原先写法: {{$store.getters.sum}} // 15
2. // 抽离后的写法: {{$store.gerters['allBook/sum']}} // 15
// 这里我都列举一下其他三种的方式
// state:
$store.state.模块名.属性名
// mutations:
$store.commit('模块名/mutation名')
// getters:
$store.gerters['模块名/getter名']
// actions:
$store.dispatch('模块名/action名')
补充: 如果要修改state/mutations/getters/actions名字,例如:可以这样写 $store.commit(‘模块名,{新名字,久名字}’) ,其他的格式都类似如此
Vuex的辅助函数map系列用法汇总
mapState/mapMutations/mapGetters/mapActions
用来优化访问的方式, 普通的写法太麻烦了,利用vuex内置的方法,可以简洁的引用vuex中的数据和方法
1. mapState函数
将state中的变量映射到当前组件中使用
使用步骤,代码如下:
// 当前组件中 按需引入mapState
// 例如引用vuex中state中的变量 c:30
<template>
{{c}} // 30
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['c'])
// 如果需要改名字的话
...mapState({'新名字':'旧名字'})
}
}
</script>
computed:{ …mapState() } 这里的…是对象的展开运算符,整体来看是对象的合并。
2. mapMutations
不多bb ,上代码自行体会:
// 在state中定义一个变量为a:10
// App.vue组件中
<template>
<div>
{{a}}
<button @click="abb">点击+1</button>
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
export default {
computed: {
...mapState(['a'])
},
methods: {
...mapMutations(['add'])
},
}
</script>
// index.js中
export default new vuex.Store({
state: {
a: 10,
},
mutations: {
add: function (state) {
state.a += 1
}
},
})
以上列举了mapState和mapMutations的语法,其他两个(mapGetters和mapActions)用法和前两个都是一样的,自行体会吧,脖子酸了,休息会,不写了
接下来讲一下在全局中和modules情况下使用map系列的用法:
如何使用全局state
-
直接使用: this.$store.state.xxx;
-
map辅助函数:
computed: { ...mapState(['xxx']), ...mapState({'新名字': 'xxx'}) }
如何使用modules中的state
-
直接使用: this.$store.state.模块名.xxx;
-
map辅助函数:
computed: { ...mapState('模块名', ['xxx']), ...mapState('模块名', {'新名字': 'xxx'}) }
如何使用全局getters
-
直接使用:
this.$store.getters.xxx
-
map辅助函数:
computed: { ...mapGetters(['xxx']), ...mapGetters({'新名字': 'xxx'}) }
如何使用modules中的getters
-
直接使用:
this.$store.getters.模块名.xxx
-
map辅助函数:
computed: { ...mapGetters('模块名', ['xxx']), ...mapGetters('模块名',{'新名字': 'xxx'}) }
如何使用全局mutations
-
直接使用:
this.$store.commit('mutation名', 参数)
-
map辅助函数:
methods: { ...mapMutations(['mutation名']), ...mapMutations({'新名字': 'mutation名'}) }
如何使用modules中的mutations(namespaced:true)
-
直接使用:
this.$store.commit('模块名/mutation名', 参数)
-
map辅助函数:
methods: { ...mapMutations('模块名', ['xxx']), ...mapMutations('模块名',{'新名字': 'xxx'}) }
如何使用全局actions
-
直接使用:
this.$store.dispatch('action名', 参数)
-
map辅助函数:
methods: { ...mapActions(['actions名']), ...mapActions({'新名字': 'actions名'}) }
如何使用modules中的actions(namespaced:true)
-
直接使用:
this.$store.dispatch('模块名/action名', 参数)
-
map辅助函数:
methods: { ...mapActions('模块名', ['xxx']), ...mapActions('模块名',{'新名字': 'xxx'}) }
Vuex中五大核心和actions/mutations/state思路图
- 五大核心API
- Actions
- State和Mutations