Vue2.x 系列文章目录
内容 | 参考链接 |
---|---|
Vue2.x - 基础 | Vue2.x - 基础 |
Vue2.x - 进阶 | Vue2.x - 进阶脚手架 |
Vue2.x - 高级 Vuex | Vuex概念、工作原理、环境搭建、基本使用、getters |
Vue2.x - 高级 Vuex | Vuex 四个 map 的用法、模块化和命名空间 |
Vue2.x - 高级 Vue-router | 路由的概念、基本使用 |
Vue2.x - 高级 Vue-router | 嵌套路由、query参数、命名路由、params参数、props配置 |
Vue2.x - 高级 Vue-router | replace属性、编程式路由导航、缓存路由组件、路由的专属钩子 |
Vue2.x - 高级 Vue-router | 全局路由守卫 |
Vue3.0 - 新增 | Vue3.0 新增内容 |
Vue2.x 项目(附源码) | Vue + ElementUI 后台管理项目(附源码) |
Vue3.0 项目 | Vue3.0 企业级 App |
用于帮助我们映射 state 中的数据为计算属性
computed: {
// 借助 mapState 生成计算属性:sum、school、subject (对象写法)
...mapState({ sum: "sum", school: "school", subject: "subject" })
// 借助 mapState 生成计算属性:sum、school、subject (数组写法)
...mapState(['sum', 'school', 'subject'])
}
用于帮助我们映射 getters 中的数据为计算属性
computed:{
// 借助 mapGetters 生成计算属性:bigSum (对象写法)
...mapGetters({bigSum: bigSum})
// 借助 mapGetters 生成计算属性:bigSum (数组写法)
...mapGetters(['bigSum'])
}
使用 mapState 和 mapGetters,可以少些很多代码。
index.js
// 该文件用于创建Vuex中最为核心的store
// 引入vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions——用于响应组件中的动作
const actions = {
addOdd(context, value){
console.log('actions中的addOdd被调用了');
if(context.state.sum % 2){
context.commit('ADD',value)
}
},
addWait(context, value){
console.log('actions中的addWait被调用了');
setTimeout(()=>{
context.commit('ADD', value)
},500)
}
}
// 准备mutations——用于修改state中的数据(state)
const mutations = {
ADD(state, value){
console.log('mutations中的ADD被调用了',state, value);
state.sum += value
},
SUB(state, value){
console.log('mutations中的SUB被调用了',state, value);
state.sum -= value
}
}
// 准备state——用于存储具体的数据
const state = {
sum: 0, //当前的和
school: '尚硅谷',
subject: '前端'
}
// 准备getters——用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum * 10
}
}
// 创建并暴露store
export default new Vuex({
actions,
mutations,
state,
getters
})
Count.vue
- 要在该组件导入
mapState
和mapGetters
import { mapState, mapGetters } from "vuex";
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h3>当前求和放大10倍:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<select v-model.number="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="add(n)">+</button>
<button @click="sub(n)">-</button>
<button @click="addOdd(n)">当前求和为奇数再加</button>
<button @click="addWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
export default {
name: "myCount",
data() {
return {
n: 1, //用户选择的数字
};
},
computed: {
// 借助mapState生成计算属性,从state中读取数据 (对象写法)
//...mapState({ sum: "sum", school: "school", subject: "subject" }),
// 借助mapState生成计算属性,从state中读取数据 (数组写法)
...mapState(['sum','school','subject']),
// 借助mapGetters生成计算属性,从getters中读取数据(对象写法)
//...mapGetters({bigSum: 'bigSum'}),
// 借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(['bigSum'])
},
methods: {
increment() {
this.$store.commit("ADD", this.n);
},
decrement() {
this.$store.cmommit("SUB", this.n);
},
incrementOdd() {
this.$store.dispatch("addOdd", this.n);
},
incrementWait() {
this.$store.dispatch("addWait", this.n);
},
},
};
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
如果不使用
mapState
和mapGetters
,则需要在 computed 中手动配置如下代码。
computed: {
sum() {
return this.$store.state.sum;
},
school() {
return this.$store.state.school;
},
subject() {
return this.$store.state.subject;
},
bigSum() {
return this.$store.getters.bigSum;
}
}
用于帮助我们生成与 actions 对话的方法,即:包含
$store.dispatch(xxx)
的函数。
methods: {
// 靠mapActions生成:addOdd、addWait (对象写法)
...mapActions({addOdd: 'addOdd', addWait: 'addWait'})
// 靠mapActions生成:addOdd、addWait (数组写法)
...mapActions(['addOdd', 'addWait'])
}
用于帮助我们生成与 mutations 对话的方法,即:包含
$store.commit(xxx)
的函数。
methods: {
// 靠mapMutations生成:ADD、SUB (对象写法)
...mapMutations({add: 'ADD', sub: 'SUB'})
// 靠mapMutations生成:ADD、SUB (数组写法)
...mapMutations(['ADD', 'SUB'])
}
index.js
不变
Count.vue
- 要在该组件导入
mapActions
和mapMutations
import { mapActions, mapMutations} from "vuex";
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h3>当前求和放大10倍:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<select v-model.number="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="add(n)">+</button>
<button @click="sub(n)">-</button>
<button @click="addOdd(n)">当前求和为奇数再加</button>
<button @click="addWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
name: "myCount",
data() {
return {
n: 1, //用户选择的数字
};
},
computed: {
// 借助mapState生成计算属性,从state中读取数据 (对象写法)
// ...mapState({ sum: "sum", school: "school", subject: "subject" }),
// 借助mapState生成计算属性,从state中读取数据 (数组写法)
...mapState(["sum", "school", "subject"]),
// 借助mapGetters生成计算属性,从getters中读取数据(对象写法)
//...mapGetters({bigSum: 'bigSum'}),
// 借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(["bigSum"]),
},
methods: {
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations (对象的写法)
...mapMutations({add: 'ADD', sub: 'SUB'}),
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations (数组的写法)
//...mapMutations(['ADD','SUB']), //此时上面的绑定也要 @ADD @SUB
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions (对象写法)
...mapActions({addOdd: 'addOdd', addWait: 'addWait'})
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions (数组写法)
//...mapActions(['addOdd','addWait'])
},
};
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
基本功能
- Person 组件添加一个人,Count 组件响应地加一
- Count 组件加一,Person 组件响应地加一
多组件共享
index.js
// 该文件用于创建Vuex中最为核心的store
// 引入vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions——用于响应组件中的动作
const actions = {
addOdd(context, value) {
console.log('actions中的addOdd被调用了');
if (context.state.sum % 2) {
context.commit('ADD', value)
}
},
addWait(context, value) {
console.log('actions中的addWait被调用了');
setTimeout(() => {
context.commit('ADD', value)
}, 500)
}
}
// 准备mutations——用于修改state中的数据(state)
const mutations = {
ADD(state, value) {
console.log('mutations中的ADD被调用了');
state.sum += value
},
SUB(state, value) {
console.log('mutations中的SUB被调用了');
state.sum -= value
},
ADD_PERSON(state, value) {
console.log('mutations中的ADD_PERSON被调用了');
state.personList.unshift(value)
}
}
// 准备state——用于存储具体的数据
const state = {
sum: 0, //当前的和
school: '清华大学',
subject: 'Web前端',
personList: [{
id: '001',
name: '张三'
}]
}
const getters = {
bigSum() {
return state.sum * 10
}
}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
Count.vue
- 使用 map 写法
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h3>当前求和放大10倍:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<h3 style="color: red">Person组件的总人数是:{{ personList.length }}</h3>
<select v-model.number="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="add(n)">+</button>
<button @click="sub(n)">-</button>
<button @click="addOdd(n)">当前求和为奇数再加</button>
<button @click="addWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
name: "myCount",
data() {
return {
n: 1, //用户选择的数字
};
},
computed: {
// 借助mapState生成计算属性,从state中读取数据 (对象写法)
// ...mapState({ sum: "sum", school: "school", subject: "subject" }),
// 借助mapState生成计算属性,从state中读取数据 (数组写法)
...mapState(["sum", "school", "subject", "personList"]),
// 借助mapGetters生成计算属性,从getters中读取数据(对象写法)
//...mapGetters({bigSum: 'bigSum'}),
// 借助mapGetters生成计算属性,从getters中读取数据(数组写法)
...mapGetters(["bigSum"]),
},
methods: {
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations (对象的写法)
...mapMutations({ add: "ADD", sub: "SUB" }),
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations (数组的写法)
// ...mapMutations(['ADD','SUB']), //此时上面的绑定也要 @ADD @SUB
...mapActions({ addOdd: "addOdd", addWait: "addWait" }),
// ...mapActions(['addOdd','addWait'])
},
};
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
Person.vue
- 使用普通的写法
<template>
<div>
<h3>人员列表</h3>
<h3 style="color: red">Count组件的求和为:{{ sum }}</h3>
<input type="text" placeholder="请输入名字" v-model="name" />
<button @click="addPerson">添加</button>
<ul>
<li v-for="p in personList" :key="p.id">{{ p.name }}</li>
</ul>
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: "myPerson",
data() {
return {
name: "",
};
},
computed: {
personList() {
return this.$store.state.personList;
},
sum() {
return this.$store.state.sum;
},
},
methods: {
addPerson() {
const personObj = { id: nanoid(), name: this.name };
this.$store.commit("ADD_PERSON", personObj);
this.name = "";
},
},
};
</script>
让代码更好维护,让多种数据分类更加明确。
index.js
- 使用模块化编程
- 导入
count.js
和person.js
文件- 在 modules 中配置
countOptions
和personAbout
// 引入vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
// 应用Vuex插件
Vue.use(Vuex)
// 创建并暴露store
export default new Vuex.Store({
modules: {
countAbout: countOptions,
personAbout: personOptions
}
})
count.js
- 此文件内容为求和相关的配置
- 注意开启命名空间,用于解决不同模块的命名冲突问题。
const countAbout = {
namespaced: true, //开启命名空间
actions: {...},
mutations: {...},
state: {...},
getters: {
xxx(state){
return state.x
}
}
}
person.js
- 此文件内容为人员信息相关的配置
- 注意开启命名空间,用于解决不同模块的命名冲突问题。
const personAbout = {
namespaced: true, //开启命名空间
actions: {},
mutations: {},
state: {},
getters: {}
}
开启命名空间后,组件中读取 state 数据
//方式一:自己读取数据
this.$store.state.personAbout.personlist
//方式二:借助 mapState 读取
...mapState('countAbout', ['sum', 'school', 'subject'])
开启命名空间后,组件中读取 getters 数据
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助 mapGetters 读取
...mapGetters('countAbout', ['bigSum'])
开启命名空间后,组件中调用 dispatch
//方式一:自己直接调用 dispatch
this.$store.dispatch('personAbout/addPersonWang', person)
//方式二:借助 mapActions 调用
...mapActions('countAbout', {addOdd: 'addOdd', addWait: 'addWait'})
开启命名空间后,组件中调用 commit
//方式一:自己直接调用 commit
this.$store.commit('personAbout/ADD_PERSON', person)
//方式二:借助 mapMutations 调用
...mapMutations('countAbout', {add: 'ADD', sub: 'SUB'})
效果如下:
vuex模块化
index.js
- 模块化
count.js
和person.js
// 引入vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
// 应用Vuex插件
Vue.use(Vuex)
// 创建并暴露store
export default new Vuex.Store({
modules: {
countAbout: countOptions,
personAbout: personOptions
}
})
count.js
- 求和相关的配置
// 求和相关的配置
export default {
// 开启命名空间
namespaced: true,
// 用于响应组件中的动作
actions: {
addOdd(context, value) {
console.log('actions中的addOdd被调用了');
if (context.state.sum % 2) {
context.commit('ADD', value)
}
},
addWait(context, value) {
console.log('actions中的addWait被调用了');
setTimeout(() => {
context.commit('ADD', value)
}, 500)
}
},
// 用于修改state中的数据(state)
mutations: {
ADD(state, value) {
console.log('mutations中的ADD被调用了');
state.sum += value
},
SUB(state, value) {
console.log('mutations中的SUB被调用了');
state.sum -= value
},
},
// 用于存储具体的数据
state: {
sum: 0, //当前的和
school: '清华大学',
subject: 'Web前端',
},
getters: {
bigSum(state) {
return state.sum * 10
}
}
}
person.js
- 人员相关的配置
import axios from 'axios'
import { nanoid } from 'nanoid'
export default {
// 开启命名空间
namespaced: true,
// 用于响应组件中的动作
actions: {
addPersonWang(context, value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON', value)
}else{
alert('添加的人必须姓王!')
}
},
//连接服务器
addPersonServer(context){
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response => {
context.commit('ADD_PERSON', {id:nanoid(), name:response.data})
},
error => {
alert(error.message)
}
)
}
},
// 用于修改state中的数据(state)
mutations: {
ADD_PERSON(state, value) {
console.log('mutations中的ADD_PERSON被调用了');
state.personList.unshift(value)
}
},
// 用于存储具体的数据
state: {
personList: [{
id: '001',
name: '张三'
}]
},
getters: {
firstPersonName(state){
return state.personList[0].name
}
}
}
Count.vue
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h3>当前求和放大10倍:{{ bigSum }}</h3>
<h3>我在{{ school }},学习{{ subject }}</h3>
<h3 style="color: red">Person组件的总人数是:{{ personList.length }}</h3>
<select v-model.number="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="add(n)">+</button>
<button @click="sub(n)">-</button>
<button @click="addOdd(n)">当前求和为奇数再加</button>
<button @click="addWait(n)">等一等再加</button>
</div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {
name: "myCount",
data() {
return {
n: 1, //用户选择的数字
};
},
computed: {
...mapState("countAbout", ['sum','school','subject']),
...mapState("personAbout", ['personList']),
...mapGetters('countAbout', ['bigSum']),
},
methods: {
...mapMutations('countAbout', { add: "ADD", sub: "SUB" }),
...mapActions('countAbout', { addOdd: "addOdd", addWait: "addWait" }),
},
};
</script>
<style scoped>
button {
margin-left: 5px;
}
</style>
Person.vue
<template>
<div>
<h3>人员列表</h3>
<h3 style="color: red">Count组件的求和为:{{ sum }}</h3>
<h3>列表中第一个人的名字是:{{firstPersonName}}</h3>
<input type="text" placeholder="请输入名字" v-model="name" />
<button @click="addPerson">添加</button>
<button @click="addPersonWang">添加姓王的</button>
<button @click="addPersonServer">添加随机人</button>
<ul>
<li v-for="p in personList" :key="p.id">{{ p.name }}</li>
</ul>
</div>
</template>
<script>
import { nanoid } from "nanoid";
export default {
name: "myPerson",
data() {
return {
name: "",
};
},
computed: {
personList() {
return this.$store.state.personAbout.personList;
},
sum() {
return this.$store.state.countAbout.sum;
},
firstPersonName(){
return this.$store.getters['personAbout/firstPersonName']
}
},
methods: {
addPerson() {
const personObj = { id: nanoid(), name: this.name };
this.$store.commit("personAbout/ADD_PERSON", personObj);
this.name = "";
},
addPersonWang(){
const personObj = { id: nanoid(), name: this.name };
this.$store.dispatch('personAbout/addPersonWang', personObj)
this.name = ''
},
addPersonServer(){
this.$store.dispatch('personAbout/addPersonServer')
}
},
};
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
不积跬步无以至千里 不积小流无以成江海