vuex的流程:
在vue组件中,通过dispatch来触发actions提交修改数据的方法,然后再通过actions的commit来触发mutations中对应的方法修改数据,mutations接收到commit的请求后,会自动修改state中的数据;最后由store触发每一个调用他的组件的更新;
vuex是什么?vuex是一个专门为vue.js应用程序开发的状态管理模式,它采用集中式存储来管理所有组件的公共状态;并以响应的规则保证状态以一种可预测的方式发生变化;
上图中绿色虚线包裹起来的部分就是vuex的核心部分;
为什么要使用vuex? 解决多组件使用共享数据的不方便取值的问题;
如何引入Vuex ?
1,下载vuex: npm install vuex --save
2,创建state.js getters.js mutations.js actions.js 模块;例如state.js文件:
export default {
msg:1,
cars:[]
}
3,创建store.js文件(各个模块中的数据比较多的时候可以这样写,将各个模块分开;单独引入,数据少的话直接将
state getters mutations actions 属性直接写在store.js文件中,如下面核心概念中的写法)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 引入state.js getters.js mutations.js actions.js 模块
import state from './state'
import getters from './getters'
import mutations from './mutations'
import actions from './actions'
export default new Vuex.Store({
state,getters,mutations,actions
})
2,在main.js中引入并添加store.js;
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.prototype.bus = new Vue()
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
核心概念:
1,state: 是vuex中的公共状态,可以将state看做是所有组件的data,用于保存所有组件的公共数据;
//在state中保存数据
const store = new Vuex.Store({
state:{
products:[
{id:1,name:'鼠标',price:20},{id:2,name:'键盘',price:30}
]
}
})
//在子组件中获取公共数据的话,这样做:
export default {
data(){
return {
products:this.$store.state.products
// 就是通过this.$store.state.属性名 方式来获取数据
}
}
}
核心概念2:Getters: Getters可以理解为所有组件的计算属性,Getters的返回值会根据他的依赖被缓存起来,只有当他的依赖值发生了变化才会被重新计算;
// 在Vuex.Store实例中添加getters 属性
const store = new Vuex.Store({
state:{
products:[
{id:1,name:'鼠标',price:20},{id:2,name:'键盘',price:30}
]
},
getters:{
saleProducts:(state)=>{
let saleProducts = state.products.map(pro=>{
return {
id:pro.id,
name:pro.name,
price:pro.price/2
}
})
return saleproducts;
}
}
})
将子组件中的products值更换为this.$store.getters.saleProducts;
export default {
data(){
return {
product:this.$store.getters.saleProducts
}
}
}
核心概念3:mutations
可以将mutations理解为store中的methods,mutations中保存着更改数据的回调函数,函数名官方规定叫type,第一个参数是state,第二个参数payload(注:也就是自定义的参数);
const store = new Vuex.Store({
mutations:{ //添加mutations
minusPrice (state, payload ) {
let newPrice = state.products.forEach( product => {
product.price -= payload
})
}
}
})
在子组件中添加一个按钮,并添加一个点击事件,用于触发minusPrice方法;<button @click="minusPrice">减少价格</button> //添加按钮;在子组件中注册minusPrice方法,并在该方法中commit一下 Vuex.Store实例中的mutations中的minusPrice这个回调函数;
export default {
data(){
return {
product:this.$store.getters.saleProducts
}
},
methods:{
minusPrice(){
this.$store.commit('minusPrice',2)
}
}
}
核心概念4,actions
actions 类似于 mutations,不同在于:actions提交的是mutations中的方法,而不是直接变更状态,actions中可以包含异步操作,mutations中绝不允许出现异步,
actions中的回调函数的第一个参数是context, 该参数是一个与store实例具有相同属性和方法的对象;
在store中添加actions属性,minusPriceAsync采用setTimeout来模拟异步操作,延迟两秒执行,用于异步改变在mutations中定义的minusprice
const store = new Vuex.Store({
state:{
products: [
{name: '鼠标', price: 20},
{name: '键盘', price: 40},
{name: '耳机', price: 60},
{name: '显示屏', price: 80}
]
},
getters:{
saleProducts: (state) => {
let saleProducts = state.products.map( product => {
return {
name: product.name,
price: product.price / 2
}
})
return saleProducts;
}
},
mutations:{
minusPrice (state, payload ) {
let newPrice = state.products.forEach( product => {
product.price -= payload
})
}
},
actions:{ //添加actions
minusPriceAsync( context, payload ) {
setTimeout( () => {
context.commit( 'minusPrice', payload ); //context提交
}, 2000)
}
}
})
在子组件中添加一个按钮,为其添加一个点击事件,并触发minusPriceAsync方法,
在子组件中注册minusPriceAsync方法,在该方法中dispatch一下actions中的minusPriceAsync这个回调函数;
methods: {
minusPriceAsync() {
this.$store.dispatch('minusPriceAsync', 5); //分发actions中的minusPriceAsync这个异步函数
}
}
核心概念5:modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象中去,当应用变得非常复杂时,store对象会变得非常臃肿,为了解决以上问题,Vuex允许将store分割成模块,每个模块拥有自己的state,mutations,actions,getters,甚至是嵌套子模块;
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})