VueX
State:存放数据的地方
Vue compoments:Vue的组件
然后组件调用一个API叫做dispatch
,dispatch('option', val)
,将数据提交到Actions,Actions是一个对象当你提交数据来之后肯定会有一个key对应option,这个val对应一个函数,这个函数用来处理dispatch传过来的val,然后需要我们自己手动调用commit
,commit过后会到Mutations(也是一个对象)里面调用相应的函数(也就是dispatch里面的option,当然与Actions类似,也是KV),同时Mutations里面能拿到State的数据,然后对数据进行操作,操作完成后,会重新解析页面。
Actions里面可以用于向服务器发送请求,同时啊如果这个数据不需要走Actions也可以直接commit到Mutations
然后上图Vuex圈起来的部分需要一个store来统一管理。因此所有方法都是store.xxx
使用
安装
npm i vuex
然后在main.js里面
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
Vue.config.productionTip = false
Vue.use(Vuex)
new Vue({
render: h => h(App),
}).$mount('#app')
当我们引入了Vuex之后我们就可以在下面的配置项中加上一个store属性,当然如果没有引入加上了也是不会生效的,正确配置完成后,所有的vm和vc都会多一个$store
属性
然后我们新建src/store/index.js
import Vuex from 'vuex'
//响应组件中的动作
const actions = {}
//用于操作数据
const mutations = {}
//用于存储数据
const state = {}
//对外暴露
export default new Vuex.Store({
actions,
mutations,
state
})
然后因为JS的import引入优先级的问题,我们需要修改一下
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
//响应组件中的动作
const actions = {}
//用于操作数据
const mutations = {}
//用于存储数据
const state = {}
//对外暴露
export default new Vuex.Store({
actions,
mutations,
state
})
然后我们来实操一下
案例
首先先准备一个页面,这里只是为了学习而已,所以页面特别素,代码多了也不方便阅读是吧
<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="plus">+</button>
<button @click="minus">-</button>
<button @click="plusEven">偶数时加</button>
</div>
</template>
<script>
export default {
name: 'Count',
data() {
return {
n: 1,
sum: 0
}
},
methods: {
plus() {
this.sum += this.n;
},
minus() {
this.sum -= this.n;
},
plusEven() {
if(this.sum % 2 === 0) {
this.sum += this.n
}
}
}
}
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
然后我们开始进行修改
在src/components/Count.vue
<template>
<div>
<h1>{{$store.state.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="plus">+</button>
<button @click="minus">-</button>
<button @click="plusEven">偶数时加</button>
</div>
</template>
<script>
export default {
name: 'Count',
data() {
return {
n: 1,
//这里把sum交给state进行管理
}
},
methods: {
//因为plus和minus操作逻辑很简单不需要走actions 所以直接commit给mutations
plus() {
this.$store.commit('PLUS', this.n);
},
minus() {
this.$store.commit('MINUS', this.n);
},
plusEven() {
this.$store.dispatch('plusEven', this.n);
}
}
}
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
然后在src/store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
//响应组件中的动作
const actions = {
plusEven(context, val) {
//这里有两个参数,第一个是上下文,里面有很多我们可能会需要的API,比如dispatch getter commit等
//val就是前面Count组件dispatch的值
if (context.state.sum % 2 === 0) {
context.commit('PLUS', val);
}
}
}
//用于操作数据
const mutations = {
PLUS(state, val) {
//这个state就是下面的state val是上面调用commit传过来的值
state.sum += val
},
MINUS(state, val) {
state.sum -= val;
}
}
//用于存储数据
const state = { sum: 0 }
//对外暴露
export default new Vuex.Store({
actions,
mutations,
state
})
一个简单的Vuex案例就到此结束了
接下来就是一些额外的东东,非必需,但是还是很有用的
getters
这是一个新的配置项,所以和store文件夹里面的东西一起用,其次这个的目的是对数据进行深加工,比如多个组件要使用这个深加工的数据,那么就可以甩在这里面
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
//响应组件中的动作
const actions = {
plusEven(context, val) {
//这里有两个参数,第一个是上下文,里面有很多我们可能会需要的API,比如dispatch getter commit等
//val就是前面Count组件dispatch的值
if (context.state.sum % 2 === 0) {
context.commit('PLUS', val);
}
}
}
//用于操作数据
const mutations = {
PLUS(state, val) {
//这个state就是下面的state val是上面调用commit传过来的值
state.sum += val
},
MINUS(state, val) {
state.sum -= val;
}
}
//在这里
const getters = {
tenfold(state) {
return state.sum * 10;
}
}
//用于存储数据
const state = { sum: 0 }
//对外暴露
export default new Vuex.Store({
actions,
mutations,
state,
getters //记得暴露出去
})
然后就可以使用{{$store.getters.tenfold}}
进行调用
mapState和mapGetters
这两个东西就是简化操作的,如果state里面的东西太多,拿的时候要$store.state.xxx
写多了就烦,这两个就是简化这个操作的,这里就简单言传一下,毕竟也不是什么太难的东西
const state = {
height: 187,
weight: 80,
age: 19,
}
const getters = {
BMI(state) {
return state.weight / (state.height * state.height);
}
}
/************************上面是store的代码********************/
//如果我们要在组件里面展示
//下面是组件里面的代码简写 明白意思就行了
export default {
// 别忘了要引入!!!
import {mapState, mapGetters} from 'vuex';
name: 'bmiTest',
...,
computed: {
//原始写法
height() {
return this.$store.state.height;
},
weight() {
return this.$store.state.weight;
},
age() {
return this.$store.state.age;
},
//两种写法,写完后就可以直接使用{{height}}
...mapState({height: 'height', weight: 'weight', age: 'age'});
//此方法在原始写法中 属性名和$store.state.xxx中的xxx同名才可以
//就是你不会给这个属性起别的名字 shengao() {return $store.state.height} 这样写就不能用下面的写法
//写了这些方法以后原始写法就可以删了 这些就是拿来简写的 写好了上面的东西就不用了
...mapState(['height', 'weight', 'age']);
//mapGetters同理
...mapGetters({BMI: 'BMI'});
...mapGetters(['BMI']);
}
}
这里加一句mapState对应state,mapGetters对应getters,别写混淆了
mapActions和mapMutations
这东西分别对应的是commit和dispatch,意思和上面的差不多,唯一的区别就是传参的时候要去html页面里面传参,其他的都一样
-
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使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。