如何使用vuex
目标:在一个项目中使用vuex,并正确执行。
如何使用vuex 项目实例之gitHub地址:https://github.com/WangShuangshuang/vuex
项目截图:
思路:
1. 用 new Vuex.store({ }) 创建一个vuex的实例,并把这个实例传入到main.js中的new Vue({ })对象中。
2. Vuex.store()构造函数接收一个对象,这个对象有4个重要的组成部分(每个组成也是对象):state, getters, mutations, actions。
2.1 state - vuex实例的数据模型
2.2 getters - vuex实例根据数据模型做的计算属性
2.3 mutations - 各个组件想要更改vuex的数据模型时,必须通过(vuex实例的commit方法)commit某一个mutation而执行;每个mutation都必须是同步执行的方法
2.4 actions - 组件如果想用异步方法来更新数据模型(比如请求一个接口得到响应数据之后,再去更新vuex的数据模型),这时就需要通过(vuex实例的dispatch方法)dispatch某一个action而执行;而每一个action的内部通过commit mutation的方式去改变数据模型
3. vuex的设计蕴含着面向对象的思想,vuex实例有自己内部的数据,而外部的方法不应该直接改变这些数据,所以必须通过调用vuex实例内部的方法,这些内部方法再去改变内部数据。保证数据的改变是可控的。
Step1 安装vuex:
安装:
npm install vuex --save
使用:
在main.js文件中,新增如下代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Step2 在main.js中,创建并注入vuex的实例对象
main.js内容:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import App from './App.vue'
Vue.config.productionTip = false
const store = new Vuex.Store({
/* 1/4 state:数据 */
state: {
count: 1,
price: 100,
},
/* 2/4 getters:store的计算属性 */
getters: {
cost(state){ // state参数必须有
return state.count * state.price;
},
memberCost(state, getters){ // state, getters参数都必须有
return getters.cost * 0.85;
},
// 返回值为方法的
discountCost: (state) => (discount) => { return state.count * state.price * discount }
},
/* 3/4 mutations:改变数据的同步方法 */
mutations: {
increment(state){
state.count++
},
reduce(state){
state.count--
},
clear(state){
state.count = 0;
},
// 附带参数的
incrementSome(state, payload){
state.count += payload.amount;
},
},
/* 4/4 actions: 以提交mutation的形式改变数据的异步方法 */
actions: {
incrementAsync(context, options){ // context对象与store实例具有相同的方法和属性,但不是后者本身
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('incrementSome', options);
resolve({ message: 'add sucess' });
}, 1000);
})
},
clear({ commit }){
return new Promise((reject, resolve) => {
var res = confirm('Sure to clear ?');
if(res){
commit('clear');
resolve({ message: 'clear success' })
} else {
reject({ message: 'would not clear' })
}
})
}
}
})
new Vue({
store,
render: h => h(App),
}).$mount('#app')
Step3 创建两个组件MyHello1.vue和MyHello2.vue
MyHello1.vue内容:
<template>
<div class="hello">
<h1>MyHello1</h1>
<p>
COUNT: <span class="count">{{ count }}</span> * PRICE: {{ price }}
<br>总价:{{ cost }}
<br>会员价:{{ memberCost }}
<br>折扣价:<input class="input" v-model="discount" /> {{ discountCost(discount) }}
</p>
<button @click="add">Add</button>
<br><button @click="addTwo">AddTwo</button>
<br><button @click="addAsync">AddAsync</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
name: 'MyHello1',
data(){
return {
text: 'abcdef',
discount: 0.5,
}
},
computed: {
textLength(){
return this.text.length;
},
...mapState([
'count', 'price',
]),
...mapGetters([
'cost', 'memberCost', 'discountCost'
]),
...mapActions([
'incrementAsync'
])
},
methods:{
add(){
this.$store.commit('increment');
},
addTwo(){
this.$store.commit({
type: 'incrementSome',
amount: 2,
})
// 等效写法:
// this.$store.commit('incrementSome', { amount: 2 })
},
addAsync(){
this.$store.dispatch('incrementAsync', { amount: 10 })
.then((data) => { // then()的参数为resolve方法的具体实现
console.log(data.message);
})
.catch((data) => { // catch()的参数为reject方法的具体实现
console.log(data.message);
})
}
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.count{
color: red;
}
.input{
width:30px;
height:30px;
line-height:30px;
}
</style>
MyHello2.vue内容:
<template>
<div class="hello">
<h1>MyHello2</h1>
<p>count: <span class="count">{{ count }}</span></p>
<button @click="add">Add</button>
<br><button @click="clear">Clear</button>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'MyHello2',
computed: {
...mapState([
'count'
])
},
methods:{
add(){
this.$store.commit('increment');
},
clear(){
this.$store.dispatch('clear')
.then((data) => {
console.log(data.message);
})
.catch((data) => {
console.log(data.message);
})
}
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.count{
color: red;
}
</style>
Step4 在App.vue中引用上面两个组件:
App.vue内容:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<MyHello1/>
<hr />
<MyHello2/>
</div>
</template>
<script>
import MyHello1 from './components/MyHello1.vue'
import MyHello2 from './components/MyHello2.vue'
export default {
name: 'app',
components: {
MyHello1,
MyHello2,
}
}
</script>
<style>
</style>
本文结束。