一.Promise
1.文件路径取别名
CLI2在build/webpack.base.conf.js下的alias中可给文件夹取别名:
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
//下面是老师常取的别名
'@': resolve('src'),
'assets': resolve('@/assets'),
'components': resolve('@/components'),
'views': resolve('@/views')
}
},
CLI4的话,在@vue这个文件夹下面有一个cli-service的文件夹
2.什么情况下会用到Promise
一般情况下是有异步操作时,使用Promise对这个异步操作进行封装。以解决回调地狱的问题。
3.Promise的基本使用
-
创建的Promise需要一个参数,这个参数是一个函数
-
resolve、reject作为函数的参数,同时它们又是函数
-
resolve()表示对then中的箭头函数进行调用,reject()表示对catch中的箭头函数进行调用
const p = new Promise(
(resolve, reject) => {
setTimeout(() => {
resolve('Hello World!');
reject('Data Error!')
}, 1000)
}
).then((data) => {
console.log(data)
}).catch((data) => {
console.log(data);
})
二、Vuex
定义:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
你可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。
与自己手动封装一个对象,对共享变量进行管理最大的不同是,vuex插件可以做到响应式。
1.安装Vuex
npm install vuex --save //codeWhy安装的是3.1.0版本
- 创建store文件夹用来存放vuex相关信息
- 创建index.js文件
在index.js文件中写如下代码:
import Vue from 'vue'
import Vuex from 'vuex'
// 1.安装插件
Vue.use(Vuex)
// 2.创建对象
const store = new Vuex.Store({
})
// 3.导出store
export default store
- 在main.js文件中进行挂载
import Vue from 'vue'
import App from './App'
import store from './store' //导入store对象
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store, //挂载store对象
render: h => h(App)
})
2.mutation的使用
我们通过提交mutation的方式,而非直接改变store.state.count。这是因为Vuex可以更明确的追踪状态的变化,所以不要直接改变store.state.count的值。
1.在mutation中定义方法
mutations: {
//方法
//默认有参数state
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
},
2.在App.vue的methods中引用
methods: {
addition() {
this.$store.commit('increment')
},
subtraction() {
this.$store.commit('decrement')
}
}
3.利用@cllick进行使用
<button @click="addition">+</button>
<button @click="subtraction">-</button>
3.getters的使用
vuex中的getters相当于vue中的computed属性。getters定义的属性可以直接在App.vue中进行调用,但mutation定义的函数需要先在methods中利用commit()调用后才能使用。
属性定义:
getters: {
powerCounter(state) {
return state.counter * state.counter
},
getStu(state) {
return state.student.filter(s => s.age >= 20).length
}
},
属性调用:
<h2>年龄大于20的学生人数:{{$store.getters.getStu}}</h2>
<h2>counter的平方:{{$store.getters.powerCounter}}</h2>
4.commit()方法
commit()方法的第一参数是函数,第二个参数可以传入让参数一函数进行调用的参数。
methods: {
addition() {
//必须使用commit()方法对mutation中定义的方法进行调用
this.$store.commit('increment')
},
subtraction() {
this.$store.commit('decrement')
},
addCount(count) {
this.$store.commit('incrementCount', count)
},
addStudent() {
const stu = {id: 114, name: 'alen', age: 35}
this.$store.commit('addStudent', stu)
}
}
Payload:在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数。
这些参数被称为是mutation的载荷(Payload)
5.对对象数据进行添加和删除的响应式方法
// 下面这个方法是响应式的方法
// Vue.set(state.info, 'address', 'Guangzhou')
// 删除元素
Vue.delete(state.info, 'age')
6.actions属性
mutation无法处理异步操作,而网络请求往往是异步的。故actions属性是用来处理异步操作的。
context是和store对象具有相同方法和属性的对象。也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等。
流程:app.vue -> actions -> mutation
store文件中代码:
mutations: {
updateInfo(state) {
state.info.name = 'Leon'
}
},
actions: {
// context: 上下文
// aUpdateInfo(context, payload) {
// setTimeout(() => {
// context.commit('updateInfo')
// console.log(payload.message);
// payload.success()
// }, 1000)
// },
aUpdateInfo(context, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('updateInfo');
console.log(payload);
resolve('1111111')
}, 1000)
})
}
},
App.vue文件中methods代码:
updateInfo() {
// this.$store.commit('updateInfo')
// this.$store.dispatch('aUpdateInfo', {
// message: '我是携带的信息',
// success: () => {
// console.log('里面已经完成了');
// }
// })
this.$store.dispatch('aUpdateInfo', '我是携带的信息').then(res => {
console.log('里面完成了提交');
console.log(res);
})
},
7.模块化module
首先,在vuex的store中定义moduleA
const store = new Vuex.Store({
modules: {
a: moduleA
}
})
然后,创建moduleA对象:
const moduleA = {
state: {
name: 'zhangsan'
},
mutations: {
updateName(state, payload) {
state.name = payload
}
},
getters: {
fullName(state) {
return state.name + '111'
},
//可以直接传入getters作为参数
fullName2(state, getters) {
return getters.fullName + '222'
},
//也可以拿到store对象中的state参数
fullName3(state, getters, rootState) {
return getters.fullName2 + rootState.counter
}
},
actions: {}
}
8.对象的解构写法
const obj = {
name: 'Leon',
age: 18,
height: 188
}
//ES6语法,会自动获取到对应的值,不需要按照顺序写也可以
const {name, height, age} = obj
所以,在module中有时会这样写:
const moduleA = {
actions: {
add({state, commit, rootState}) {
//上述代码表示取了context对象中的state、commit、rootState属性作为参数
//执行代码
}
}
}
三、网络请求封装
1.axois
回顾ajax-axios:
- 可以通过BootCDN搜索axios
- 复制script标签,在文件中导入
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
在终端输入:node server.js 启动服务器监听。
最后通过html页面的按钮触发请求。
2.Vue中的axios使用:
1.在VueCLI2项目文件夹下进行安装:
npm install axios --save
2.在main.js文件中导入并调用
import axios from 'axios'
//1.axios的基本使用
axios({
//测试接口
// url: 'httpbin.org'
url: 'http://123.207.32.32:8000/home/multidata',
methods: 'get' //请求方法可以不写,则默认是get请求
}).then(res => {
console.log(res);
})
axios.all方法,可以同时发送多个请求:可以设置默认路径、超时设置等。
axios.spread方法可以将结果分别打印出来。不用该方法则打印结果为一个结果数列。
.then(results => {
console.log(results);
})
/*
接口1:随机笑话
请求地址:https://autumnfish.cn/api/joke/list
请求方法:get
请求参数:num(笑话条数,数字)
响应内容:随机笑话
*/
axios.defaults.baseURL = 'https://autumnfish.cn/api/joke/list' //默认路径
axios.defaults.timeout = 5000 //超时设置,超过5s报错
axios.all([axios({
url: '?num=1',
}), axios({
params: {
num: 2
}
}
)]).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
3.创建对应的axios实例
之前的axios方法都是全局调用,创建axios实例后便可解决不同网页对应不同的接口地址问题。
const instance1 = axios.create({
baseURL: 'https://autumnfish.cn/api/joke/list',
timeout: 5000
})
instance1({
url: '/?num=1'
}).then(res => {
console.log(res);
})
instance1({
url: '',
params: {
num: 2
}
}).then(res => {
console.log(res);
})
const instance2 = axios.create({
baseURL: 'https://autumnfish.cn/api/joke',
timeout: 5000
})
4.减少对axios框架的依赖
- 因为做项目的过程中,担心框架有一天可能会不再维护了。所以往往采用封装的思想,将对axios的使用进行封装。减少对于框架的依赖性。
- 创建network文件夹,在内部创建request.js文件。
- conf表示配置,success和failure分别表示请求成功和失败的回调函数
import axios from 'axios'
export function request(config, success, failure) {
// 1.创建axios实例
const instance = axios.create({
baseURL: 'https://autumnfish.cn/api/joke',
timeout: 5000
})
//发送真正的网络请求
instance(config).then(res => {
success(res)
}
).catch(err => {
failure(err)
}
)
}
在main.js文件中进行导入:
import {request} from './network/request'
request({
url: '?num=1'
}, res => {
console.log(res);
}, err => {
console.warn(err);
})
5.axios拦截器
为什么需要拦截器?
- 比如config中的一些信息不符合服务器的要求
- 比如每次发送网络请求时,都希望在界面中显示一个请求的图标
- 某些网络请求(比如登陆需要携带tocken)必须携带一些特殊的信息
在request.js文件中设置拦截器:拦截器分为请求拦截和响应拦截。