Vue.js学习笔记第四部分Vuex状态管理和axios
因为hexo会试图渲染页面的mastache语法 所以每个mastache语法间加入空格
vue版本:v2.6.12
一. Promise知识回顾
Promise是异步编程的一种解决方案。
常见场景:网络请求
解决问题:回调地狱
$.ajax('url1',function(data1){ $.ajax(data1['url2'],function(data2){ $.ajax(data1['url3'],function(data3){ $.ajax(data1['url4'],function(data4){ console.log(data4); }) }) }) }) <!--0-->
转树形为链式
Promise的链式调用
1 | new Promise((resolve,reject)=>{ |
Promise.all
1 | Promise.all([ |
Promise语法糖await
1 | async function callAjax(){ |
二. Vuex
官方解释:Vuex是一个专为Vue.js应用程序开发的状态管理模式
- 它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex也集成到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能
状态管理是什么?
- 我们可以简单的将其看成需要多个组件共享的变量全部存储在一个对象里面。
- 然后将这个对象放在顶层的Vue实例中,实现多个组件变量的共享
哪些状态需要共享?
- 比如用户登录状态、用户名称、头像、地理位置
- 商品收藏、购物车物品
文件:Vuex存储文件位于src/store/index.js
state基本使用
1 | import Vue from 'vue' |
组件中访问state
{ {$store.state.counter} }
提交mutations修改state
- Vuex的store状态更新唯一方式:提交Mutation
store/index.js
1 | export default new Vuex.Store({ |
组件User.vue
1 | <script> |
带参数提交mutations修改state
组件:
1 | ... |
store/index.js
1 | ... |
- 提交mutation携带的额外参数被称为载荷(Payload)
- 可以是一个对象
带对象参数提交mutations修改state
组件:
1 | ... |
store/index.js:
1 | ... |
Getters基本使用
类似于计算属性
1 | export default new Vuex.Store({ |
调动
1 | <h2>{ {$store.getters.powerCounter} }</h2> |
getters参数传递
1 | moreAgeStu(state) { |
调用
1 | <h2>{{$store.getters.moreAgeStu(18)}}</h2> |
mutations的类型常量
我们可以发现mutations里面的属性名和组件中commit提交的参数名是一致的,当属性少时还不会有问题,但是当有几百个这样的变量时要改就非常麻烦了
我们是否可以将其抽离出来?
在store目录下新建一个mutations-types.js文件
这个文件专门用来定义变量,例如:
export const INCREMENT = 'increment' <!--15-->
改写组件中的调用
... methods: { addition() { this.$store.commit(INCREMENT) }, ... <!--16-->
这样如果等多次用到常量,并且当常量名字拼错后马上会报undefine,然后根据填错的常量名很快就能定位到是哪个常量
Mutation同步函数
- 通常情况下,Vuex要求我们Mutation中的方法必须是同步方法
- 主要的原因是当我们使用devtools时,可以帮助我们捕捉到mutation的快照
- 如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候会完成
Action基本定义
有些情况我们确实希望在Vuex中进行一些异步操作,比如网络请求必然是异步的,此时如何处理呢
Action类似于Mutation,用来代替Mutation进行异步操作
store/index.js
state: { students:[ {id:101,name:'111',age:14}, {id:102,name:'112',age:15}, {id:103,name:'113',age:16} ] }, mutations: { updateInfo(state){ state.students.push({id:103,name:'113',age:16}) } }, actions: { //上下文 现在是store对象 aUpdateInfo(context) { setTimeout(() => { context.commit('updateInfo') },1000) } }, <!--17-->
actions结合promise
store/index.js
actions: { //上下文 现在是store对象 aUpdateInfo(context, payload) { return new Promise((resolve, reject) => { setTimeout(() => { context.commit('updateInfo') console.log(payload); resolve('1111') },1000) }) } }, <!--18-->
返回promise对象, 这样的话就能对执行结果成功或者失败都进行处理了
modules基本使用
Modeule是模块的意思
- Vue使用单一状态树,意味着很多状态交给Vuex管理
- 当应用变得非常复杂时,store对象就有可能变成非常臃肿
- 为了解决这个问题,Vuex允许我们将store分割成模块,每个模块有自己的state、mutation、action、getters等
组织方式
const moduleA = { state: {...}, mutations: {...}, actions: {...}, getters: {...} } const moduleB = { state: {...}, mutations: {...}, actions: {...} } const store = new Vuex.Stroe({ modules: { a: moduleA, b: moduleB } }) store.state.a //moduleA的状态 store.state.b //moduleB的状态 <!--19-->
三. 网络请求封装
1.网络请求模块选择-axios
- Vue中发送网络请求方式非常多
- 选择一:传统的Ajax是基于XMLHttpRequest(XHR)
- 为什么不用它:
- 配置和调用方式等非常混乱
- 编码可读性差
- 真实开发中很少直接用,而是使用jQuery-Ajax
- 选择二:jQuery-Ajax
- 相对于传统Ajax非常好用
- 为什么不用它:
- 在Vue整个开发过程中不需要使用jQuery
- jQuery代码1w+行,而Vue代码也1w+行
- 没有必要为了网络请求一个功能就引用jQuery
- 选择三:官方在Vue1.x时推出了Vue-resource
- 相对jQuery小很多
- 为什么不用它:
- 不更新了
- 选择四:作者在说明不更新和维护Vue-resource的同时,推荐了一个框架:axios
- axios有非常多的优先,用起来也方便
- 功能特点:
- 在浏览器中发送XMLHttpRequests请求
- 在node.js中发送http请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 等等
2.axios框架基本使用
axios请求方式
- 支持多种请求方式:
- axios(config)
- axios.request(config)
- axios.get(url,[config])
- axios.delete(url,[config])
- axios.head(url,[config])
- axios.post(url,[data,[config]])
- axios.put(url,[data,[config]])
- axios.patc(url, [data,[config]])
安装:npm install axios -save
引用:import axios from 'axios'
使用:
简单使用:
axios({ url: 'http://123.207.32.32:8000/home/multidata', method: 'post' }).then(res => { console.log(res); }) <!--20-->
3.axios发送并发请求
axios.all([ axios({ url: 'http://123.207.32.32:8000/home/data', params: { type: 'pop', page: 1 } }), axios({ url: 'http://123.207.32.32:8000/home/multidata' })]) .then(axios.spread((res1,res2) => { console.log(res1) console.log(res2) })) <!--21-->
常见配置选项
- 请求地址:
url: '/user'
- 请求类型:
method: 'get'
- 请求根路径:
baseURL: 'http://www.mt.com/api'
- 请求前数据处理:
transformRequest: [function(data){}]
- 请求后数据处理:
transformResponse: [function(data){}]
- 自定义请求头:
headers: {'x-Requested-With':'XMLHttpRequest'}
- URL查询对象:
params: {id: 12}
- 查询对象序列化函数:
paramsSerializer: function(params){}
- request body:
data: {key:'aa'}
- 超时设置:timeout:
1000
- 跨域是否带Token:
withCredentials: false
- 自定义请求处理:
adapter: function(resolve, reject, config){}
- 身份验证信息:
auth: {uname: '', pwd: '12'}
- 响应的数据格式json/blob/document/arraybuffer/text/stream:``responseType: ‘json’`
- 请求地址:
5.axios实例和模块封装
axios实例解决分布式服务器的问题
const instance1 = axios.create({ baseURL: 'http://123.207.32.32:8000', timeout: 5000 }) instance1({ url: '/home/multidata' }).then(res => { console.log(res); }) instance1({ url: '/home/data', params: { type: 'pop', page: 1 } }).then(res => { console.log(res); }) const instance2 = axios.create({ baseURL: 'http://222.111.33.33:8080/', timeout: 1000, }) instance2({ url: '/home/data', params: { type: 'pop', page: 1 } }).then(res => { console.log(res); }) <!--22-->
使用:
import {request} from './network/request.js' request({ url: '/home/multidata', }, res => { console.log(res); }, err => { console.log(err); }) <!--23-->
使用:
request({ //对象解构 baseConfig: { }, success: function(res) { }, failure: function (err) { } }) <!--24-->
使用:
request({ url: '/home/multidata' }).then(res => { console.log(res); }).catch(err => { console.log(err); }) <!--25-->
使用:
```javascript
request({url: '/home/multidata'
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#### 6.axios拦截器的使用
- axios提供了拦截器,用于发送每次请求或得到响应后,进行对应处理
- 作用:请求之前想要做什么事情就需要拦截器,比如可以在请求前加一个loading,请求成功后关闭loading
- 使用:
- ```javascript
import axios from 'axios'
export function request(config){
//1.创建axios实例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.axios拦截器
//拦截请求
instance.interceptors.request.use(config => {
//发送请求成功
console.log(config);
// 1.比如config中一些信息不符合服务器要求
// 2.比如每次发送网络请求,都希望在界面中显示一个请求图标
// 3.某些网络请求(比如登陆),必须携带特殊信息(token)
return config
},err => {
//发送请求失败
console.log(err);
})
//拦截响应
instance.interceptors.response.use(res => {
// 响应成功
console.log(res);
// 比如只拿出res.data数据
return res
}, err => {
// 响应失败
console.log(err);
})
//3.发送真正的网络请求
return instance(config)
}