一、vuex是做什么的?
- vuex是一个集中式的存储管理中心,vuex中可以用来存储数据(状态)
- vuex也是一个状态管理中心,它可以进行状态的管理
二、什么是状态?
- 我们使用一条数据去管理一个视图,那么这个数据我们就称之为’状态’。
三、什么是状态管理模式?
- 我们使用一条数据去管理一个视图,那么这种管理模式我们称之为状态管理。
四、什么时候使用vuex
- 中大型应用使用
五、vuex 的开发流程
思维流程:
component-----发送请求
actions-----处理 修改状态
mutation----业务逻辑 修改state
getters-----读取state,渲染到component
四种使用方案
- 前:标准 ----- 后:标准
- 前:标准 ----- 后:非标准
- 前:非标准 ----- 后:标准
- 前: 非标准 ----- 后:标准
(前)(view)component ---dispatch---> actions ---commit--->mutations---state <----getters----component(后)
创建项目
$ vue create vuex_pro
安装vuex
$ npm install vuex --save
或 $ yarn add vuex
在项目目录src中新建文件夹store,并建立index.js文件,创建一个 store作为仓库,并配置一些选项
在整个项目的入口文件main.js,根实例中注册,以便整个项目使用方便
举个例子说明整个流程
点击按钮,实现数据,以及视图的动态变化
1. 前:标准 ----- 后:标准
1、首先我们需要将已存在的数据渲染到页面上
配置实例项
getter中方法
state中数据
通过this.$store.getter.getCount可以拿到数据,并渲染到页面
2、点击 页面+按钮改变数字显示
过程:
(1)用户点击通过dispatch发送请求
<template>
<div id="app">
<button @click="increment"> + </button>
<p> {{this.$store.getters.getCount}} </p><-- 通过getter获取数据-->
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
count: 0
}
},
methods:{
increment(){
console.log(this.$store)
//dispatch可以接收两个参数(actions中方法的名称,传递给actions的数据)
this.$store.dispatch('increment')//请求一个字符串,该字符串为actions对象中方法名称
},
}
</script>
//store中配置文件
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state.js'
import actions from './actions.js';
import mutations from './mutations.js';
import getters from './getter.js';
Vue.use(Vuex);
const store = new Vuex.Store({
state,//数据状态
actions,
mutations,//动作触发者,修改数据
getters,//数据s获取者
})
export default store;
// actions.js文件内容
//actions是一个对象,它里面存放的是方法,这些方法来创建一个动作,这个动作需要用commit来发送
import * as type from './type.js'//存放动作类型的type 文件
const actions = {
increment({ commit }){//可以接收两个参数,第一个为store对象,第二个为前台组件发送过来的数据
let action = {
type :type.INCREMENT//动作的类型
}
commit(action)
}
}
export default actions
//mutations.js文件内容
// mutations是一个对象,里面存储的是方法,方法名称为actions方法中的动作类型
import * as type from './type'
const mutations = {
[type.INCREMENT]( state,action ){//state是state中的数据,action是actions中的commit的发送内容
state.count++
}
}
export default mutations;
这种为前:标准-------后:标准的vuex开发流程
2. 前:标准 ----- 后:非标准
<template>
<div id="app">
<button @click="increment"> + </button>
<p> {{this.$store.state.count}} </p> <-- 直接通过state获取数据,不通过getter-->
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
count: 0
}
},
methods:{
increment(){
console.log(this.$store)
this.$store.dispatch('increment')
}
}
}
</script>
//其他配置文件不变
前:标准 ----- 后:非标准 的vuex开发流程省去getters方法,直接从state上获取数据
3. 前:非标准 ----- 后:标准
<template>
<div id="app">
<button @click="increment"> + </button>
<p> {{this.$store.getters.getCount}} </p><-- 通过getter获取数据-->
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
count: 0
}
},
methods:{
increment(){
console.log(this.$store)
this.$store.commit('INCREMENT')//直接发送请求到mutations中,省略dispatch方法
}
}
</script>
前:非标准 ----- 后:标准 这种vuex开发流程,component直接通过commit发送请求到mutations,mutations对象中方法修改数据,通过getters获取数据渲染到页面
4. 前: 非标准 ----- 后:标准
<template>
<div id="app">
<button @click="increment"> + </button>
<p> {{this.$store.state.count}} </p> <-- 直接通过state获取数据,不通过getter-->
</div>
</template>
<script>
export default {
name: 'app',
data(){
return {
count: 0
}
},
methods:{
increment(){
console.log(this.$store)
this.$store.commit('INCREMENT')//直接发送请求到mutations中,省略dispatch方法
}
}
</script>
前: 非标准 ----- 后:标准 :这种vuex开发流程,component直接通过commit发送请求到mutations,mutations对象中方法修改数据,后省去getters方法,直接从state上获取数据。
五、 vuex中mapActions, mapMutations, mapGetters工具
上面例子中请求,无论是actions对象,还是mutations对象中都只包含一个方法,所以我们通过,dispatch,或者commit可以发送请求,但是如果actions对象,mutations对象包含多个方法时,我们需要通过重复上面代码去请求,容易造成代码冗余。
所以我们可以使用 :vuex中mapActions, mapMutations, mapGetters工具,使用解构赋值的方法发送请求:
例:
<template>
<div id="app">
<button @click="increment"> + </button>
<p> {{getCount}} </p> <-- 直接通过解构获取数据 -->
</div>
</template>
<script>
import {mapGetters,mapActions,mapMutations}from 'vuex'
export default {
name: 'app',
data(){
return {
count: 0
}
},
computed:{
...mapGetters(['getCount'])
},
methods:{
...mapActions(['increment']),
...mapMutations(['INCREMENT'])
},
}
</script>
这段代码与上面代码实现效果相同,是不是看起来,更清晰,更简单。
六、vuex核心概念之module使用
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
我们简单看一下,module模块的使用。
下述例子可以实现数据的双向绑定功能
- 1、首先我们可以单独定义一个模块文件
//home模块js文件----home.js
const homeStore = {
state:{
todos:[
{
id:1,
task:'打球'
},
{
id:2,
task:'敲代码'
}
]
},
actions:{
addtodos({commit},payload){//可以接收两个参数,第一个为store对象,第二个为前台组件发送过来的数据
let action = {
type:'ADDTODOS',
payload
}
commit( action );//通过commit方法将action(用户请求内容)发送出去
},
},
mutations:{
['ADDTODOS']( state,action ){//接收到actions中发送的内容,并根据请求对state中的数据进行修改
console.log(action.payload)
state.todos.push({
id:state.todos.length+1,
task:action.payload
})
}
},
getters:{//通过getters方法,将state中数据渲染到页面
getTodos(state){
return state.todos
console.log(state)
}
},
};
export default homeStore;
- 2、在我们的store仓库index.js中导入上述分割模块
import Vue from 'vue';
import Vuex from 'vuex';
import homeStore from './home/home.js';//模块导入
Vue.use(Vuex);
const store = new Vuex.Store({
// state,//数据状态
// actions,
// mutations,//动作触发者,修改数据
// getters,//数据s获取者
modules:{//数据分块
homeStore
}
})
export default store;
- 3、创建一个组件,将模块数据渲染到组件模板中
//home.vue文件
<template>
<div>
<input type="text" @keyup.enter="addtodos(val)" v-model="val">
<ul>
<li v-for="item in getTodos" :key="item.id"> {{item.task}} </li>
</ul>
</div>
</template>
<script>
import { mapGetters, mapActions, mapMutations } from 'vuex';
export default {
data(){
return {
val:''
}
},
methods:{
...mapActions(['addtodos']),//用户在input中输入数据,按下enter键发送请求,请求携带输入数据
...mapMutations(['ADDTODOS']),
},
computed:{
...mapGetters(['getTodos'])//结构得到getters对象中方法的数据,渲染至页面
}
}
</script>
- 4、将组件在根实例中进行注册使用,将数据渲染到页面
//App.vue文件
<template>
<div id="app">
<Home></Home>
</div>
</template>
<script>
import {mapGetters,mapActions,mapMutations}from 'vuex';
import Home from './components/home'
export default {
name: 'app',
components:{
Home
},
}
</script>
以上,为vuex中核心概念中module的简单使用流程。