
vuex工作圖示.png
-
State對(duì)象:給Vue Component提供數(shù)據(jù)狀態(tài),
this.$store.state.name、...mapState(['name']) + computed -
gettings對(duì)象:對(duì)State里面的數(shù)據(jù)進(jìn)一步加工,
this.$store.getters.name、...mapGetters(['name']) + computed -
Mutation對(duì)象:改變state狀態(tài)的方法集合,
this.$store.commit('方法名',參數(shù))、...mapMutations(['name']) + methods -
Actions對(duì)象:處理異步數(shù)據(jù),
this.$store.dispatch('方法名',參數(shù))
1. 不使用Vuex實(shí)現(xiàn)Tab功能
關(guān)于Tab的實(shí)現(xiàn):理想狀態(tài)下,"選擇層Tab + 展示層Current",就夠了。但是,由于沒(méi)有公共狀態(tài)存儲(chǔ)的地方,只能借助父組件App,進(jìn)行tabIndex屬性的傳遞通信,很麻煩。所以說(shuō),兄弟組件之間的通信還是Vuex比較適合
知識(shí)點(diǎn)1:動(dòng)態(tài)改變class類(lèi)的方式
Array
知識(shí)點(diǎn)2:父子組件的通信派發(fā)事件this.$emit、props
# 子組件Tab: 存放Tab組件樣式的地方
<template>
<div>
<a href="javascript:;" @click="clickTab(1)" :class="['router', { current: tabIndex == 1 }]">選項(xiàng)1</a>
<a href="javascript:;" @click="clickTab(2)" :class="['router', { current: tabIndex == 2 }]">選項(xiàng)2</a>
<a href="javascript:;" @click="clickTab(3)" :class="['router', { current: tabIndex == 3 }]">選項(xiàng)3</a>
<a href="javascript:;" @click="clickTab(4)" :class="['router', { current: tabIndex == 4 }]">選項(xiàng)4</a>
</div>
</template>
<script>
export default {
name: "tab",
props: {
tabIndex: Number,
},
methods: {
clickTab(index) {
// 自定義派發(fā)事件,監(jiān)聽(tīng)Tab的改變(子組件向父組件通信)
this.$emit("clickTab", index);
},
},
};
</script>
<style scoped>
.router {
text-decoration: none;
color: #000;
margin-right: 10px;
}
.current {
color: aqua;
}
</style>
# 父組件:控制Tab邏輯的地方
<template>
<div id="app">
<Tab :tabIndex="tabIndex" @clickTab="changeTab"></Tab>
<Current :tabIndex="tabIndex"></Current>
</div>
</template>
<script>
import Tab from "@/components/tabs/index.vue";
import Current from "@/views/Current.vue";
export default {
name: "App",
data() {
return {
tabIndex: 1,
};
},
components: {
Tab,
Current,
},
methods: {
changeTab(index) {
this.tabIndex = index;
},
},
};
</script>
# 子組件Current,展示Tab內(nèi)容的地方
<template>
<div>頁(yè)面{{ tabIndex }}</div>
</template>
<script>
export default {
name: "Current",
props: {
tabIndex: Number,
},
};
</script>
2. 使用Vuex重寫(xiě)Tab功能
將tabIndex屬性,以及操作tabIndex屬性的方法,統(tǒng)一存儲(chǔ)到Vuex當(dāng)中,然后,在"選擇層Tab + 展示層
Current",就夠了,跟App.vue沒(méi)關(guān)系了。知識(shí)點(diǎn):如何在Vue組件當(dāng)中調(diào)用Vuex里面的數(shù)據(jù)和方法?
...mapState(['name'])、...mapMutations(['name'])
# store.js,聲明數(shù)據(jù)、以及操作數(shù)據(jù)方法
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
tabIndex: 1,
test: "選項(xiàng)4"
},
mutations: {
setTabIndex(state, index) {
state.tabIndex = index;
}
}
});
# 子組件Tab: 存放Tab組件樣式的地方,并調(diào)用邏輯方法
<template>
<div>
<a href="javascript:;" @click="setTabIndex(1)" :class="['router', { current: tabIndex == 1 }]">選項(xiàng)1</a>
<a href="javascript:;" @click="setTabIndex(2)" :class="['router', { current: tabIndex == 2 }]">選項(xiàng)2</a>
<a href="javascript:;" @click="setTabIndex(3)" :class="['router', { current: tabIndex == 3 }]">選項(xiàng)3</a>
<a href="javascript:;" @click="setTabIndex(4)" :class="['router', { current: tabIndex == 4 }]">{{ test }}</a>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
name: "tab",
computed: {
// 輔助方法mapState,拿到State對(duì)象里面的數(shù)據(jù)
// ...mapState(["tabIndex", "test"]),
tabIndex() {
return this.$store.state.tabIndex;
},
test() {
return this.$store.state.test;
},
},
methods: {
// 輔助方法mapMutations,拿到Mutations對(duì)象里面的方法
// ...mapMutations(["setTabIndex"]),
setTabIndex(index) {
this.$store.commit("setTabIndex", index);
},
},
};
</script>
<style scoped>
.router {
text-decoration: none;
color: #000;
margin-right: 10px;
}
.current {
color: aqua;
}
</style>
#父組件App.vue
<template>
<div id="app">
<Tab></Tab>
<Current></Current>
</div>
</template>
<script>
import Tab from "@/components/tabs/index.vue";
import Current from "@/views/Current.vue";
export default {
name: "App",
components: {
Tab,
Current,
},
};
</script>
#子組件,展示內(nèi)容區(qū)
<template>
<div>頁(yè)面{{ tabIndex }}</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "Current",
computed: {
...mapState(["tabIndex"]),
},
};
</script>
3.actions處理異步數(shù)據(jù)dispatch、 context.commit()
問(wèn)題:如何將接口請(qǐng)求到的數(shù)據(jù)存儲(chǔ)到Vuex里面,并渲染到Vue組件當(dāng)中?
第一步:定義actions方法獲取異步數(shù)據(jù)
第二步:調(diào)用mutations方法將異步數(shù)據(jù)存到state里面
第三步:vue components拿著state里面的數(shù)據(jù)渲染
# 前提:Express API
# // http://localhost:3000/api/test?name=小明&age=18
module.exports = (app) => {
var express = require("express");
var router = express.Router();
router.get("/test", (req, res) => {
if ("小明" == req.query.name && 18 == req.query.age) {
res.send("我是小明,今年18");
} else {
res.send("hello world");
}
});
// 掛載router對(duì)象
app.use("/api", router);
};
# vuex定義異步請(qǐng)求、數(shù)據(jù)存儲(chǔ)等方法
import Vue from "vue";
import Vuex from "vuex";
import { axios } from "@/libs/https.js";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
expressText: ""
},
mutations: {
setExpressText(state, text) {
state.expressText = text;
}
},
actions: {
// context上下文對(duì)象包含commit屬性、payload接受一個(gè)對(duì)象參數(shù)
getData(context, payload) {
axios.get(`/api/test?name=${payload.name}&age=${payload.age}`).then(res => {
context.commit("setExpressText", res);
});
}
}
});
# actions function調(diào)用、以及數(shù)據(jù)渲染
<template>
<div id="app">
{{ expressText }}
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "App",
computed: {
...mapState(["expressText"]),
},
mounted() {
this.$store.dispatch("getData", { name: "小明", age: 18 });
},
};
</script>