第四章Vuex

文章目录

  • Vuex简介
      • Vuex是什么
      • 什么时候使用Vuex
      • Vuex工作原理
  • Vuex环境搭建
      • 下载vuex
      • 创建src/store/index.js
      • 传入store配置项
  • 求和案例
    • 纯vue版本
    • Vuex版本
  • getters配置项
  • 四个map方法的使用
    • mapState与mapGetters
    • mapActions与mapMutations
  • 多组件共享数据
  • 模块化+命名空间

Vuex简介

Vuex是什么

  1. 概念:专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
  2. Vuex Github地址

第四章Vuex_第1张图片

第四章Vuex_第2张图片

什么时候使用Vuex

  1. 多个组件依赖于同一状态
  2. 来自不同组件的行为需要变更同一状态

多个组件依赖于同一个状态(变量),或者来自不同组件的行为需要变更同一个状态(其实就是多个不同组件的读写),最好应用vuex!

Vuex工作原理

对下图的解释:

第四章Vuex_第3张图片

  • store(其实就是上图Vuex):Actions,Mutations,State的父亲,它们三个之间的状态转换(灰色箭头的api)由store提供(store.dispatch,store.commit等等)

  • Actions:一个普普通通的Object类型对象,vc的改变会先通过store.dispatch()将值传递给action。然后经由action通过store.commit()发送给Mutations。

    • Actions还可以通过ajax和后端交互,就是下图中的Backend API,通过后端接口拿数据,也是组装到Action中

    • 如果不调用Backend API,VC可以直接将数据交给Mutations,绕开Actions。也就是说Actions是可以跳过的

      • 类似生活,Actions类似我们的服务员,Mutations类似我们的厨师,Vue Components就是我们的客户,我们点菜时,可以通过服务员去点菜,如果我们熟悉菜品,也可以不需要服务员的帮助,直接让厨师做
      • 但是如果我们不了解菜品,就肯定需要服务员的帮助,如果我们需要后端接口的数据,就类似需要服务员的帮助,就必须有Actions的介入
  • Mutations(n. 突变,变更):它是一个Object类型的对象。负责真正处理,加工修改数据,处理完成后将处理完成的数据传入State中

  • Vue的开发工具,Devtools,监测的就是Mutations里的数据

  • State:也是一个Object类型的对象,vuex会将里面的数据进行渲染,还给VC,更新VC

Vuex环境搭建

下载vuex

  • 你在vue2的项目中,只能安装vue3版本
  • 你在vue3的项目中,只能安装vue4版本
  • 所以这里安装vue3:npm i vuex@3

创建src/store/index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
   
//准备actions对象——响应组件中用户的动作、处理业务逻辑
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}
   
//创建并暴露store
export default new Vuex.Store({
   	actions,
   	mutations,
   	state
})

  • 根据上面的工作原理,store中应该至少包含 actions,mutations,state这三个东西,然后将这三个东西塞入new出来的store中,最后再暴露store:
  • 这里注意Vue.use(Vuex),如果写在我们的main.js中,我们知道import引入文件的执行是先于我们本文件js代码的执行,所以会导致我们使用vuex时,并没有引入vuex

传入store配置项

import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
import store from './store'

Vue.config.productionTip = false

Vue.use(Vuex)

new Vue({
    el:"#app",
    render: h => h(App),
    store
})

  • src/main.js中创建 vm 时传入store配置项

    • import store from ‘./store’ 自动扫描store文件夹下的index.js文件
  • store是简写 ,完整写法是 store:store

求和案例

纯vue版本

App.vue

<template>
	<div class="container">
		<Count/>
	</div>
</template>

<script>
	import Count from './components/Count'
	export default {
		name:'App',
		components:{Count}
	}
</script>

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<select v-model.number="n">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
		</select>
		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数再加</button>
		<button @click="incrementWait">等一等再加</button>
	</div>
</template>

<script>
	export default {
		name:'Count',
		data() {
			return {
				n:1, //用户选择的数字
				sum:0 //当前的和
			}
		},
		methods: {
			increment(){
				this.sum += this.n
			},
			decrement(){
				this.sum -= this.n
			},
			incrementOdd(){
				if(this.sum % 2){
					this.sum += this.n
				}
			},
			incrementWait(){
				setTimeout(()=>{
					this.sum += this.n
				},500)
			},
		},
	}
</script>

<style>
	button{
		margin-left: 5px;
	}
</style>


  • 我们操作的sum在组件本身,所以直接操作就行

Vuex版本

Count.vue







对应index.js编写

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
   
//准备actions对象——响应组件中用户的动作
const actions = {
    addOdd(context,value){
        console.log("actions中的addOdd被调用了")
        if(context.state.sum % 2){
            context.commit('ADD',value)
        }
    },
    addWait(context,value){
        console.log("actions中的addWait被调用了")
        setTimeout(()=>{
			context.commit('ADD',value)
		},500)
    },
}
//准备mutations对象——修改state中的数据
const mutations = {
    ADD(state,value){
        state.sum += value
    },
    SUBTRACT(state,value){
        state.sum -= value
    }
}
//准备state对象——保存具体的数据
const state = {
    sum:0 //当前的和
}
   
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

总结:

Vuex的基本使用:

  • 初始化数据state,配置actions、mutations,操作文件store.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)

const actions = {
    //响应组件中加的动作
	jia(context,value){
		// console.log('actions中的jia被调用了',miniStore,value)
		context.commit('JIA',value)
	},
}

const mutations = {
    //执行加
	JIA(state,value){
		// console.log('mutations中的JIA被调用了',state,value)
		state.sum += value
	}
}

//初始化数据
const state = {
   sum:0
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
})
  • 组件中读取vuex中的数据:$store.state.sum
  • 组件中修改vuex中的数据:$store.dispatch(‘action中的方法名’,数据) 或 $store.commit(‘mutations中的方法名’,数据)
    • actions中的方法也进行$store.dispatch(‘action中的方法名’,数据)

备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit

  • 为什么业务逻辑写这里面,也是有对应可能对代码进行服用,如果都想实现同一个功能,如果在单独的组件中,在别的组件中想用,则需要又写

getters配置项

count.vue







index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
   
//准备actions对象——响应组件中用户的动作
const actions = {
    addOdd(context,value){
        console.log("actions中的addOdd被调用了")
        if(context.state.sum % 2){
            context.commit('ADD',value)
        }
    },
    addWait(context,value){
        console.log("actions中的addWait被调用了")
        setTimeout(()=>{
			context.commit('ADD',value)
		},500)
    },
}
//准备mutations对象——修改state中的数据
const mutations = {
    ADD(state,value){
        state.sum += value
    },
    SUBTRACT(state,value){
        state.sum -= value
    }
}
//准备state对象——保存具体的数据
const state = {
    sum:0 //当前的和
}
//准备getters对象——用于将state中的数据进行加工
const getters = {
    bigSum(){
        return state.sum * 10
    }
}
   
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

总结:

getters配置项的使用:

概念:当state中的数据需要经过加工后再使用时,可以使用getters加工在store.js中追加getters配置

  • 非常类似我们data和计算属性的关系
const getters = {
	bigSum(state){
		return state.sum * 10
	}
}

//创建并暴露store
export default new Vuex.Store({
	...
	getters
})
  • 组件中读取数据:$store.getters.bigSum

四个map方法的使用

mapState与mapGetters

想使用需要先引入import {mapState,mapGetters} from ‘vuex’

index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
   
//准备actions对象——响应组件中用户的动作
const actions = {
    addOdd(context,value){
        console.log("actions中的addOdd被调用了")
        if(context.state.sum % 2){
            context.commit('ADD',value)
        }
    },
    addWait(context,value){
        console.log("actions中的addWait被调用了")
        setTimeout(()=>{
			context.commit('ADD',value)
		},500)
    },
}
//准备mutations对象——修改state中的数据
const mutations = {
    ADD(state,value){
        state.sum += value
    },
    SUBTRACT(state,value){
        state.sum -= value
    }
}
//准备state对象——保存具体的数据
const state = {
    sum:0, //当前的和
    name:'JOJO',
    school:'尚硅谷',
}
//准备getters对象——用于将state中的数据进行加工
const getters = {
    bigSum(){
        return state.sum * 10
    }
}
   
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

Count.vue







  • … 是ES6的格式,是将这个对象中的所有key:value展开放到当前这个对象中

总结:

mapState方法:用于帮助我们映射state中的数据为计算属性

computed: {
    //借助mapState生成计算属性:sum、school、subject(对象写法)
     ...mapState({sum:'sum',school:'school',subject:'subject'}),      
	//借助mapState生成计算属性:sum、school、subject(数组写法)
	 ...mapState(['sum','school','subject']),
}

mapGetters方法:用于帮助我们映射getters中的数据为计算属性

computed: {
    //借助mapGetters生成计算属性:bigSum(对象写法)
    ...mapGetters({bigSum:'bigSum'}),

	//借助mapGetters生成计算属性:bigSum(数组写法)
	...mapGetters(['bigSum'])
},
  • 数组写法需要我们的计算属性名和我们的state中对象的属性名相同

mapActions与mapMutations

想使用先引入import {mapMutations,mapActions} from ‘vuex’







总结:

mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}

mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    

    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),

}

备注:mapActions与mapMutations使用时,若需要传递参数,则需要在模板中绑定事件时传递好参数,否则参数是事件对象

多组件共享数据

count.vue







Person.vue





index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
   
//准备actions对象——响应组件中用户的动作
const actions = {
    addOdd(context,value){
        console.log("actions中的addOdd被调用了")
        if(context.state.sum % 2){
            context.commit('ADD',value)
        }
    },
    addWait(context,value){
        console.log("actions中的addWait被调用了")
        setTimeout(()=>{
			context.commit('ADD',value)
		},500)
    },
}
//准备mutations对象——修改state中的数据
const mutations = {
    ADD(state,value){
        state.sum += value
    },
    SUBTRACT(state,value){
        state.sum -= value
    },
	ADD_PERSON(state,value){
		console.log('mutations中的ADD_PERSON被调用了')
		state.personList.unshift(value)
	}
}
//准备state对象——保存具体的数据
const state = {
    sum:0, //当前的和
    name:'JOJO',
    school:'尚硅谷',
    personList:[
		{id:'001',name:'JOJO'}
	]
}
//准备getters对象——用于将state中的数据进行加工
const getters = {
    bigSum(){
        return state.sum * 10
    }
}
   
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

App.vue





第四章Vuex_第4张图片

模块化+命名空间

count.js

export default{
    namespaced:true,
    actions:{
        addOdd(context,value){
            console.log("actions中的addOdd被调用了")
            if(context.state.sum % 2){
                context.commit('ADD',value)
            }
        },
        addWait(context,value){
            console.log("actions中的addWait被调用了")
            setTimeout(()=>{
                context.commit('ADD',value)
            },500)
        }
    },
    mutations:{
        ADD(state,value){
            state.sum += value
        },
        SUBTRACT(state,value){
            state.sum -= value
        }
    },
    state:{
        sum:0, //当前的和
        name:'JOJO',
        school:'尚硅谷',
    },
    getters:{
        bigSum(state){
            return state.sum * 10
        }
    }
}

person.js

import axios from "axios"
import { nanoid } from "nanoid"

export default{
    namespaced:true,
    actions:{
        addPersonWang(context,value){
            if(value.name.indexOf('王') === 0){
                context.commit('ADD_PERSON',value)
            }else{
                alert('添加的人必须姓王!')
            }
        },
        addPersonServer(context){
            axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(
                response => {
                    context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
                },
                error => {
                    alert(error.message)
                }
            )
        }
    },
    mutations:{
        ADD_PERSON(state,value){
            console.log('mutations中的ADD_PERSON被调用了')
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'JOJO'}
        ]
    },
    getters:{
        firstPersonName(state){
            return state.personList[0].name
        }
    }
}

index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引入count
import countOptions from './count'
//引入person
import personOptions from './person'
//应用Vuex插件
Vue.use(Vuex)
   
//创建并暴露store
export default new Vuex.Store({
    modules:{
        countAbout:countOptions,
        personAbout:personOptions,
    }
})

count.vue







person.vue

import axios from "axios"
import { nanoid } from "nanoid"

export default{
    namespaced:true,
    actions:{
        addPersonWang(context,value){
            if(value.name.indexOf('王') === 0){
                context.commit('ADD_PERSON',value)
            }else{
                alert('添加的人必须姓王!')
            }
        },
        addPersonServer(context){
            axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(
                response => {
                    context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
                },
                error => {
                    alert(error.message)
                }
            )
        }
    },
    mutations:{
        ADD_PERSON(state,value){
            console.log('mutations中的ADD_PERSON被调用了')
            state.personList.unshift(value)
        }
    },
    state:{
        personList:[
            {id:'001',name:'JOJO'}
        ]
    },
    getters:{
        firstPersonName(state){
            return state.personList[0].name
        }
    }
}

你可能感兴趣的:(Vue,javascript,vue.js,前端)