30分钟彻底搞懂Vuex

229 阅读7分钟

VUEX是什么?能干什么?为什么要用VUEX?

VUE页面其实是由各个组件构成的,组件之间通信传值不可避免,父子组件之间传值相对容易,但是兄弟组件之间传值就不那么容易了,为了实现兄弟组件之间的传值,我们可能会写很多冗余的代码,也不太好维护。

一切困难的出现,也是代表新技术的革新~~~

不错,VUEX就是为了解决组件之间传值而诞生的。

VUEX的核心思想就是把数据放到一个公共的仓库里,然后用规定的方法去调用和维护这些数据

如上图,state的变化可以引起视图View的更新,视图View上可以触发一些事件(如客户的点击等)调用Actions方法,Actions方法的执行可以引起State的变化,这样就形成了闭环

说到VUEX,很多人认为已经学习了很多次了,甚至在工作中也使用了很多次,但是再次使用还得查资料,究其原因还是没有掌握真正的学习方法。由于人类的记忆是会时间遗忘的,这不可避免。所以造成 大多数人吸收知识的过程是“进-出”,真正的过程应该是“进-吸收-出” 只有真正的掌握学习一门新技术的正确姿势,才会有越来越多的知识储备,越来越牛逼~~~

那怎么样才是正确的学习方法呢?

来了解一个词 “学以致用”先学再用,而我们很多时候就是没有真正的学会就去用了,这样就造成了用多少次还是不了解。

怎么样才是正确的了解方法呢?

正如我们了解人的本能作用不凡先看看人的结构,人的部位包含耳朵,鼻子,眼睛,嘴巴,手脚,大脑等;耳朵可以听声音,鼻子可以闻味道;眼睛可以看东西;嘴巴可以吃东西;手脚可以干活走路;大脑可以思考;这些部位的作用构成了人的作用,人可以听、闻、看、吃、工作、走路、思考等。我们用这种 先分解在组装合并;从内到外逐层了解的思想 去学习,就可以彻底了解并学会一门新技术。

今天我们讲的主角是vuex,要想彻底学会VUEX,我们需要先分解

vuex分为什么部分?

包含5部分,分别是state,getters,mutations,actions,modules

State是存储数据的 仓库

Getters是把state的值计算后得到的新值,我们可以理解为 计算属性

Mutations 是 改变state 的唯一方式,利用 commit mutations 的方式,修改仓库数据

Actions 通过触发mutations来修改仓库数据,利用 dispatch actions 的方式调用actions,然后在actions里commit mutations 达到改变仓库数据的目的。

Modules字面意思就是模块,这个适合在大型项目中多人开发使用,如果项目小没有必要使用;

可能不太好理解mutations和actions,我们可以这么认为,要改变state数据mutations和actions都需要,mutations用于直接修改仓库数据,但是什么时候触发呢,actions用于触发mutations

不好理解就举个栗子🌰

如上图我们点击➕,应该通过dispatch触发actions里的submitSetCount,然后在submitSetCount里通过commit触发mutations里的setCount,这是一个连贯的过程,就跟我们走路,膝关节动起来,步子就迈开了,膝关节就好比actions,迈开步子就好比mutations。

mutations: {
    setCount (state, payload) {
        state.count += payload
    }
},
actions: {
    submitSetCount(context, payload) {
        context.commit('setCount', payload)
    }
}

这样我们在actions方法里要做的就是commit一个mutations里定义的方法,并把需要的值传给mutations里对应的方法

可以理解为由客户调用,就跟上面这个设置步长的图,客户可以点击加号或减号,点击的过程我们就可以触发actions,这样我们对VUEX就有一个完整的理解了,仓库的里的数据由mutations改变,mutations由actions触发,actions由客户触发。

掌握了基本的思路后,我们接下来就开始使用了,相信这样的使用方式一定是 有思想的使用

VUEX的使用步骤

第一步安装vuex

npm install vuex --save

第二步,根目录下建store文件夹,文件夹里建index.js,引入vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

第三步,在main.js中,引用上一步新建的index.js,并全局引用store

import store from '../store/index'

new Vue({
  store,//置入vue中,全局引用vuex
  render: h => h(App),
}).$mount('#app')

第四步,在store/index.js中写仓库数据

改变state的唯一方法是通过commit提交mutations方法,官方建议修改state数据都要通过dispatch一个actions方法,然后在actions方法里commit一个mutations方法,这样看起来就是下面这个过程

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex)
const store = new Vuex. Store({
    state: {
        count: 1,


    },
    getters: {
        changeCount (state, getters) {
            return store.state.count*2 + 1
        }
    },
    mutations: {
        setCount (state, payload) {
            state.count += payload
        }
    },
    actions: {
        submitSetCount(context, payload) {
            context.commit('setCount', payload)
        }
    }
})

export default store

我们注意到,上面

getters的参数([state] [,getters]) state是vuex的state的值,getters是仓库中定义的所有getters属性

mutations的参数([state] [,payload])

state代表仓库数据,payload代表commit的时候传的参数

actions的参数([context] [,payload])

[context]参数下面会讲到,payload同样是调用的时候传的参数

第五步,在页面中使用仓库中数据,页面中操作改变数据

<template>
  <div id="app">
    <p>{{this.$store.state.count}}</p>
    <br>
    <p>{{this.$store.getters.changeCount}}</p>
    <button @click="changeCount">点击一下</button>
  </div>
</template>

<script>

export default {
  name: 'App',
  methods: {
    changeCount() {
        this.$store.dispatch('submitSetCount',3)
    }
  }
}
</script>

大家可以执行这些例子,会发现VUEX是如此的简单

读到这里,我们已经掌握了VUEX的基本使用,可以在项目中大显身手了,但是如果要达到炉火纯青的地步,接着往下读,相信你会得到更多的收获~~~

简短的页面调用方式

上面操作仓库数据的方法太长,有没有简短的方式呢?

vuex提供了mapState,mapGetters,mapMutations,mapActions方法,分别对应state,getters,mutations,actions;

首先我们要导入这些方法

import { mapState, mapGetters, mapActions } from 'vuex'

computed: {    
    ...mapState([      
        'count'    
    ]),    
    ...mapGetters([      
        'changeCount'    
    ])  
}

对于mapState和mapGetters我们可以理解为计算属性,要放入computed里 对于mapMutations和mapActions我们可以理解为方法,要放入methods中

我们看下面经过改造的例子

<template>
  <div id="app">
    <p>{{count}}</p>
    <br>
    <p>{{changeCount}}</p>
    <button @click="clickCount">点击一下</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
  name: 'App',
  computed: {
    ...mapState([
      'count'
    ]),
    ...mapGetters([
      'changeCount'
    ])
  },
  methods: {
    ...mapActions([
      'submitSetCount'
    ]),
    clickCount() {
        this.submitSetCount(3)
    }
  }
</script>

对于mapState,mapGetters,mapMutations,mapActions我们可以理解为封装好的函数,直接调用这些会精简我们的项目

如果大型项目,我们需要更加精简项目,这时候modules就派上用场了

modules是什么?怎么用?

当项目庞大,多人参与开发的时候,我们上面写的VUEX文件将会非常庞大,维护起来难度也加大, 一切困难的出现,也是代表新技术的革新~~~ ,modules就是来解决这个问题的,modules的字面意思是“模块”,它的思路就是把vuex分为各个模块,每个模块处理一类事情,每个模块写在单独的文件里,然后在一个总的文件里导入这些模块,每个模块都包含state,getters, mutations, actions,甚至包含子模块。

废话说多了难理解,举个🌰

store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex)

import login from './login'
import order from './order'

export default new Vuex.Store({
    modules: {
        login,
        order
    }
})

store/login.js

const login = {
    state: {
        name: 'Lili'
    },
    getters: {
        changeName (state, getters) {
            return '我是' + login.state.name
        }
    },
    mutations: {
        setName (state, payload) {
            state.name  = payload
        }
    },
    actions: {
        submitSetName(context, payload) {
            console.log(context,'79')
            context.commit('setName', payload)
        }
    }
}

export default login

store/order.js

const order = {
    state: {
        id: 1
    },
    getters: {
        changeId (state, getters) {
            return order.state.id*2 + 1
        }
    },
    mutations: {
        setId (state, payload) {

            state.id += payload
        }
    },
    actions: {
        submitSetId(context, payload) {
            context.commit('setId', payload)
        }
    }
}

export default order

我们分开模块了,接下来就需要思考怎么调用这些模块中的state,getters, mutations, actions?

<template>
  <div id="app">
    <p>{{name}}</p>
    <br>
    <p>{{changeName}}</p>

    <p>{{id}}</p>
    <br>
    <p>{{changeId}}</p>
    <button @click="clickName">点击改变名字</button>
    <button @click="clickId">点击改变订单ID</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapActions } from 'vuex'
export default {
  name: 'App',
  computed: {
    ...mapState([
      'name',
      'id'
    ]),
    ...mapGetters([
      'changeName',
      'changeId'
    ])
  },
  methods: {
    ...mapActions([
      'submitSetName',
      'submitSetId'
    ]),
    clickName() {
        this.submitSetName("TOM")
    },
    clickId() {
        this.submitSetId("22")
    }
  }
}
</script>

通过这个例子,我们看到调用方式几乎是一模一样的

仔细思考,如果A模块和B模块之间想互相取值怎么办

我们看一下下面例子,参数context是什么

actions: {
    submitSetName(context, payload) {
        console.log(context,'79')
        context.commit('setName', payload)
    }
}

"context"打印出来是

原来context参数是一个对象,包含了很多属性,比如可以通过rootState,取到所有模块中store中数据

到这里我们的VUEX课程就讲完了,觉得好的话,记得给我点赞鼓励一下~~~