Vue-cli4——vuex
Day1
文章目录
前言
此文章根据官方文档及些网络资料编写,仅供个人使用。提示:以下是本篇文章正文内容,下面案例可供参考
一、介绍
它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
如果有多个组件的状态需要共享,都用同一个状态的时候,就需要vuex。例如:
- 用户的登录状态、名称、头像、地理信息
- 商品的收藏、购物车中的物品
二、各种状态
2.1 单界面的状态管理
-
State:不用多说,就是我们的状态。(你姑且可以当做就是data中的属性)
-
View:视图层,可以针对State的变化,显示不同的信息。(这个好理解吧?)
-
Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ryIIrrOd-1605854623467)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119162745025.png)]
计数器就是很简单的单界面管理,代码我就不放了,之前写过
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HUU7fzfQ-1605854623469)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119162812959.png)]
2.2多界面的状态管理
多个页面用同一个状态,下面就是官方给出的图片。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKP5dK7v-1605854623470)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119161603117.png)]
new Promise((resolve, reject) => {
setTimeout(() => {
// 成功的时候调用resolve
// resolve('Hello World')
// 失败的时候调用reject
reject('error message')
}, 1000)
}).then......
他希望你数据在这里面处理
.then((data) => {
// 1.100行的处理代码
console.log(data);
console.log(data);
console.log(data);
console.log(data);
console.log(data);
}).catch((err) => {
console.log(err);
})
然后你要注意,网络请求成功的话会执行 resolve(‘Hello World’)
他会跳到then
去执行,将里面的数据给到then
。
然后你要注意,网络请求失败的话会调用reject(‘error message’)
,他会跳到catch
去执行,将里面的数据给到catch
。
2.3 三种状态
pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWq2EIM2-1605854623474)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201119141406232.png)]
2.4 另外一种状态的处理形式
err写在then的里面
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('Hello Vuejs')
reject('error message')
}, 1000)
}).then(data => {
console.log(data);
}, err => {
console.log(err);
})
三、链式调用
第一种办法
// wrapped into
// 网络请求: aaa -> 自己处理(10行)
// 处理: aaa111 -> 自己处理(10行)
// 处理: aaa111222 -> 自己处理
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
// 1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
// 2.对结果进行第一次处理
return new Promise((resolve, reject) => {
// resolve(res + '111')
reject('err')
})
}).then(res => {
console.log(res, '第二层的10行处理代码');
return new Promise(resolve => {
resolve(res + '222')
})
}).then(res => {
console.log(res, '第三层的10行处理代码');
}).catch(err => {
console.log(err);
})
第二种办法
// new Promise(resolve => resolve(结果))简写
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
// 1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
// 2.对结果进行第一次处理
return Promise.resolve(res + '111')
}).then(res => {
console.log(res, '第二层的10行处理代码');
return Promise.resolve(res + '222')
}).then(res => {
console.log(res, '第三层的10行处理代码');
})
第三种办法,省略掉Promise.resolve
// 省略掉Promise.resolve
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
// 1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
// 2.对结果进行第一次处理
return res + '111'
}).then(res => {
console.log(res, '第二层的10行处理代码');
return res + '222'
}).then(res => {
console.log(res, '第三层的10行处理代码');
})
第四种办法
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa')
}, 1000)
}).then(res => {
// 1.自己处理10行代码
console.log(res, '第一层的10行处理代码');
// 2.对结果进行第一次处理
// return Promise.reject('error message')
throw 'error message'
}).then(res => {
console.log(res, '第二层的10行处理代码');
return Promise.resolve(res + '222')
}).then(res => {
console.log(res, '第三层的10行处理代码');
}).catch(err => {
console.log(err);
})
</script>
-
State:状态,保存共享状态的地址
-
Vue Components:组件
-
Actions:是做异步操作的,发送网络请求
-
Backend:后端
-
Mutations:方法
-
Devtools:会记录你每次修改State状态
修改State必须通过 Mutations 修改,这样就可以利用 Devtools 记录每一步修改状态。
四、Vuex简单的实例
简单的计数器
App.vue
<template>
<div>
<h2>hello world</h2>
<h2>{{ message }}</h2>
<button @click="addition">+</button>
<button @click="subtraction">-</button>
{{ $store.state.counter }}
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
message: "HELLO"
}
},
methods: {
addition() {
this.$store.commit('increment')
},
subtraction() {
this.$store.commit('decrement')
},
},
}
</script>
store/index.js
import {createStore} from 'vuex'
import Vue from 'vue'
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
counter: 0,
}
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
},
},
actions: {},
modules: {},
})
export default store
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y5PsBT1A-1605854623476)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120103439629.png)]
五、Getters
有些时候我们需要对state中的一些状态进行操作,这个时候就需要用到Getters了
5.1 将couter的数量乘以2
我们在实例的基础上添加一些代码,
store/index.js
getters: {
powerCounter: state => {
return state.counter * 2
},
},
App.vue
powerCounter
<h2>{{ $store.getters.powerCounter }}</h2>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nhqGoLwC-1605854623476)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120104255259.png)]
5.2 参数和传递参数
store/index.js
state: {
counter: 0,
students: [
{id: 110, name: 'why', age: 18},
{id: 111, name: 'kobe', age: 24},
{id: 112, name: 'james', age: 30},
{id: 113, name: 'curry', age: 10}
]
},
getters: {
moreAgeStu(state) {
return age => {
return state.students.filter(s => s.age > age)
}
},
moreAgeStuLength: (state, getters) => {
return getters.moreAgeStu.length
}
},
App.vue
more20stuLength
<h2> {{ $store.getters.moreAgeStuLength }} </h2>
moreAgeStu
<h2> {{ $store.getters.moreAgeStu(19) }} </h2>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WrGNww75-1605854623477)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120104740851.png)]
六、Mutations
更新Vuex的store状态的更新唯一方式:提交Mutations
一般Mutation
是带参数的state
,
而从Vue里面提交的时候是用commit
6.1 携带参数
store/index.js
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
},
App.vue
<button @click="addCount(5)">+5</button>
<button @click="addStudent">添加学生</button>
<script>
addCount(count) {
this.$store.commit('incrementCount', 5)
},
addStudent() {
const stu = {id:114, name:'alan', age: 30}
this.$store.commit('addStudent', stu)
}
},
}
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R0PGkZMx-1605854623477)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120113059191.png)]
6.2 另一种提交方式
这种提交方式,提交上去的一种对象,如果要提取数据需要payload.count
App.vue
addCount(count) {
// this.$store.commit('incrementCount', 5)
this.$store.commit({
type: 'incrementCount',
count
})
},
store/index.js
incrementCount: (state, payload) => {
console.log(payload);
},
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D3WcSAJm-1605854623478)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120114134613.png)]
state.info['address'] = '嘻嘻嘻'
delete state.info.age
响应式的前提是,已经在state里面定义好了
6.3 定义常量
我们在mutations-types.js
里面定义一个常量,在其他文件里面用就可以
store/index.js
import {
INCREMENT
} from "@/store/mutations-types
mutations: {
[INCREMENT](state) {
state.counter++
},
}
App.vue
import {
INCREMENT
} from "@/store/mutations-types";
methods: {
addition() {
this.$store.commit(INCREMENT)
},
}
在mutation里面的所有代码,都不可以是异步的(setTimeout),必须是同步
七、Action
类似Mutation,但是里面是可以进行异步操作的,类似网络请求。
action本身可以使用Promise,进行异步操作
一般action
是带参数的context
,
而从Vue里面提交的时候是用dispatch
7.1 简单实现
store/index.js
mutations: {
updateInfo(state) {
// state.info['address'] = '嘻嘻嘻'
// delete state.info.age
state.info.name = 'TETETE '
}
},
actions: {
aUpdateInfo(context, payload) {
setTimeout(()=>{
// 要注意,这里的updateInfo是指上面mutations里面的mutations
context.commit('updateInfo')
console.log(payload.message);
payload.success()
},1000)
}
},
App.vue
updataInfo() {
this.$store.dispatch('aUpdateInfo', {
message: '我是携带的信息',
success: () => {
console.log('已经完成')
}
})
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OV2O3XRS-1605854623479)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120125552927.png)]
点击按钮的一秒后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xWHyBggg-1605854623480)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120125607355.png)]
7.2 使用Promise
store/index.js
mutations: {
updateInfo(state) {
// state.info['address'] = '嘻嘻嘻'
// delete state.info.age
state.info.name = 'TETETE '
}
},
actions: {
aUpdateInfo(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(()=>{
// 要注意,这里的updateInfo是指上面mutations里面的mutations
context.commit('updateInfo')
console.log(payload);
resolve('123321')
},1000)
})
}
},
App.vue
updataInfo() {
this.$store.dispatch('aUpdateInfo',
'我是携带的信息').then(res => {
console.log('里面完成了提交');
console.log(res)
})
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4OKQZbyi-1605854623480)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201120131012696.png)]
八、Modules
这是一个模块,每一个模块有自己的state、mutations、actions、getters等。
Vue实例找mutations,会先去store里面找,找不到在去模块找
8.1 实例
rootState,是指父的State
store/index.js
const moduleA = {
state: {
name: 'zhangsan'
},
mutations: {
updateName(state, payload) {
state.name = payload
}
},
getters: {
fullname(state) {
return state.name + '11111'
},
fullname2(state, getters) {
return getters.fullname + '2222'
},
fullname3(state, getters, rootState) {
return getters.fullname2 + rootState.counter
}
},
actions: {
aUpdateName(context) {
console.log(context);
setTimeout(() => {
context.commit('updateName', 'wangwu')
}, 1000)
}
}
}
// 在store里面添加
modules: {
a: moduleA
},
App.vue
<h2>----------App内容: modules中的内容----------</h2>
<h2>{{$store.state.a.name}}</h2>
<button @click="updateName">修改名字</button>
<h2>{{$store.getters.fullname}}</h2>
<h2>{{$store.getters.fullname2}}</h2>
<h2>{{$store.getters.fullname3}}</h2>
<button @click="asyncUpdateName">异步修改名字</button>
// 在Vue实例里面
updateName() {
this.$store.commit('updateName', 'lisi')
},
asyncUpdateName() {
this.$store.dispatch('aUpdateName')
}
九、分离式目录结构
store
modules
moduleA.js
actions.js
getters.js
index.js
mutations.js
mutations-types.js
重构代码例如action.js:
export default {
aUpdateInfo(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updateInfo')
console.log(payload);
resolve('123321')
}, 1000)
})
}
}
我们利用export default {}
将内容导出
在index.js导入
import moduleA from "@/store/modules/moduleA";
import actions from "@/store/actions";
import mutations from "@/store/mutations";
import getters from "@/store/getters";
const state = {
counter: 0,
students: [
{id: 110, name: 'why', age: 18},
{id: 111, name: 'kobe', age: 24},
{id: 112, name: 'james', age: 30},
{id: 113, name: 'curry', age: 10}
],
info: {
name: 'kobe',
age: 40,
height: 188
}
}
const store = new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
a: moduleA
}
})