-
State对象:给Vue Component提供数据状态,
this.$store.state.name
、...mapState(['name']) + computed
-
gettings对象:对State里面的数据进一步加工,
this.$store.getters.name
、...mapGetters(['name']) + computed
-
Mutation对象:改变state状态的方法集合,
this.$store.commit('方法名',参数)
、...mapMutations(['name']) + methods
-
Actions对象:处理异步数据,
this.$store.dispatch('方法名',参数)
1. 不使用Vuex实现Tab功能
关于Tab的实现:理想状态下,"选择层Tab + 展示层Current",就够了。但是,由于没有公共状态存储的地方,只能借助父组件App,进行tabIndex属性的传递通信,很麻烦。所以说,兄弟组件之间的通信还是Vuex比较适合
知识点1:动态改变class类的方式
Array
知识点2:父子组件的通信派发事件this.$emit
、props
# 子组件Tab: 存放Tab组件样式的地方
<template>
<div>
<a href="javascript:;" @click="clickTab(1)" :class="['router', { current: tabIndex == 1 }]">选项1</a>
<a href="javascript:;" @click="clickTab(2)" :class="['router', { current: tabIndex == 2 }]">选项2</a>
<a href="javascript:;" @click="clickTab(3)" :class="['router', { current: tabIndex == 3 }]">选项3</a>
<a href="javascript:;" @click="clickTab(4)" :class="['router', { current: tabIndex == 4 }]">选项4</a>
</div>
</template>
<script>
export default {
name: "tab",
props: {
tabIndex: Number,
},
methods: {
clickTab(index) {
// 自定义派发事件,监听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内容的地方
<template>
<div>页面{{ tabIndex }}</div>
</template>
<script>
export default {
name: "Current",
props: {
tabIndex: Number,
},
};
</script>
2. 使用Vuex重写Tab功能
将tabIndex属性,以及操作tabIndex属性的方法,统一存储到Vuex当中,然后,在"选择层Tab + 展示层
Current",就够了,跟App.vue没关系了。知识点:如何在Vue组件当中调用Vuex里面的数据和方法?
...mapState(['name'])
、...mapMutations(['name'])
# store.js,声明数据、以及操作数据方法
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
tabIndex: 1,
test: "选项4"
},
mutations: {
setTabIndex(state, index) {
state.tabIndex = index;
}
}
});
# 子组件Tab: 存放Tab组件样式的地方,并调用逻辑方法
<template>
<div>
<a href="javascript:;" @click="setTabIndex(1)" :class="['router', { current: tabIndex == 1 }]">选项1</a>
<a href="javascript:;" @click="setTabIndex(2)" :class="['router', { current: tabIndex == 2 }]">选项2</a>
<a href="javascript:;" @click="setTabIndex(3)" :class="['router', { current: tabIndex == 3 }]">选项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对象里面的数据
// ...mapState(["tabIndex", "test"]),
tabIndex() {
return this.$store.state.tabIndex;
},
test() {
return this.$store.state.test;
},
},
methods: {
// 辅助方法mapMutations,拿到Mutations对象里面的方法
// ...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>
#子组件,展示内容区
<template>
<div>页面{{ tabIndex }}</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "Current",
computed: {
...mapState(["tabIndex"]),
},
};
</script>
3.actions处理异步数据dispatch
、 context.commit()
问题:如何将接口请求到的数据存储到Vuex里面,并渲染到Vue组件当中?
第一步:定义actions方法获取异步数据
第二步:调用mutations方法将异步数据存到state里面
第三步:vue components拿着state里面的数据渲染
# 前提: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对象
app.use("/api", router);
};
# vuex定义异步请求、数据存储等方法
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上下文对象包含commit属性、payload接受一个对象参数
getData(context, payload) {
axios.get(`/api/test?name=${payload.name}&age=${payload.age}`).then(res => {
context.commit("setExpressText", res);
});
}
}
});
# actions function调用、以及数据渲染
<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>
网友评论