【Vue】阶段练习
需求
# 基础:
1. 基于上次汽车管理系统的汽车接口,结合前端Vue框架:
- 实现登陆功能
- 显示所有汽车功能
- 新增汽车功能
# 进阶
2. 把所有接口都对应上前端vue
参考汽车之家
首页
1. 导航条 ---> 登录
2. 筛选框
3. 新闻广告区域
登录功能
展示所有汽车页面
项目
登录页面
# 1.如何使用axios发送post请求?
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
更多内容参考axios官网文档:https://www.axios-http.cn/docs/instance
跨域请求
一 同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现
请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同.
比如:我在本地上的域名是127.0.0.1:8000,请求另外一个域名:127.0.0.1:8001一段数据
浏览器上就会报错,个就是同源策略的保护,如果浏览器对javascript没有同源策略的保护,那么一些重要的机密网站将会很危险
已拦截跨源请求:同源策略禁止读取位于 http://127.0.0.1:8001/SendAjax/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。
但是注意,项目2中的访问已经发生了,说明是浏览器对非同源请求返回的结果做了拦截
二 CORS(跨域资源共享)简介
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
三 CORS基本流程
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段。
浏览器发出CORS非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
四 CORS两种请求详解
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。
浏览器对这两种请求的处理,是不一样的。
* 简单请求和非简单请求的区别?
简单请求:一次请求
非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
* 关于“预检”
- 请求方式:OPTIONS
- “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
- 如何“预检”
=> 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
Access-Control-Request-Method
=> 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
Access-Control-Request-Headers
支持跨域,简单请求
服务器设置响应头:Access-Control-Allow-Origin = ‘域名’ 或 ‘*’
支持跨域,复杂请求
由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。
- “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
- “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
五 Django项目中支持CORS
在返回的结果中加入允许信息(简单请求)
def test(request):
import json
obj=HttpResponse(json.dumps({'name':'lqz'}))
# obj['Access-Control-Allow-Origin']='*'
obj['Access-Control-Allow-Origin']='http://127.0.0.1:8004'
return obj
放到中间件处理复杂和简单请求:
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
def process_response(self,request,response):
if request.method=="OPTIONS":
#可以加*
response["Access-Control-Allow-Headers"]="Content-Type"
response["Access-Control-Allow-Origin"] = "http://localhost:8080"
return response
六 django 使用django-cors-headers 解决跨域问题
1、使用pip安装
pip install django-cors-headers
2、添加到setting的app中
INSTALLED_APPS = (
...
'corsheaders',
...
)
3、添加中间件
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
...
]
4、setting下面添加下面的配置
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
'Pragma',
'token'
)
代码
# 代码
```python
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
<script src="../js/axios.js"></script>
<link rel="stylesheet" href="../js/bootstrap.css">
</head>
<body>
<div id="app">
<component ref="mychild" @my-event="handleEvent" :is="who"></component>
</div>
<script>
let login = {
template: `
<div class="container">
<div class="col-md-6 col-md-offset-3">
<h2 class="text-center">用户登录</h2>
<div class="form-group">
<label for="name">用户名</label>
<input type="text" id="name" class="form-control" v-model="username">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" id="password" class="form-control" v-model="password">
</div>
<input id="loginBtn" type="button" class="btn btn-success btn-block" value="登录" @click="loginRequest()">
</div>
</div>
`,
data() {
return {
username: null,
password: null,
token: null,
userdata: null,
code: null,
msg: null,
who: 'login',
}
},
methods: {
loginRequest() {
axios.post('http://127.0.0.1:8000/api/v1/login/', {
username: this.username,
password: this.password,
}).then((res) => {
this.userdata = res
this.code = res.data.code
this.msg = res.data.msg
alert(this.msg)
if (res.data.token) {
this.token = res.data.token
this.$emit('my-event', {toPage: 'carPage', token: this.token}) // 触发component里面的my-event事件
// 将token传递给vm根组件。
}
})
}
},
}
let carPage = {
template: `
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default" v-for="item in data">
<div class="panel-body">
<a href="">
<h4 class="media-heading">{{ item.name + item.price }}</h4>
</a>
<div class="media">
<div class="media-left">
<a href="#">
<img style="width: 100px;" class="media-object" :src="item" alt="...">
</a>
</div>
<div class="media-body">
{{ item.factory_detail }}
{{ item.distributor_list }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>`,
data() {
return {
data: null,
token: null,
}
},
methods: {
getData() {
const request = axios.create({
baseURL: 'http://127.0.0.1:8000/api/v1/',
timeout: 1000,
headers: {'token': this.token}
}); // 配置axios对象,在请求头中添加token。
request.get('car_model/',
).then((res) => {
this.data = res.data.results // 获取后端返回的数据 将数据赋值给局部组件的this.data属性,在template使用this.data属性
})
},
},
watch: {
token() {
this.getData() // 用监听属性监听token的变化 当接收到父组件传来的token之后进行页面刷新
}
}
}
let vm = new Vue({
el: '#app',
data: {
token: null,
who: 'login',
},
methods: {
handleEvent(data) {
this.token = data.token
this.who = data.toPage
}
},
components: {
login,
carPage,
},
updated() {
if (this.token) {
this.$refs.mychild.token = this.token
// 当vm根组件里的this.token变化之后,将子组件carPage中的token属性进行修改。
}
}
})
</script>
</body>
</html>
```