上一篇文章Vue学习之认识到应用(二)因为字太多页面反应不过来,卡了。重新写了一部分,难受。
目录
13.Vue-Router前端路由
13.1.路由的发展阶段
13.1.1.后端路由阶段
13.1.2.前后端分离阶段
13.1.3. 单页面富应用阶段
13.2.URL和内容映射
13.2.1. hash
13.2.2.history模式
13.3.vue-router的基本使用
13.3.1.Vue Router的安装
13.3.2.Vue Router的使用
13.3.3.路由的默认路径
13.3.4.history模式
13.3.5.router-link
13.3.6.路由懒加载
13.3.7.路由的其他属性
13.4.动态路由
13.4.1.获取动态路由的值
13.5.NotFound
13.6.路由嵌套
13.6.1.路由的嵌套配置
13.7.代码的页面跳转
13.7.1.在vue2中实现页面跳转
13.7.2.vue2页面跳转的query参数
13.7.3.vue3中实现页面跳转
13.7.4.页面的前进后退
13.8.动态添加路由
13.8.1.动态管理路由
13.9.路由导航守卫
13.9.1.用户登录守卫案例
14. Vuex状态管理
14.1. Vuex和全局对象的区别
14.2.Vuex的基本使用
14.2.1.vuex的安装
14.2.2. 创建store
14.2.3.组件中使用state
14.2.4.单一状态树
14.3.mapState的使用
14.3.1.在options api中使用mapState
14.3.2. 在setup中使用mapState
14.4.getters的使用
14.4.1.getters的第二个参数
14.4.2.getters的返回函数(了解)
14.5.mapGetters的使用
14.5.1.在options api中使用mapGetters
14.5.2.在setup中使用mapGetters
14.6.Mutations的使用
14.6.1.Mutations携带参数
14.7.mapMutations的使用
14.7.1.在options api使用mapMutations
14.7.2.mutations重要原则
14.8.actions的使用
14.8.1.actions的分发操作
14.8.2.actions携带参数
14.9.mapActions的使用
14.9.1.在options api使用mapActions
14.9.2.在setup使用mapActions
14.10.module的使用
14.10.1. module的局部状态
14.10.2.module的命名空间
14.10.3.module修改或派发根组件
15.Pinia状态管理
15.1.Pinia和Vuex的区别
15.2.Pinia的使用
15.3.认识Store
15.3.1.定义Store
15.3.2.Store的使用
15.4.State的使用
15.4.1.读取和写入state
15.4.2.重置state
15.4.3.改变state
15.4.4.替换state
15.5.Getters的使用
15.5.1. 访问当前store的getters
15.5.2.getters访问其他getters
15.5.3.访问其他store的getters
15.5.4.getters返回函数
15.6.Actions的使用
15.6.1.Actions执行异步操作
16.网络请求库 - axios
16.1. axios请求方式
16.2.常见的配置选项
16.3. axios的创建实例
16.4.请求和响应拦截器
16.5.axios请求库封装
路由的概念在软件工程中出现,最早是在后端路由中实现的,web的发展主要经历了这样一些阶段:
早期的网站开发整个HTML页面是由服务器来渲染的.
前端渲染的理解:
其实SPA最主要的特点就是在前后端分离的基础上加了一层前端路由.
也就是前端来维护一套路由规则.
前端路由的核心是什么呢?改变URL,但是页面不进行整体的刷新。
前端路由是如何做到URL和内容进行映射呢?
监听URL的改变。有两种模式来改变url,不刷新页面:
URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径。
除了hash模式之外,还可以用history模式实现。
history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面:
目前前端流行的三大框架, 都有自己的路由实现:
Vue Router是Vue.js的官方路由:它与Vue.js核心深度集成,让用Vue.js构建单页应用(SPA)变得非常容易。
vue-router是基于路由和组件的
所以vue-router的作用就是根据编写的映射关系切换组件。
vue-router要安装在项目里面,所以在项目目录里面使用指令。
npm install vue-router
这样就代表安装成功了。
使用vue-router的步骤:
1.创建路由需要映射的组件(打算显示的页面);
2.通过createRouter创建路由对象,并且传入routers和history对象;
可以在src创建一个router文件夹,创建index.js文件,在index里面编写。
import { createRouter, createWebHashHistory } from 'vue-router'
//导入创建的组件
import Home from '../components/Home.vue'
import About from '../components/About.vue'
//配置路由的映射
const routes = [
{ path: '/home', component: Home },
{ path: '/About', component: About }
]
//创建router对象
const router = createRouter({
routes,
history: createWebHashHistory()
})
//将router导出
export default router
3.使用app注册路由对象(use方法);
在main.js导入router,使用use方法使用
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
4.通过
主页
关于
router-link路径切换,to编写要去的路径,router-view显示router-link的内容。
怎么让路径默认跳到首页,并且
const routes = [
{ path:'/', redirect: '/home'},
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
前面的hash模式可以看到路径上面有#,有的时候不希望出现这样的符号,可以设置为history模式。
只要从vue-router引入createWebHistory,并且在createRouter函数对象里面的history设置为createWebHistory()即可。
可以看到路径上没有#了。
router-link也可以设置其他的属性。
to属性:
使用replace属性, 在点击了有replace属性的路径的时候,新的路径直接替代旧的路径,不能通过返回键回到旧的路径。
默认有router-link-active的class名,通过active-class可以设置class名。
主页
关于
把active状态的class名改成active,就可以用css编写样式了。
和active-class类似的用法。
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载:
在11.5章节中有讲到怎么将代码分包。
Vue Router支持动态导入组件。
const routes = [
{ path:'/', redirect: '/home'},
{ path: '/home', component: () => import('../components/Home.vue') },
{ path: '/about', component: () => import('../components/About.vue') }
]
在打包后,就会进行分包了。
打包代码 npm run build
name属性:路由记录独一无二的名称;
const routes = [
{ path:'/',
redirect: '/home'
},
{ path: '/home',
name: 'home',
component: () => import('../components/Home.vue'),
meta: {
name: 'zzz',
age: 16
}
},
{ path: '/about',
component: () => import('../components/About.vue')
}
]
很多时候我们需要将给定匹配模式的路由映射到同一个组件:
{
path: '/user/:id',
component: () => import('../components/User.vue')
}
在router-link中进行如下跳转:
路由后面可以加参数,但是显示的依然是同一个页面。
在User.vue组件中如何获取到对应的值呢?
user: {{ $route.params.id }}
created() {
console.log("create的",this.$route.params.id);
}
import { useRoute } from 'vue-router'
setup() {
const route = useRoute()
console.log(route);
console.log(route.params.id);
}
{
path: '/:pathMatch(.*)',
component: () => import('../components/NotFound.vue')
}
我们可以通过$route.params.pathMatch获取到传入的参数
NotFound:{{$route.params.pathMatch}}
匹配规则加*
也可以在/:pathMatch(.*)后面加一个*;
{
path: '/:pathMatch(.*)*',
component: () => import('../components/NotFound.vue')
}
/:pathMatch(.*)与 /:pathMatch(.*)*的区别在于解析的时候,是否解析/:
/:pathMatch(.*)
/:pathMatch(.*)*
什么是路由的嵌套,上面写的Home、About、User等都属于第一层路由,我们在它们之间来回切换。
但是Home页面,也可能会在多个组件之间来回切换:我们可以使用嵌套路由,在Home中也使用router-view来占位之后需要渲染的组件。
比如下面的发现音乐页面还可以切换排行榜。
想要实现路由嵌套,可以嵌套一个children数组,在里面编写路由信息。
要注意path不需要/
{ path: '/home',
name: 'home',
component: () => import('../components/Home.vue'),
meta: {
name: 'zzz',
age: 16
},
children: [
{
path: 'recommend',
component: ()=> import('../components/homeRecommend.vue')
}
]
},
一些普通元素想要进行页面跳转,不像router-link有to属性,所以我们就需要用代码编写方法来实现页面跳转。
编写一个触发跳转的元素,给该元素添加上方法。
btnClick() {
this.$router.push('/about')
}
btnClick() {
this.$router.replace('/about')
}
也可以传入一个对象。
btnClick() {
this.$router.push({
path: '/about'
})
}
使用对象写法可以传入更多的参数,可以传入query。
btnClick() {
this.$router.push({
path: '/about',
query: { name: 'zzz', age: 14 }
})
}
在界面中可以通过$route.query来获取参数。
query{{ $rooute.query.name }}
在vue3中需要将useRouter函数导入,使用router
对象参数和query参数与上面的vue2的类似。
router的go方法:
router也有back:
const adminRoute = {
path:'/admin',
component: () => import('../components/admin.vue')
}
router.addRoute(adminRoute)
也可以判断是否拥有权限来动态添加路由。
let isAdmin = false
if(isAdmin){
const adminRoute = {
path:'/admin',
component: () => import('../components/admin.vue')
}
router.addRoute(adminRoute)
}
上面的isAdmin的false值可以动态改变,当isAdmin为false的时候,就不添加admin这个路由。
如果想要为route添加一个children路由,那么需要传入name。
给home添加children路由,在addRoute前面的参数添加name。
const adminRoute = {
path:'/admin',
component: () => import('../components/admin.vue')
}
router.addRoute('home', adminRoute)
三种删除路由的方式:
1.添加name相同的路由;如果name相同,就会删除之前已经添加的路由,因为它们名字必须是唯一的。
router.addRoute({path:'/about', name:'about', components: About})
2.通过removeRoute方法,传入路由名称;
router.removeRoute('about')
3.通过addRoute方法的返回值回调;
const removeRoute = router.addRoute(routeRecord)
removeRoute()
除了删除路由,还有其他的方法。
比如要完成一个功能:只有在登录了之后才可以查看用户的订单,就可以用路由导航守卫在要跳转的两个页面中间拦截判断逻辑。
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
全局的前置守卫beforeEach是在导航触发时会被回调的:
router.beforeEach((to, from) => {
console.log(to);
console.log(from);
return false
})
我们想完成一个需求:点击进入到订单页面,判断用户是否登录。
一般我们在完成登录的时候,服务器会传递一个token保存到localStorage来表示登录成功。
//route.js
router.beforeEach((to, from) => {
console.log(to);
console.log(from);
const token = localStorage.getItem("token")
if(!token && to.path === "/order"){
return "/login"
}
})
Vue-Router还提供了很多的其他守卫函数,目的都是在某一个时刻给予我们回调,让我们可以更好的控制程序的流程或者功能:
在开发中,我们的应用程序需要处理各种各样的数据,这些数据需要保存在我们应用程序中的某一个位置,对于这些数据的管理我们就称之为是状态管理。
在Vue开发中,我们使用组件化的开发方式。
在开发的过程中就是在这三者之间不断循环。
之前不是学过父子组件和非父子组件之间的数据传递吗?这个不能实现状态管理吗?
管理不断变化的state本身是非常困难的:
因此,我们是否可以考虑将组件的内部状态抽离出来,以一个全局单例的方式来管理呢?
第一:Vuex的状态存储是响应式的
如果在创建项目的过程中有选择安装vuex就不用再安装了,如果没有选择就需要安装一下。
我们要使用vuex,第一步就是安装。
npm install vuex
开发的时候一般在src文件中创建store文件夹用来储存状态。
//store index.js
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 0
})
})
export default store
//main.js
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')
把store的index.js文件导出就能在main.js使用了,use(store)。
在store中定义了一个counter, 怎么在组件中使用?
1.在组件template中使用state
app计数: {{$store.state.counter}}
这样就可以拿到store的counter了。
2.在vue3的setup中使用state
我们来实现点击按钮将counter增加的需求。
app计数: {{$store.state.counter}}
//store index.js
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 0
}),
mutations: {
increment(state) {
state.counter++
}
}
})
因为不能直接改变store的状态,所以我们需要显示提交mutations。在本案例中的store.commit("increment")需要与mutations的increment相对应,increment传入state就可以使用state修改counter的内容了。
3. 在vue2的options api中使用state
app计数: {{$store.state.counter}}
app options api计数: {{ storeCounter }}
可以在computed里面使用this.$store.state.来获取store里面的数据。
Vuex 使用单一状态树:
前面学习了怎么在组件中获取状态,但是只是拿一个状态;
如果我们有很多状态要获取的话,就可以使用mapState的函数。下面state里面有三个变量。
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 0,
name: "zzz",
level: 100
}),
mutations: {
increment(state) {
state.counter++
}
}
})
export default store
可以使用展开运算符和原来有的computed混合在一起;
有的时候data会和state里面的变量相同,mapState里面的名又需要和state里面的相同,使用对象类型就可以给变量重命名了。
...mapState({
sName: state => state.name,
sLevel: state => state.level,
sCounter: state => state.counter,
})
这样就可以使用sName、sLevel、sCounter了。
在setup中如果我们获取单个状态是非常简单的:
import { useStore, mapState } from 'vuex'
import { computed } from 'vue'
export function useState(mapper) {
const store = useStore()
const stateFns = mapState(mapper)
const newState = {}
Object.keys(stateFns).forEach(key => {
newState[key] = computed(stateFns[key].bind({$store: store}))
})
return newState
}
这样太麻烦了,开发的时候可以直接对store.state进行解构。
import {toRefs} from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const {name, level} = toRefs(store.state)
如果怕命名有冲突还可以起别名。
const { name: cName, level: cLevel } = toRefs(store.state)
getters是将数据处理,有点类似于computed。某些属性可能需要经过变化后来使用,这个时候可以使用getters。
const store = createStore({
state: () => ({
counter: 10,
}),
getters: {
doubleCounter(state) {
return state.counter * 2
}
}
doubleCounter:{{ $store.getters.doubleCounter }}
可以用$store.getters.doubleCounter来拿到getters里面的处理过后的数据。
getters也可以传入第二个参数getters,在本案例中是使用了getters里面的bookName。
本案例是创建了一个books数组,在getters的bookName传入state中的name,而getters的totalPrice使用reduce高阶函数将price相加,并且返回bookName。
const store = createStore({
state: () => ({
name: "zzz",
books: [
{ id:11, name:"book1", price:20 },
{ id:22, name:"book2", price:25 },
{ id:33, name:"book3", price:26 },
]
}),
getters: {
bookName(state) {
return state.name
},
totalPrice(state, getters) {
let price = state.books.reduce((preValue, item) => {
return preValue + item.price
},0)
return price + "," + getters.bookName
}
}
})
totalPrice:{{ $store.getters.totalPrice }}
getters中的函数本身、可以返回一个函数、在使用的时候相当于可以调用这个函数。
totalPriceFunction(state) {
return function(price){
let totalPrice = state.books.reduce((preValue, item)=> {
if(price > 15){
return preValue + item.price
}
}, 0)
return totalPrice
}
}
也可以使用箭头函数。
totalPriceFunction(state) {
return (price) => {
let totalPrice = state.books.reduce((preValue, item)=> {
if(price > 15){
return preValue + item.price
}
}, 0)
return totalPrice
}
}
在使用的时候可以传入参数。
totalPriceFunction:{{ $store.getters.totalPriceFunction(11) }}
我们也可以使用mapGetters的辅助函数,当一次想要使用很多个getters的时候。
可以使用展开运算符和原来有的computed混合在一起;
mapGetters方式一:数组类型
使用mapGetters辅助函数就可以在template中插值语法使用了
bookName:{{ bookName }}
totalPrice:{{ totalPrice }}
mapGetters方式二:对象类型
...mapGetters({
sBookName: getters => getters.bookName,
sTotalPrice: getters => getters.totalPrice,
})
如果想要自己封装一个像在options api里面的mapGetters函数太麻烦了,不如直接解构,再用toRefs包裹实现响应式。
更改vuex的store中的状态唯一方法是提交mutation。虽然直接用state修改也是修改,但是不符合规范,不符合单项数据流的标准。为了vuex对数据更改进行跟踪。
counter: {{$store.state.counter}}
需要将更改数据的操作使用this.$store.commit发射出去,在mutations可以对数据进行处理。
const store = createStore({
state: () => ({
counter: 10
}),
mutations: {
increment(state) {
state.counter++
},
decrement(state) {
state.counter--
}
}
})
很多时候我们在提交mutation的时候,会携带一些数据,这个时候我们可以使用参数。
mutations: {
increment(state, payload) {
state.counter++
console.log(payload);
}
},
methods: {
increment() {
this.$store.commit("increment","参数")
}
}
payload可以为对象类型,我们也可以传入对象。
methods: {
increment() {
this.$store.commit("increment",{ counter:10, name:"name" })
}
}
mutations: {
increment(state, payload) {
state.counter += payload.counter
}
},
对象风格的提交方式。
this.$store.commit({
type: "addNumber",
counter: 100
})
如果方法很多,可以用mapMutations辅助函数来拿多个。
mapMutations数组类型
想做异步操作可以使用actions。
Action类似于mutation,不同在于:
这里有一个非常重要的参数context:
actions: {
increment(context) {
context.commit("increment")
}
}
如何使用action?可以进行action的分发:分发使用的是store的dispatch函数。
counter: {{$store.state.counter}}
在actions里面需要再提交一次mutation,才能修改state里面的值。
和mutation相同,action也可以传递参数。
btnClick() {
this.$store.dispatch("increment", {count: 100})
}
也可以以对象的形式进行分发。
btnClick() {
this.$store.dispatch({
type: "increment",
count: 100
})
}
action也有对应的辅助函数。一次想要取多个action的时候可以使用。
mapActions方式一:数组类型
mapActions方式二:对象类型
...mapActions(
{
add: "increment",
sub: "decrement"
}
)
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂时,store 对象就有可能变得相当臃肿;
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
const moduleA = {
state: ()=> ({
}),
getters: {},
mutations: {},
actions: {}
}
const moduleB = {
state: ()=> ({
}),
getters: {},
mutations: {},
actions: {}
}
{{ $store.state.moduleA.xx }}
如果需要拿state里面的内容,需要多加一个模板名。
{{ $store.getters.xx }}
想拿getters里面的内容,是不需要模块名的。 但是可能会冲突,14.10.2.module的命名空间有讲到。
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象:
mutations: {
changeName(state) {
state.name = "zzz"
}
},
getters: {
info(state, getters ,rootState) {
return state.name
}
}
默认情况下,模块内部的action和mutation仍然是注册在全局的命名空间中的:
const moduleA = {
namespaced: true,
state: ()=> ({
}),
getters: {},
mutations: {},
actions: {}
}
添加了namespaced:true之后,要使用getters就需要这样来做。
{{ $store.getters["模块名/模块getter"] }}
提交mutation时,默认也是不跟模块名称的,加了namespaced:true之后,也要加上模块名。
store.commit("模块名/模块mutation")
提交action也一样。
如果想要在模块里面修改根组件的state内容,可以这么做。
changeAction({commit, dispatch, state, rootState, getters, rootGetters}){
commit("changeName", null, {root: true})
dispatch("changeRootAction", null, {root: true})
}
null是传递的参数,{root: true}代表传递给根组件。
Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理,让它用起来像组合式API(Composition API)。
在前面学习vuex的时候发现在setup使用辅助函数很不好用,所以给vue3设计一个更符合composition 的状态管理库,Pinia。
那么我们不是已经有Vuex了吗?为什么还要用Pinia呢?
和Vuex相比,Pinia有很多的优势:
在使用Pinia之前需要先安装。
npm install pinia
创建一个stores文件夹来放pinia
// stores index.js
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
在main.js中引用。
import { createApp } from 'vue'
import App from './App.vue'
import pinia from '../stores'
createApp(App).use(pinia).mount('#app')
一个 Store (如 Pinia)是一个实体,它会持有为绑定到你组件树的状态和业务逻辑,也就是保存了全局的状态;
它有点像始终存在,并且每个人都可以读取和写入的组件;
Store是使用defineStore()定义的,它需要有一个唯一名称,作为第一个参数传递。
在stores的index.js创建完之后,不用将内容写在这个文件里面,可以在其他文件编写。
import { defineStore } from 'pinia'
const useCounter = defineStore("counter", {
state: ()=> ({
count: 90
})
})
export default useCounter
defineStore里面的第一个参数,这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store:
counter: {{ counterStore.count }}
在template里面使用,都不需要使用$store.state拿count。
注意Store获取到后不能被解构,那么会失去响应式:
const { count } = counterStore //不是响应式的
const { count: count1 } = toRefs(counterStore) //响应式的
const { count: count2 } = storeToRefs(counterStore) //响应式的
state是Pinia的核心部分,在 Pinia 中,状态被定义为返回初始状态的函数;
const useCounter = defineStore("counter", {
state: ()=> ({
count: 90,
name: "zzz",
age: 16
})
})
默认情况下,可以通过store实例访问状态来直接读取和写入状态;在vuex中是不能直接写入状态的,而是要通过mutation。
可以通过调用store上的$reset()方法将状态重置到其初始值。
const counterStore = useCounter()
counterStore.$reset()
除了直接用store.count++修改store,还可以调用$patch方法;
允许使用部分state对象同时应用多个更改。
const counterStore = useCounter()
counterStore.$patch({
count: 100,
name: "ccc"
})
可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:
const counterStore = useCounter()
counterStore.$state = {
count: 100,
name: "ccc"
}
Getters相当于Store的计算属性:
import { defineStore } from 'pinia'
const useCounter = defineStore("counter", {
state: ()=> ({
count: 90,
name: "zzz",
age: 16
}),
getters: {
doubleCount(state){
return state.count * 2
}
}
})
export default useCounter
访问当前store的getters和使用state用法一致。
counter: {{ counterStore.count }}
doubleCount: {{ counterStore.doubleCount }}
我们可以通过this来访问到当前store实例的所有其他属性;
getters: {
doubleCount(state){
return state.count * 2
},
doublePlusOne(state) {
return this.doubleCount + 1
}
}
getters: {
message: function(state) {
const userStore = useUser()
return userStore.name
}
}
getters返回函数就可以在使用的时候写入参数了。
import { defineStore } from 'pinia'
const useCounter = defineStore("counter", {
state: ()=> ({
users:[
{id: 111, name: "zzz", age: 18},
{id: 222, name: "xxx", age: 24},
{id: 333, name: "ccc", age: 28},
]
}),
getters: {
getUserById(state) {
return userId => {
return state.users.find(item => item.id === userId)
}
}
}
})
export default useCounter
User: {{ getUserById(111) }}
Actions相当于组件中的methods。可以使用this.变量来修改变量的值。
和getters一样,在action中可以通过this访问整个store实例的所有操作。
actions: {
increment() {
this.count ++
}
}
counter: {{ counterStore.count }}
counterStore.actions方法名()就可以使用actions里面的方法了,非常方便。
Actions中是支持异步操作的,我们可以编写异步函数,在函数中使用await。
actions: {
async fetchAction() {
const res = await fetch("http://xxx.xxx.xx.xx/xxx")
const data = await res.json()
return data
}
}
在以前vue是有维护过一个网络请求库的,但在2016年11月份后推荐使用axios了。
axios有很多功能特点。
import axios from 'axios'
支持多种请求方式:
//axios.get("http://xxx.xx.xx.xx:8080/home?id=111")
axios.get("http://xxx.xx.xx.xx:8080/home",{
params: {
id:111
}
}).then(res => {
console.log("res", res.data)
})
axios.post("http://xxx.xx.xx.xx:8080/home", {
//如果有参数可以放到这里
name: 1111,
password: 200
}).then(res => {
console.log("res": res.data)
})
//也可以这样写
axios.post("http://xxx.xx.xx.xx:8080/home", {
//如果有参数可以放到这里
data:{
name: 1111,
password: 200
}
}).then(res => {
console.log("res": res.data)
})
有时候, 我们可能需求同时发送两个请求
const baseURL = "http://xxx.xx.xx.xx/8080"
axios.defaults.baseURL = baseURL
axios.get("/home/aa").then(res => {
console.log("res": res.data)
})
为什么要创建axios的实例呢?
当我们从axios模块中导入对象时, 使用的实例是默认的实例; 当给该实例设置一些默认配置时, 这些配置就被固定下来了. 但是后续开发中, 某些配置可能会不太一样;
在开发中可能会有多个实例。
const instance1 = axios.create({
baseURL: "http://xxx.xx.xx.xx:8080",
timeout: 8000,
headers:{}
})
instance1.get("/home",{
params:{
id: 100
}
}).then(res=> {
console.log(res.data);
})
axios可以设置拦截器:拦截每次请求和响应
拦截请求
axios.interceptors.request.use((config)=> {
console.log("请求拦截成功");
//开始loading的动画
//对原来的配置进行修改 1.header 2.认证登录 token/cookie 3.请求参数进行某些转化
return config
}, err =>{
console.log("请求拦截失败")
return err
})
拦截结果
axios.interceptors.response.use((res)=> {
console.log("响应拦截成功");
//结束loading的动画
//对数据进行转化
return res.data
}, err =>{
console.log("响应拦截失败")
return err
})
res.data可以拿到data结果。
import axios from "axios";
class MyRequest {
constructor(baseURL, timeout = 10000) {
this.instance = axios.create({
baseURL,
timeout
})
}
request(config) {
return new Promise ((resolve, reject)=> {
this.instance.request(config).then(res => {
resolve(res.data)
}).catch(err => {
reject(err)
})
})
}
get(config) {
return this.request({ ...config, method: "get"})
}
post(config) {
return this.request({ ...config, method: "post"})
}
}
const myRequest1 = new MyRequest("http://xxx.xx.xx.xx:8080")
const myRequest2 = new MyRequest("http://xxx.xx.xx.xx:8888")
//也可以把myRequest1导出
export default new MyRequest("http://xxx.xx.xx.xx:8080")