二、Vue3前后端分离

1.常见ES6语法

1.1变量和常量

var/let/const

var作用域为函数
let作用域为块(函数内)
const作用域为块,常量
    不能修改info常量,可以修改里面的value和id
<script>
    const info = {id:1,value:18};  // 块级作用域 + 常量(ref)
    
    info.value = 999;
</script>

1.2模板字符串

使用模板字符串更加方便
<script>
    let name = "张开";
    let age = 73;
    
    let info =  `我叫${name},今年${age}岁`;
</script>

1.3动态参数

 动态参数:...data
实现一次接收多个参数或者传入多个参数
<script>
    function info(v1,...data){
        console.log(v1,data);
    }

    info(11,22,333,444,55);    //11传给v1,后续的其他数传给data
</script>


<script>
    function info(v1,v2,v3,v4){
        console.log(v1,v2,v3,v4);
    }

    info(11,22,333,444);
    nums = [22,33,44,55,66,77,88];
    info(11,...nums)                //nums打散后依次传入,多余的数不会传入,少于参数时未传入值的参数为undefine
</script>

1.4解构赋值

<script>
    let info = {name:"武沛齐",email:"wupeiqi@live.com",addr:"北京"};
    let {name,addr} = info;     
    
    console.log(name);
    console.log(addr);
</script>
Vue3中需要什么就要导入什么,不像vue2中this.$router this.$route。
import {name,addr} from 'vue'
<script>
    
    function getData(n1,{name,addr}){
        //let {name,addr} = info; 
        
        console.log(name);
        console.log(addr);
    }
    
    let info = {name:"武沛齐",email:"wupeiqi@live.com",addr:"北京"};
    getData(111,info);    //传入info对象,解构出name和addr直接使用
    
</script>
列表中同样可以使用:
<script>
    let nums = [11,22,33,44];
    let [n1,n2] = nums;
</script>
<script>
    function getData(n1,[n2,n3,n4]){
        console.log(n1,n2,n3,n4)
    }
    let nums = [11,22,33,44];
    getData(100,nums);
</script>

1.5 箭头函数

注意:使用箭头函数时,this对象指的当前,使用普通函数时,this对象不一定指当前。

<script>
    function f1(name,age){
        console.log(name,age);
    }
    f1("张开",99);
    
    //箭头函数
    let f2 = (name,age) =>{
        console.log(name,age);
    }
    f2("张开",99);
    
</script>

<script>
    var name = "源代码";
    let info = {
        name: "武沛齐",
        func: function () {
            console.log(this.name); // 函数内部默认都有this关键字,输出武沛齐
        }
    }
    info.func();

    function getData() {
        console.log(this.name); // 这里的this=window,输出 源代码
    }

    getData();
</script>

<script>
    var name = "源代码";
    let info = {
        name: "武沛齐",
        func: function () {
            console.log(this.name); // 函数内部默认都有this关键字,this=info对象,输出武沛齐

            function getData() {
                console.log(this.name); // 函数内部默认都有this关键字,this=window,输出 源代码
            }
            getData();
        }
    }
    info.func();
</script>



将getData改成箭头函数:

<script>
    var name = "源代码";
    let info = {
        name: "武沛齐",
        func: function () {
            console.log(this.name); // 函数内部默认都有this关键字,this=info对象

            let getData = () => {
                console.log(this.name); //无this关键字,找到上一级info的this,输出 武沛齐
            }
            getData();
        }
    }
    info.func();


</script>

1.6 模块导入

通过export导出变量或方法,通过import导入使用:

在这里插入图片描述

也可以通过直接导出对象使用:
在这里插入图片描述

2.flex布局

传统的页面布局:div+css+float实现。
flex布局更简单,包括容器和元素

2.1 容器

1.布局

<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
</div>

<style>
    .menu{
        
        display:flex;
    }
</style>

2.元素方向

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/,item元素横向排列
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
</div>


</body>
</html>

3.元素排列方式

justify-content: 主轴
align-items: 副轴
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/
            /*justify-content: space-evenly;*/
            justify-content: space-between;

            align-items: center;
            /*align-items: flex-start;*/
            /*align-items: flex-end;*/
        }
        .menu .item{
            width: 45px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
    <div class='item'>深圳</div>
</div>


</body>
</html>

4.换行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/
            /*justify-content: space-evenly;*/
            justify-content: flex-start;

            /*align-items: center;*/
            align-items: flex-start;
            /*align-items: flex-end;*/

            flex-wrap: wrap;   //超过时自动进行换行
        }
        .menu .item{
            width: 45px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
</div>


</body>
</html>

5.多行控制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/
            /*justify-content: space-evenly;*/
            justify-content: flex-start;

            /*align-items: center;*/
            align-items: flex-start;
            /*align-items: flex-end;*/

            flex-wrap: wrap;
            align-content: center;   //多行时起作用,控制换行时多行的垂直排放
        }
        .menu .item{
            width: 45px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
</div>


</body>
</html>

案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/


            /*justify-content: space-between;*/
            justify-content: space-around; /*横轴*/

            align-items: flex-start; /*纵轴*/

            flex-wrap: wrap;

            align-content: flex-start; /*多行文本,从顶部开始*/
        }

        .menu .item {
            width: 150px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item'>北京</div>
    <div class='item'>上海</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
    <div class='item'>深圳</div>
</div>


</body>
</html>

2.2 元素

1.顺序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/


            /*justify-content: space-between;*/
            justify-content: space-around; /*横轴*/

            align-items: flex-start; /*纵轴*/

            flex-wrap: wrap;

            align-content: flex-start; /*多行文本,从顶部开始*/
        }

        .menu .item {
            width: 50px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item' style="order: 1">北京</div>    //order指定顺序
    <div class='item' style="order: 0">上海</div>
    <div class='item' style="order: 2">深圳</div>
</div>


</body>
</html>

2.剩余空间

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .menu {
            border: 1px solid red;
            width: 500px;
            height: 500px;

            display: flex;
            flex-direction: row; /*主轴=横向*/


            /*justify-content: space-between;*/
            justify-content: flex-start; /*横轴*/
        }

        .menu .item {
            width: 50px;
            height: 50px;
            border: 1px solid green;
        }
    </style>
</head>
<body>
<div class='menu'>
    <div class='item' style="">北京</div>
    <div class='item' style="flex-grow: 2">上海</div>    //剩余空间使用flex-grow填充
    <div class='item' style="flex-grow: 1">深圳</div>
</div>


</body>
</html>

案例

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .container {
            width: 1100px;
            margin: 0 auto;
        }

        .row1 {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
        }

        .row1 .company {
            width: 210px;
            height: 180px;
            background-color: saddlebrown;
        }

        .row1 .pic {
            width: 266px;
            height: 180px;
            background-color: cadetblue;
        }

        .row2 .title {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
        }

        .row2 .pic-list {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
        }

        .row2 .pic-list .big {
            background-color: aquamarine;
            height: 610px;
            width: 210px;
            margin-right: 20px;
        }

        .row2 .pic-list .right-list {
            background-color: antiquewhite;
            flex-grow: 1;
        }

        .row2 .pic-list .right-list .group {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
            flex-wrap: wrap;
        }

        .row2 .pic-list .right-list .phone {
            margin-bottom: 10px;
            border: 1px solid red;
            width: 200px;
            height: 300px;
        }

        .course-list {
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap;
        }

        .course-list .item {
            width: 24%;
            height: 100px;
            background-color: skyblue;
            margin-top: 15px;
        }
        /*如果最后一个元素,是第3个,右边距=一个位置 + 所有空白位置/3(有三个空白位置)*/
        .course-list .item:last-child:nth-child(4n - 1) {
            margin-right: calc(24% + 4% / 3);
        }
        .course-list .item:last-child:nth-child(4n - 2) {
            margin-right: calc(48% + 8% / 3);
        }
    </style>
</head>
<body>

<div class="container">

    <div class="row1">
        <div class="company"></div>
        <div class="pic"></div>
        <div class="pic"></div>
        <div class="pic"></div>
    </div>

    <div class="row2">
        <div class="title">
            <div>手机</div>
            <div>查看更多</div>
        </div>

        <div class="pic-list">
            <div class="big"></div>
            <div class="right-list">
                <div class="group">
                    <div class="phone"></div>
                    <div class="phone"></div>
                    <div class="phone"></div>
                    <div class="phone"></div>
                </div>
                <div class="group">
                    <div class="phone"></div>
                    <div class="phone"></div>
                    <div class="phone"></div>
                    <div class="phone"></div>
                </div>
            </div>
        </div>
    </div>

    <div class="course-list">
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>
        <div class="item"></div>

    </div>
</div>

</body>
</html>

3.vue-router

3.1 安装

npm install vue-router --save
手动创建文件+配置

vue add router

3.2 必备操作

router下配置路由:
使用匿名指向组件和直接指向一样
使用什么需要导入什么
在这里插入图片描述

App.vue:

使用链接到组件,可以使用router里配置的path或者name来指向
在这里插入图片描述

1.URL传值(GET)

在App.vue中使用query来在url中传递值。
在组件中接收值需要:
1.导入useRoute,然后创建对象
2.使用route.query.变量来取到对应的值,变量需要使用ref包裹

此时存在的问题:
在url都传递了值的组件件跳转时,页面的参数数据不会变化
解决方法:
导入onBeforeRouteUpdate,参数to代表要跳转的组件
使用to.query.变量取出要跳转组件的数据赋值给当前页变量
在这里插入图片描述

2.URL动态参数params

参数在path中传递:

在这里插入图片描述

通过params传递参数:
在这里插入图片描述

在组件中接收展示:
在这里插入图片描述

3.路由嵌套

实现进入一个模块后,可选择下级多个路由进入子模块
router/index.js:

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
    {
        path: '/',
        name: "Index",
        component: HomeView
    },
    {
        path: '/home',
        name: 'Home',
        component: HomeView
    },
    {
        path: '/login',
        name: 'Login',
        component: () => import('../views/LoginView.vue'),
    },
    {
        path: '/pins',
        // name: 'Pins',
        component: () => import('../views/PinsView.vue'),
        children: [
            {
                path: '',    //访问pins组件时默认打开New组件,可以使用导入组件也可以使用重定向
                //component: () => import('../views/NewView.vue'),
                redirect: {name: "New"},
            },
            {
                path: 'new',
                name: 'New',
                component: () => import('../views/NewView.vue'),
            },
            {
                path: 'hot',
                name: 'Hot',
                component: () => import('../views/HotView.vue'),
            },
            {
                path: 'following',
                name: 'Following',
                component: () => import('../views/FollowingView.vue'),
            }
        ]
    },
    {
        path: '/course',
        name: 'Course',
        component: () => import('../views/CourseView.vue')
    },
    {
        path: '/detail/:id',
        name: 'Detail',
        component: () => import('../views/DetailView.vue')
    },
    {
        path: '/news',
        name: 'News',
        component: () => import('../views/NewsView.vue')
    }
]

const router = createRouter({
    history: createWebHistory(),
    routes
})

export default router

views/PinsView.vue

<template>
    <div>
        <div>上面的内容</div>
        <div>
            <h3>左边菜单</h3>
            <router-link :to="{name:'Hot'}">热点</router-link>
            <router-link :to="{name:'New'}">最新</router-link>
            <router-link :to="{name:'Following'}">关注</router-link>
        </div>
        <div>右边的内容</div>
        <div>
            <router-view/>
        </div>
    </div>
</template>

<script>
    export default {
        name: "PinsView"
    }
</script>

<style scoped>

</style>

4.编程式导航

实现跳转:
router-link标签
router对象实现 this.$router.push
使用push和replace的区别:
在浏览器回退时,push能回退到实现跳转的页面,replace会覆盖而直接回退到上一个页面

<template>
    <div>
        <h1>新闻页面</h1>
        <input type="button" value="跳转" @click="doClick"/>
    </div>
</template>

<script setup>
    import {useRouter} from 'vue-router'

    const router = useRouter();


    function doClick() {
        //跳转到首页 [Course,]
        // router.push({path:"/home"})
        // router.push({name:"Home"})
        // router.push({name: "Course", query: {page: 10, size: 20}})
        router.push({name: "Detail", params: {id: 100}, query: {page: 10, size: 20}})

        // router.replace({path:"/home"})
        // router.replace({name:"Home"})
        // router.replace({name: "Course", query: {page: 10, size: 20}})
        // router.replace({name: "Detail", params: {id: 100}, query: {page: 10, size: 20}})
        // router.replace({name: "Course", query: {page: 10, size: 20}})

    }
</script>

<style scoped>

</style>
4.1 登录跳转(保留顶部)

登录跳转时,有些会保留顶部的原始导航栏有些不保留。
LoginView.vue

<template>
    <div style="width: 400px;height: 200px;margin: 100px auto;">
        <input type="text" v-model="username">
        <input type="password" v-model="password">
        <input type="button" value="登录" @click="doLogin"/>
    </div>
</template>

<script setup>
    import {useRouter} from 'vue-router'
    import {ref} from 'vue'

    const router = useRouter();

    const username = ref("");
    const password = ref("");

    function doLogin() {
        //...
        if (username.value.length > 0 && password.value.length > 0) {
            console.log("登录成功");
            router.replace({name: "Home"})
        } else {
            console.log("登录失败");
        }
    }
</script>

<style scoped>

</style>

App.vue中导航保留
在这里插入图片描述

router/index.js:
在这里插入图片描述

4.2 登录跳转(不含顶部)

router/index.js:

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
    {
        path: '/login',
        name: 'Login',
        component: () => import('../views/LoginView.vue'),
    },
    {
        path: '/',
        component: HomeView,
        children: [
            {
                path: '',
                // name: 'Index',
                // component: () => import('../views/IndexView.vue'),
                redirect: {name: "Index"}
            },
            {
                path: 'index',
                name: 'Index',
                component: () => import('../views/IndexView.vue'),
            },
            {
                path: '/course',
                name: 'Course',
                component: () => import('../views/CourseView.vue')
            },
            {
                path: '/news',
                name: 'News',
                component: () => import('../views/NewsView.vue')
            },
            {
                path: '/pins',
                component: () => import('../views/PinsView.vue'),
                children: [
                    {
                        path: '',
                        //component: () => import('../views/NewView.vue'),
                        redirect: {name: "New"},
                    },
                    {
                        path: 'new',
                        name: 'New',
                        component: () => import('../views/NewView.vue'),
                    },
                    {
                        path: 'hot',
                        name: 'Hot',
                        component: () => import('../views/HotView.vue'),
                    },
                    {
                        path: 'following',
                        name: 'Following',
                        component: () => import('../views/FollowingView.vue'),
                    }
                ]
            },
        ]
    },
]

const router = createRouter({
    history: createWebHistory(),
    routes
})

export default router

5.导航守卫(全局)

未登录时,部分内容不允许访问,会跳转带登录页

import {createRouter, createWebHistory} from 'vue-router'
import HomeView from '../views/HomeView.vue'

const routes = [
    {
        path: '/login',
        name: 'Login',
        component: () => import('../views/LoginView.vue'),
    },
    {
        path: '/',
        component: HomeView,
        children: [
            {
                path: '',
                // name: 'Index',
                // component: () => import('../views/IndexView.vue'),
                redirect: {name: "Index"}
            },
            {
                path: 'index',
                name: 'Index',
                component: () => import('../views/IndexView.vue'),
            },
            {
                path: '/course',
                name: 'Course',
                component: () => import('../views/CourseView.vue')
            },
            {
                path: '/news',
                name: 'News',
                component: () => import('../views/NewsView.vue')
            },
            {
                path: '/pins',
                component: () => import('../views/PinsView.vue'),
                children: [
                    {
                        path: '',
                        //component: () => import('../views/NewView.vue'),
                        redirect: {name: "New"},
                    },
                    {
                        path: 'new',
                        name: 'New',
                        component: () => import('../views/NewView.vue'),
                    },
                    {
                        path: 'hot',
                        name: 'Hot',
                        component: () => import('../views/HotView.vue'),
                    },
                    {
                        path: 'following',
                        name: 'Following',
                        component: () => import('../views/FollowingView.vue'),
                    }
                ]
            },
        ]
    },
]

const router = createRouter({
    history: createWebHistory(),
    routes
})


router.beforeEach((to, from, next) => {
    // to,即将访问路由对象
    // from,当前正要离开路由
    // next() 继续向后执行,去to的页面
    // next(false) 不跳转,还在当前页面。
    // next("/xxx")  next({name:"xxx"})  next({pat:"/xxx"})
    let token = sessionStorage.getItem("isLogin");

    if (token) {
        // 已登录,可以向目标地址访问
        next();
        return
    }

    // 未登录,登录页面
    if (to.name === "Login") {
        next();
        return;
    }

    // 未登录,访问的其他地址
    next({name: "Login"});

})


export default router

4.vuex

4.1 安装

npm install vue-vuex --save
手动创建文件+配置

vue add vuex (推荐)

4.2 使用示例

登录后,将导航栏的登录替换成显示用户名

4.2.1 案例(vuex)

store/index.js
import {createStore} from 'vuex'

export default createStore({
    state: {
        username: "",
        token: ""
    },
    getters: {},
    mutations: {
        login(state, {username, token}) {
            state.username = username;
            state.token = token;
        }
    },
    actions: {},
    modules: {}
})

LoginView:
使用store,调用login方法
在这里插入图片描述

HomeView:
调用store.state.username获取用户名,将导航栏登录改为v-if使用

在这里插入图片描述

此时存在的问题:
登录后导航栏会变成用户名,但是刷新页面后又会消失

解决方法:使用vuex+存储

4.2.2 案例(vuex+存储)

这里使用localStorage存储,将用户信息存储到localStorage,调用state时先读取
在这里插入图片描述

4.2.3 案例(注销功能)

清空state及localStorage的值,跳转到登录页

在这里插入图片描述
在这里插入图片描述

4.2.4 动态购物车案例

动态改变state中数据需要使用computed计算属性
在这里插入图片描述

同时注意进行计算的变量的数据类型:
在这里插入图片描述

5.vue3-cookies

实现将数据在cookie中进行存取。

5.1 安装

npm install vue3-cookies --save

5.2 使用

导入
在这里插入图片描述

使用:

在这里插入图片描述
在这里插入图片描述

6.axios

6.1 安装

npm install axios --save
手动配置

vue add axios

6.2 使用示例

6.2.1 快速发送

在这里插入图片描述
在这里插入图片描述

6.2.2 拦截器

请求拦截器,响应拦截器

/* eslint-disable */

import axios from "axios";

// import {useRouter} from "vue-router";
// import {useStore} from "vuex";
// import {getToken} from "@/plugins/cookie";
//
// const router = useRouter();
// const store = useStore();
axios.defaults.baseURL = 'https://api.luffycity.com/api/';
// axios.defaults.headers.common['Authorization'] = getToken();
// axios.defaults.headers.post['Content-Type'] = 'application/json';


let config = {
    // baseURL: process.env.baseURL || process.env.apiUrl || ""
    // timeout: 60 * 1000, // Timeout
    // withCredentials: true, // Check cross-site Access-Control
};

const _axios = axios.create(config);

_axios.interceptors.request.use(
    function (config) {
        // Do something before request is sent
        // console.log("请求前执行");
        const token = getToken();
        if (token) {
            config.headers['token'] = token;
        }
        return config;
    }
);


// 浏览器上有Token,但是Token在后端已经失效
_axios.interceptors.response.use(
    function (response) {
        // Do something with response data
        // 请求成功 200成功(登录失效了){code:-1,msg:"登录失效"}   {code:0,msg:data}   {code:1000,msg:"认证失败"}
        if (response.data.code === 1000) {
            //认证失败,token过期,登录失败 -> 登录页面
            store.commit("logout");
            router.replace({name: "Login"});
            return Promise.reject();
        }

        return response;
    },
    function (error) {
        // Do something with response error
        // 请求失败自动执行此处的代码,返回的状态码:500(认证401if (error.response.status === 401) {
            store.commit("logout");
            router.replace({name: "Login"});
        }
        return Promise.reject(error);
    }
);


export default _axios;

7.后端API

7.1 跨域问题

前端调用的后端接口不属于同一个域(域名或端口不同),就会产生跨域问题
本质上想要处理跨域,添加一些响应头即可。

from django.shortcuts import render
from django.http import JsonResponse


def user_list(request):
    info = {"code": 0, 'data': "success"}
    response = JsonResponse(info)

    # 响应头
    print(request.method)

    # 任意网址
    response["Access-Control-Allow-Origin"] = "*"
    # 任意的请求方式
    response["Access-Control-Allow-Methods"] = "*"  # "PUT,DELETE,GET,POST"
    # 允许任意的请求头
    response["Access-Control-Allow-Headers"] = "*"

    return response
注意:测试时一定要移除csrf认证。
写在中间件的process_response中
from django.utils.deprecation import MiddlewareMixin


class CorsMiddleware(MiddlewareMixin):
    def process_response(self, request, response):
        # 任意网址
        response["Access-Control-Allow-Origin"] = "*"
        # 任意的请求方式
        response["Access-Control-Allow-Methods"] = "*"   # "PUT,DELETE,GET,POST"
        # 允许任意的请求头
        response["Access-Control-Allow-Headers"] = "*"
        return response

7.2 发送两个请求现象

跨域时发送的是:
简单请求:1个请求

复杂请求:2个请求

OPTIONS请求,预检

真正的请求

条件:
  ``1``、请求方式:HEAD、GET、POST
  ``2``、请求头信息:
    ``Accept
    ``Accept``-``Language
    ``Content``-``Language
    ``Last``-``Event``-``ID
    ``Content``-``Type` `对应的值是以下三个中的任意一个
                ``application``/``x``-``www``-``form``-``urlencoded
                ``multipart``/``form``-``data
                ``text``/``plain
注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值