什么是vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能
好的 完全看不懂
简单来讲,我们可以把一些货物一起放在一个仓库之中,可以让我们与货物的距离只有一条通道,当我们去存取货物的时候,里面的东西是共有的,大家都能公用,谁都可以往里面进行存取操作
安装、使用 vuex
npm install vuex --save
在src目录下手动创建目录文件 vuex/store.js
在main.js中配置
import Vue from 'vue'
import App from './App'
import router from './router'
import vuex from 'vuex'
Vue.use(vuex)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
在vuex/store.js中配置
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex); //必不可少
const state={
count:1
}
export default new vuex.Store({ //暴露vuex.store
state
})
在需要调用的组件中引入
import store from '@/vuex/store'
export default {
store //一定要在实例中注册
}
获取store中的state
<template>
<div>
{{$store.state.count}} //1
</div>
</template>
此处提前说明一下moudle 模块组,随着数据组件状态越来越多,同写一个文件不好维护
新建一个js 暴露出来
export default {
state:{
count:1
}
}
在store.js中导入
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
import states from './state'
export default new vuex.Store({
modules:{ //此参数固定
state:states
}
})
{{$store.state.state.count}}
//1
其实只是相当于多了一层导入,方便我们调用维护状态
回到开始
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
export default new vuex.Store({
state
})
简单改变state
<template>
<div>
{{$store.state.count}}
<p>
<button @click="change">Change</button>
</p>
</div>
</template>
<script>
import store from '@/vuex/store'
export default {
store,
methods:{
change(){
this.$store.state.count++
}
}
}
</script>
<style>
</style>
强行改变vuex的state 是流氓行为(违法)
Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
简单粗暴理解: 我们要把我们需要做状态管理的量放到这里来,然后在后面的操作动它
我们有了state状态树,我们要改变它的状态(值),就必须用vue指定唯一方法 mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。
简单粗暴理解:任何不以mutation的方式改变state的值,都是耍流氓(违法)
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
const mutations={ //简单编辑操作state的mutations (固定写法)
add(state){ //此处的state就是上面的state对象
state.count++;
},
reduce(state){
state.count--;
}
}
export default new vuex.Store({
state,mutations
})
在组件中调用mutations
<template>
<div>
{{$store.state.count}}
<p>
<button @click="$store.commit('add')">+</button> //此处的调用方法注意一下 是commit
//可不是$store.mutations.add
<button @click="$store.commit('reduce')">-</button>
</p>
</div>
</template>
<script>
import store from '@/vuex/store'
export default {
store,
}
</script>
<style>
</style>
此时已经可以通过按钮通过mutations改变state了
在渲染vue的时候,根据钩子函数生命周期渲染不同的DOM,一般情况下我们不用直接引用,而是赋值computed
computed属性可以在输出前,对data中的值进行改变,我们就利用这种特性把store.js中的state值赋值给我们模板中的data值。
export default {
store,
computed:{
count(){ //将状态赋值给count
return this.$store.state.count;
}
}
}
相应的改变插值中的内容 效果不变
<template>
<div>
{{count}}
<p>
<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>
</p>
</div>
</template>
此写法稍微有些麻烦,数据多了更是繁琐
vuex为我们提供了mapState操作
首先先引入mapState
import store from '@/vuex/store'
import {mapState} from 'vuex';
在computed中进行赋值 效果是一样的 motations也可运行
computed:mapState({
count:state=>state.count
})
可能箭头函数有点懵
computed:mapState({
count:function(state){
return state.count
}
})
接下来设置一下参数,方法肯定有时候带参数的嘛 在store.js中
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
const mutations={
add(state,n){ =>此处增加了一个参数n
state.count+=n;
},
reduce(state){
state.count--;
}
}
export default new vuex.Store({
state,mutations
})
接下来只需要在调用mutation方法处传入实参即可
<template>
<div>
{{count}}
<p>
<button @click="$store.commit('add',10)">+</button>
<button @click="$store.commit('reduce')">-</button>
</p>
</div>
</template>
类似开始的state 调用方法有些繁琐 不喜欢看到$store.commit( )
模板获取Mutations方法 vuex也为我们提供了相应的方法
import store from '@/vuex/store'
import {mapState,mapMutations} from 'vuex'; =>引入模板
方法 我们写在methods中
methods:mapMutations([
'add','reduce'
]),
然后改变html 这样就跟vue一样啦
<template>
<div>
{{count}}
<p>
<button @click="add(10)">+</button>
<button @click="reduce">-</button>
</p>
</div>
</template>
getters计算过滤操作
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
const mutations={
add(state,n){
state.count+=n;
},
reduce(state){
state.count--;
}
}
const getters = {
count:function(state){
return state.count +=100; =>类似filters 过滤得到state
}
}
export default new vuex.Store({
state,mutations,getters
})
在组件中获取过滤之后的state
import store from '@/vuex/store'
import {mapState,mapMutations} from 'vuex';
export default {
store,
computed:mapState({
count:function(state){
return state.count
}
}),
methods:mapMutations([
'add','reduce'
]),
}
我们先分析一下当前代码
我们都知道代码属性相同会覆盖,也就是我如果在写一次coumped属性那么上面的原有属性将会覆盖,此处运用es6的扩展运算符进行改写
import store from '@/vuex/store'
import {mapState,mapMutations} from 'vuex';
export default {
store,
computed:{
...mapState(["count"]),
count(){
return this.$store.getters.count;=>此时count是过滤后的state
}
},
methods:mapMutations([
'add','reduce'
]),
}
mapState通过扩展运算符将$store.state.count 映射this.count 这个this 很重要,这个映射直接映射到当前Vue的this对象上。(这句话不懂也可以记一下)
此时有测试的小伙伴可能发现 count是110 110 加的 而不是10 10 加的
因为当count发生改变的时候 先通过getters过滤得到新的state(此时已经+100) 然后由mutation改变+10
用mapGetters简化模板写法
import store from '@/vuex/store'
import {mapState,mapMutations,mapGetters} from 'vuex';
export default {
store,
computed:{
...mapState(["count"]),
...mapGetters(["count"])
},
methods:mapMutations([
'add','reduce'
]),
}
其实这里mapMutation也可以简写,我想大家知道怎么写了
actions异步修改状态
actions和之前讲的Mutations功能基本一样,不同点是,actions是异步的改变state状态,而Mutations是同步改变状态。至于什么是异步什么是同步这里我就不做太多解释了
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
const mutations={
add(state,n){
state.count+=n;
},
reduce(state){
state.count--;
}
}
const getters = {
count:function(state){
return state.count +=100;
}
}
const actions ={
addAction(context){
context.commit('add',10) =>之前说过 mutation方法通过 commit调用 忘记了可以翻翻前面哦
},
reduceAction({commit}){
commit('reduce')
}
}
export default new vuex.Store({
state,mutations,getters,actions
})
这是两处不同的引用mutations的方法
增加actions 当然 里面的方法名是自定义的
context --- {commit}
context:上下文对象,这里你可以理解称store本身。
{commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了。
模板中使用actions
import store from '@/vuex/store'
import {mapState,mapMutations,mapGetters,mapActions} from 'vuex';
export default {
store,
computed:{
...mapState(["count"]),
...mapGetters(["count"])
},
methods:{
...mapMutations(['add','reduce']),
...mapActions(['addAction','reduceAction'])
}
}
其实写法太简单了 练两下就soeasy了
调用异步方法名
<template>
<div>
{{count}}
<p>
<button @click="addAction">+</button>
<button @click="reduceAction">-</button>
</p>
</div>
效果相同 因为只是操作mutation的方法 将其转换为异步
dispatch
修改了一下代码,可以直接复制,为了让效果更明显
store.js
import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex);
const state={
count:1
}
const mutations={
add(state,n){
state.count+=n;
},
reduce(state){
state.count--;
}
}
const actions ={
addAction(context){
context.commit('add',10)
},
reduceAction({commit}){
commit('reduce')
}
}
export default new vuex.Store({
state,mutations,actions
})
vue组件
<template>
<div>
{{count}}
<p>
<button @click="addAction">+</button>
<button @click="reduceAction">-</button>
</p>
</div>
</template>
<script>
import store from '@/vuex/store'
import {mapState,mapMutations,mapActions,mapGetters} from 'vuex';
export default {
store,
computed:{
...mapState(["count"]),
},
methods:{
// ...mapActions(['addAction','reduceAction'])
addAction(){
this.$store.dispatch('addAction',10)
},
reduceAction(){
this.$store.dispatch('reduceAction')
}
}
}
</script>
<style>
</style>
可以做下比较,dispatch其实就是相当于mutation的commit调用,我们使用map映射省略dispatch,昨天有位小伙伴问我dispatch是什么突然卡了,果然太久没敲就尴尬了
区别:
dispatch:含有异步操作,写法: this.$store.dispatch('actions方法名',值)
commit:同步操作,写法:this.$store.commit('mutations方法名',值)
还是建议多用map映射
vuex-persistedstate简单使用
npm install vuex-persistedstate -D
在store.js中引入
import Vue from 'vue'
import vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
Vue.use(vuex);
const state={
count:1
}
const mutations={
add(state,n){
state.count+=n;
},
reduce(state){
state.count--;
}
}
const actions ={
addAction(context){
context.commit('add',10)
},
reduceAction({commit}){
commit('reduce')
}
}
export default new vuex.Store({
plugins: [createPersistedState()], //添加这句即可 默认存储本地localSrorage 更多配置可以百度一下
state,mutations,actions
})
因为我们的操作都是操作state的 因此只存储state的变化 小伙伴可以自己试一下
网友评论