DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • html

  • css

  • javascript

  • jquery

  • UI库

  • 第一次学vue

    • 基础语法(1)
    • 基础语法(2)
    • Vue生命期钩子
    • 基础语法(3)
    • Vue-cli
    • 插件的使用(1)
    • 插件的使用(2)
      • vuex
        • 综合示例
        • Q&A
        • 第一个问题
        • 第二个问题
        • 第三个问题
      • vue3-cookies
      • axios
        • 后端代码
        • 基于vue2
        • 基于vue3
        • 拦截器
        • 方式一
        • 方式二
        • 跨域问题
    • 总结
  • 第二次学vue

  • 前端
  • 第一次学vue
DC
2023-11-25
目录

插件的使用(2)

# vuex

vuex 状态管理器 让多个组件共享数据, 开发中通常用来保持当前的登陆状态

★ 一定要注意一点, 一旦刷新页面, vuex中的数据就没有了!!
vuex存储的数据只是在页面中, 相当于全局变量, 页面刷新时vuex里的数据会重新初始化, 导致数据丢失!!
vuex里的数据是保存在运行内存中的, 当页面刷新时, 页面会重新加载vue实例, vuex里面的数据会被重新赋值!!

先进行安装, 跟router的安装一样, 有两种方式.
方式一: npm install vue-vuex --save 并需手动创建文件和进行配置
方式二: vue add vuex (会自动创建文件并进行配置) 选它!!

# 综合示例

我们以一个登陆的综合案例来完成以下几个需求:

此示例中的登陆跳转含顶部!
1> 未登录,导航栏右侧显示登录按钮; 登陆成功后,登陆按钮处显示用户名
   技术点: v-if v-else vuex 计算属性 (之所以使用计算属性,涉及到单页面应用,组件间切换时,生命周期的开始结束)
2> 解决刷新页面后,登陆状态就消失了
   技术点: 浏览器localStorage持久化保存登陆状态
3> 登陆成功后,当前登陆的用户名左边显示 有多少条未读私信. “需保证刷新后,不会归0”
   登陆成功后,点击导航栏上的资讯按钮,进入该页面后,点击“发送一条私信按钮” 用户名 左边的 未读私信的条数会加1.
   点击 “全读” 按钮,私信条数清0.
   技术点: 计算属性、localStorage
4> 未登录,首页和登录页面可以访问,资讯和直播页面需要登录后才能访问
   技术点: 导航守卫
5> 添加退出登录按钮,回归未登录的状态
1
2
3
4
5
6
7
8
9
10
11
12

ld12

关键代码逻辑截图如下:

image-20231017215354353

# Q&A

蛮重要的, 请细品.

# 第一个问题

代入上方的综合示例中,App.vue是根组件,关于name常量,若我们写成 const name = store.state.username
你会看到这样的现象,登陆成功后,依旧显示的是登陆按钮,不会显示当前登陆用户.
但如果我们此时刷新下页面.登陆用户就显示出来啦!

如何解释?

第一点:
   在router的配置文件中写了两个路由, 其name分别为One、Two, 它们都会渲染到App.vue的<router-view/>处 (单页面应用)!! 
   One组件先渲染到此处,开始它的生命周期,当<router-view/>处切换到渲染Two组件时,One组件的生命周期结束.. 
   当再次切换One组件时,One组件会开始新一轮的生命周期.
   
第二点:
   ♀ 只要不刷新,不管访问啥地址,一直访问的都是App.vue, 就像前面vue-route所说, "同一组件间路由切换, 是复用"! 
   所以登陆成功,App.vue还是那个App.vue,name的赋值语句不会重新执行..
   举个例子.
     192.168.106:8080/news --> 192.168.106:8080/live 
     App.vue还是那个App.vue,只是在`<router-view/>`news组件切换到了live组件 live组件开始新的生命周期,news结束
   ♀ 当刷新的时候,App.vue的生命周期重新加载!name的赋值语句重新执行.
   进一步说
     当我们刷新,重新访问/加载 192.168.106:8080/news
     App.vue里的代码会重新执行.News组件会重新渲染到App.vue的<router-view/>处!!

借此,我们还可以解释,App.vue中的name和letterNums为啥要用计算属性.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

做了个小实验对第一点进行验证, 在App live 和 News这三个组件中添加类似于这样的代码:

<script setup>
import {onUnmounted} from 'vue';
console.log("开始Live的生命周期");
onUnmounted(()=>{
  console.log("Live的生命周期结束")
})
</script>
1
2
3
4
5
6
7

smzq11

验证结果: (ps,页面刷新,浏览器控制台的打印会清空)
切换到哪个组件, 哪个组件就会开始新一轮的生命周期 但上一个组件的销毁在当前切换组件生命周期开始的后面.

# 第二个问题

在vue-router的笔记中, 我们阐述了两种登陆,含顶部和不含顶部的.
如果是不含顶部的登陆代码, 我们发现name是不需要计算属性的!! letterNums需要加计算属性.

这又是为何?

其实第二个问题的本质还是第一个问题.
分析缘由,从路由的结构入手,以下是 不含顶部 的路由结构. 分为了两个一级组件,MenuView和LoginView,MenuView下有嵌套!
但要注意,'/'路由加载的是MenuView,但未给他设置name属性,当加载时,会一并加载嵌套的HomeView组件.
于是,我猜想,从LoginView组件登陆成功后,跳转Home路由. MenuView、HomeView都会重新开始生命周期.
这就导致MenuView里的name赋值语句会重新运行,所以name就不需要计算属性.
而letterNums,是News组件干的,只涉及二级组件在MenuView的<router-view/>处的切换,MenuView组件不会重新渲染
所以,letterNums需要计算属性!!


const routes = [
    {
        path: '/',
        component: MenuView,
        children: [
            {
                path: '',
                name: "Index",
                component: HomeView,
            },
            {
                path: '/home',
                name: 'Home',
                redirect: {name: 'Index'},
            },
            {
                path: '/news',
                name: 'News',
                component: () => import('../views/NewsView.vue')
            },
            {
                path: '/live',
                name: 'Live',
                component: () => import('../views/LiveView.vue')
            },
        ],
    },
    {
        path: '/login',
        name: 'Login',
        component: () => import('../views/LoginView.vue')
    },
]
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

做了个小实验进行佐证!! 验证过程动图如下.

mydbl

# 第三个问题

是否可以用 localstorage代替Vuex.

对于不变的数据确实可以,但是当两个组件共用一个数据源(对象或数组)时.如果其中的一个组件改变了该数据源,希望另一个组件响应该变化时
Vuex才是首选,loaclstorage是无法做到的.

而且在vuex中,对于数据的修改可以先做一系列的验证! 有解藕的功效!!

vuex中的数据在内存里,loaclstorage的数据在本地文件里,从内存中读取的速度更快.
1
2
3
4
5
6

# vue3-cookies

官方文档: https://www.npmjs.com/package/vue3-cookies

需要通过npm安装后, 手动进行文件的配置.

// --save、-S参数意思是把模块的版本信息保存到dependencies(生产环境依赖)中,即package.json文件的dependencies字段中
// 从npm 5.0.0 开始,npm install 默认就使用 --save 选项,不需要再加这个选项
npm install vue3-cookies --save

// 在main.js中配置
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import VueCookies from 'vue3-cookies'

createApp(App).use(store).use(router).use(VueCookies).mount('#app')


// 使用cookies
import {useCookies} from 'vue3-cookies'
const {cookies} = useCookies();
cookies.set("ts", "123123", "10s")  // !!可以设置过期时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

举个例子, 我们可以将上面vuex的综合示例中使用localStorage的地方全换成使用cookies!! 关键代码如下:

/* 在src下新建plugins文件夹.在里面创建index.js文件!*/

import {useCookies} from "vue3-cookies";
const {cookies} = useCookies();  // es6里的解构赋值,因为useCookies()是一个对象.

export const getToken = () => {
    return cookies.get("token") || "";
}

export const getUserName = () => {
    return cookies.get("username") || "";
}

export const setUserToken = (user, token) => {
    cookies.set('username', user, "30s");
    cookies.set('token', token, "30s");
}

export const clearUserToken = () => {
    cookies.remove("username");
    cookies.remove("token");
}

/* 将使用localStorage的地方全换成使用cookies */
import {createStore} from 'vuex'
import {getToken, getUserName,setUserToken,clearUserToken} from "@/plugins/cookie";

export default createStore({
    state: {
        // username: localStorage.getItem('username'),
        // token: localStorage.getItem('token'),
        username: getUserName(),
        token: getToken(),
        car: localStorage.getItem('carNum') || 0,
    },
    getters: {},
    mutations: {
        login(state, {username, token}) {
            state.username = username;
            state.token = token;
            // localStorage.setItem('username', username);
            // localStorage.setItem('token', token);
            setUserToken(username,token);
        },
        logout(state) {
            state.username = "";
            state.token = "";

            // localStorage.removeItem('username');
            // localStorage.removeItem('token');
            clearUserToken();
        },
        addCar(state) {
            state.car = parseInt(state.car) + 1;
            localStorage.setItem('carNum', state.car);
        }
    },
    actions: {},
    modules: {}
})
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

# axios

重点关注基于vue3的使用!

proxy.$axios.get(`/tran/`, {params: search_params}).then((res) => {}).catch(error => {})
proxy.$axios.post(`/tran/`, {k1:123, k2:456}, {params: search_params}).then((res) => {}).catch(error => {})
1
2

# 后端代码

下面的示例, 都使用这个后端代码.

pip install django-cors-headers==3.8.0 + 注册'corsheaders' + 添加中间件 + 在setting文件里配置

先复习一点知识
GET or POST: url中的参数 - query_params; 请求头中的 - META、headers都行,注意会加HTTP_.
POST: 请求体中的数据 - data (一般在使用认证类时,前端需要在http请求头中添加token信息)

因为浏览器的同源策略,前后端交互时会出现跨域问题.   
解决跨域有很多种办法:  
1> 后端使用cors技术.   
2> 使用nginx做转发.    
3> 前端做代理: 注意, 它只适合测试阶段使用,项目上线后是没有的.
  
当前浏览器访问的地址 与 向后端API发送网络请求的地址 同源策略!!
请求能发过去,后端api能接收到并处理数据,能返回. 但到浏览器那被拦截了.
1
2
3
4
5
6
7
8

url.py

from django.urls import path
from api import views

urlpatterns = [
    path('user/', views.UserView.as_view()),
]
1
2
3
4
5
6

views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class UserView(APIView):
    # GET请求解决跨域: 'Access-Control-Allow-Origin': '*'
    def get(self, request):
        return Response(
            {'name': '路飞', 'age': '19'},
            headers={'Access-Control-Allow-Origin': '*'}
        )

    # POST请求解决跨域: 借助django-cors-headers (它一并将GET请求的跨域解决了)
    def post(self, request):
        print(request.META.get("HTTP_TOKEN"))
        username = request.data.get('username')
        password = request.data.get('password')
        if username == "lqz" and password == "123":
            return Response({'code': 100, 'msg': "登陆成功!"})
        else:
            return Response({'code': 101, 'msg': "用户名或密码错误!"})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 基于vue2

该示例是基于vue2实现的,而且没有使用脚手架. 只是axios的简单使用. (无需过多关注,后续开发都使用的vue3)

wa

前端利用axios向后端发送了get和post请求!!post请求在请求体中添加表单数据,在请求头中添加token信息.

安装 npm install -S axios - 导入 import axios from "axios"; - 使用它发送get/post请求,获取api数据渲染到页面上!
(注意代码中打上五角星的地方!!)

App.vue

<template>
  <div id="father">
    <span style="color: rgb(128,128,128)">需求: 点击按钮发送get请求获取api数据!</span> <br>
    <p>
      姓名: {{ name ? name : "暂无" }} | 年龄: {{ age ? age : "暂无" }}
      <button @click="handleClick">获取数据!</button>
    </p>
    <p>后端返回数据: {{ get_data }}</p>
    <hr>
    <span style="color: rgb(128,128,128);">需求: 前端通过表单向后端发送post请求,请求体和请求头中都携带数据!</span>
    <span style="color: rgb(128,128,128);">登陆失败弹出提示框,登陆成功跳转百度页面.</span>
    <p>用户名: <input type="text" v-model="username"></p>
    <p>密码:&nbsp;&nbsp;&nbsp; <input type="password" v-model="password"></p>
    <button @click="handleSubmit">登陆</button>
    <p>后端返回数据: {{ post_data }}</p>
  </div>
</template>

<style>
#father {
  width: 500px;
  margin: auto;
  padding: 10px;
  border: 1px solid bisque;
}
</style>

<script>
import axios from "axios";  // 就像py中安装第三方模块,直接导入模块名就可以使用

export default {
  name: 'App',
  data() {
    return {
      name: "", 
      age: "",
      username: "",
      password: "",
      get_data: "",
      post_data: "",
    }
  },
  methods: {
    // ★ get请求一般不会通过点击获取后端api数据,而是在生命周期create函数里就发送axios请求了!
    handleClick() {
      axios.get("http://127.0.0.1:8000/user/").then(res => {
        // 注意: 真正的数据在res.data里
        this.get_data = res.data
        this.name = res.data.name
        this.age = res.data.age
      })
    },
    // ★ Post请求,数据放到http的请求体里,token信息放到http的请求头里!
    handleSubmit() {
      // axios.post(url,请求体,请求头).then()
      axios.post("http://127.0.0.1:8000/user/", {
            username: this.username,
            password: this.password,
          }, {
            headers: {"token": "abcdefgh"}
          },
      ).then(res => {
        this.post_data = res.data
        if (res.data.code === 100) {
          setTimeout(() => location.href = "https://www.baidu.com/", 2000)
        } else {
          alert("登陆失败!")
        }
      })
    },
  },
}
</script>
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

# 基于vue3

安装: npm install axios --save or vue add axios
选前者, 因为若选后者, 也需在其自动生成的配置文件上进行修改. 还不如一开始就自己手动配置!

★★★ 有两种方式使用axios!!
方式一: 创建axios对象,页面中导入并实现.
方式二: 创建axios对象,设置vue对象中,其他页面获取vue对象.

简单来说
运行命令 `npm install axios --save` 安装好后, 在src目录下新建 文件夹plugins, 在该目录下 创建文件 axios.js

▲方式一:
  src/plugins/axios.js的最后
     export default _axios;
  LoginView.vue里
     import _axios from "@/plugins/axios";
     _axios.post().then(res => {console.log(res.data)})
   
▲方式二:
  思想: 通过将属性或方法添加到globalProperties中,可以使它们在应用的任何组件中都可以访问到,而不需要在每个组件中单独引入或定义!
  src/plugins/axios.js的最后
     export function installAxios(Vue) {
         Vue.config.globalProperties.$axios = _axios;  // 相当于在vue实例里加入了$axios这个成员!
     }
  src/main.js里
     import {installAxios} from "@/plugins/axios";
     const app = createApp(App)
     installAxios(app)
     app.use(store).use(router).use(ElementPlus).mount('#app')
  LoginView.vue里
     import {getCurrentInstance, ref} from 'vue'
     const {proxy} = getCurrentInstance()
     proxy.$axios.post().then(res => {console.log(res.data)})   
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
# 拦截器

里面比较重要的知识点是 拦截器! 它是基于promise实现的,不用深究, 知道它如何用就行!!
针对拦截器先来一点科普.

可查看该博客辅助理解: https://juejin.cn/post/7100470316857557006

axios的拦截器是一种机制,它允许你在发送请求或接收响应之前对它们进行拦截和处理.
因此,axios提供了两种类型的拦截器:请求拦截器和响应拦截器.
1> 请求拦截器
   在所有的请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装;
2> 响应拦截器
   在所有的请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等.

另外,通过 `axios.interceptors.request.use` 和 `axios.interceptors.response.use` 方法来添加拦截器.
这两个方法都接受两个参数:一个处理成功的回调函数和一个处理失败的回调函数.
具体来说,请求失败和响应失败是两种不同的情况.
- 请求失败是指在发送请求的过程中出现了错误,例如网络连接失败、请求超时等.
  这种情况下,请求可能根本没有发送到服务器,因此无法收到任何响应.
  在 axios 中,请求失败会触发 `axios.interceptors.request` 中的第二个回调函数.
- 响应失败是指在请求已经发送并收到了服务器的响应,但是服务器返回的<"状态码">表示请求失败.
  例如: 服务器返回的状态码为 404 表示请求的资源不存在; 返回的状态码为 500 表示服务器内部错误等.
       我们熟知的drf认证失败,返回401.
  在 axios 中, 响应失败会触发 `axios.interceptors.response` 中的第二个回调函数.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

★ 特别注意!! 响应成功不代表真正成功!!
<状态码是200>只能说拿到了后端API返回的数据, 真正的成功要看返回数据中的<"返回码">,通常是code字段值!!

# 方式一

代码是嘛样的, 看下方.

运行命令 npm install axios --save 安装好后, 在src目录下新建 文件夹plugins, 在该目录下 创建文件 axios.js

src/plugins/axios.js

import axios from "axios";

// import {useRouter} from "vue-router";
// const router = useRouter();

/*
1> 基于axios发送请求时,请求url的前缀
   axios.defaults.baseURL = 'http://127.0.0.1:8000/api/';
2> 发送请求时,携带请求头 common表示所有请求发送时,都会携带该请求头
   import {getToken} from "@/plugins/cookie";
   axios.defaults.headers.common['Authorization'] = getToken();
3> 发送请求时,携带请求头 post表示只要发送post请求时,才会携带该请求头
   axios.defaults.headers.post['Content-Type'] = 'application/json';
★★注意!! 添加请求头未添加上的话要想到预检!后端没在CORS_ALLOW_HEADERS中配置里添加允许该请求头.
*/
axios.defaults.baseURL = 'http://127.0.0.1:8000/';

/* 通过axios.create()创建一个axios对象时,可以添加一些参数/做一些配置 */
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) {
        console.log(config)
        // 这里是有token,才在请求头中携带token ;
        // 而在上面axios.defaults.headers.common['Authorization'] = "xxx";是有没有token都会有这个请求头
        const token = "xxxxxx"
        if (token) {
            config.headers['token'] = token
        }
        return config;
    }
);

/* 响应拦截器 */
// ★★★ 浏览器上有Token,但是Token在后端已经失效 -- 必须这样解决!! (失不失效后端说的算,而不是看前端)
_axios.interceptors.response.use(
    // 前后端可以约定,返回码101表示用户名或密码错误,登陆失败;返回码102表示token过期,登陆失败.
    function (response) {
        if (response.data.code === 102) {
            // 登陆失败,返回登陆界面,通常还需清除本地token信息..
            return Promise.reject();  // 执行了这句,就拦腰斩断,不往后走了.
        }
        // 该返回的数据会被axios.then(res)的参数res接收
        return response;
    },
    function (error) {
        // if (error.response.status === 401) {
        //
        // }
        // 该返回的数据会被axios.catch(err)中的error接收
        return Promise.reject(error);
    }
);


export default _axios;
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

LoginView.vue

<template>
  <div class="about">
    <h1>This is an Login page</h1>
    <div>
      姓名: <input type="text" v-model="username"> <br>
      密码: <input type="text" v-model="password"> <br>
      <input type="button" value="登陆" @click="doLogin" style="margin-left: 148px">
    </div>
  </div>
</template>

<script setup>
import {ref} from "vue";
import _axios from "@/plugins/axios";

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

function doLogin() {
  _axios.post("user/", {
    username: username.value,
    password: password.value,
  }).then(res => {
    console.log(res.data)
  }).catch(error => {
    console.log(error)
  })
}
</script>
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
# 方式二

代码是嘛样的, 看下方.

运行命令 npm install axios --save 安装好后, 在src目录下新建 文件夹plugins, 在该目录下 创建文件 axios.js

src/plugins/axios.js

import axios from "axios";

axios.defaults.baseURL = 'http://127.0.0.1:8000/';

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
        return config;
    },
    function (error) {
        // Do something with request error
        return Promise.reject(error);
    }
);

_axios.interceptors.response.use(
    function (response) {
        // Do something with response data
        return response;
    },
    function (error) {
        // Do something with response error
        return Promise.reject(error);
    }
);


// export default _axios;  // 方式一
// 方式二 方式二和方式一不同的地方在这里!!
export function installAxios(Vue) {
    Vue.config.globalProperties.$axios = _axios;
}
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

src/main.js

import './plugins/axios'
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

import {installAxios} from "@/plugins/axios";

const app = createApp(App)
installAxios(app)
app.use(store).use(router).use(ElementPlus).mount('#app')
1
2
3
4
5
6
7
8
9
10
11
12
13

LoginView.vue

<template>
  <div class="about">
    <h1>This is an Login page</h1>
    <div>
      姓名: <input type="text" v-model="username"> <br>
      密码: <input type="text" v-model="password"> <br>
      <input type="button" value="登陆" @click="doLogin" style="margin-left: 148px">
    </div>
  </div>
</template>

<script setup>
import {getCurrentInstance, ref} from 'vue'
const {proxy} = getCurrentInstance()

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

function doLogin() {
  proxy.$axios.post("user/", {
    username: username.value,
    password: password.value,
  }).then(res => {
    console.log(res.data)
  }).catch(error => {
    console.log(error)
  })
}
</script>
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

# 跨域问题

CORS 解决的本质就是在返回数据时候加一些响应头即可解决!!

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
  
# Ps:测试时记得移除csrf认证中间件.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

或者写在自定义中间件里

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
1
2
3
4
5
6
7
8
9

Ps: 若前后端分离的模式, 非要解决跨域, 有个奇淫技巧. 几乎不会这么做.

[需要跨域]
前 https://www.luffycity.com/free-course
后 https://api.luffycity.com/api/v1/course/
  
[不需要跨域]
前 https://www.luffycity.com/free-course
后 https://www.luffycity.com/api/v1/course/
1
2
3
4
5
6
7

插件的使用(1)
总结

← 插件的使用(1) 总结→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式