前端对接后端api
项目环境
本次项目环境前端环境是
vue3
环境下的vite
+Element-plus
后端 则是DoteNet7.0
的编译环境。其中后端内容已经前面浪浪山管理系统开发---MVC架构设计文章中讲了。我们先来看看我们要实现的效果图:
我们将实现红框部分的内容,即将后端数据在前端表格中显示出来。
前端部分内容搭建
项目目录建立
首先我们在创建
vite
项目的时候会有一个默认的views
文件夹,这个文件夹包含各个网页的内容,然后因为本次教程我们要实现系统日志
内容,所以我们在views
文件夹下创建一个system
文件夹,在system
文件夹内我们创建一个log.vue
以来实现对应的日志显示内容。相关的目录结构如下图所示:
日志信息表格建立
我们接下来将建立下图部分的内容。
我们这里采用的是
Element-plus
的表格
组件,所以我们得前往Element-plus
官网找到表格
组件的代码。
我们这里选用的是基础表格控件,我们复制以上黄色框框的代码进入
log.vue
文件 ,注意这里的<template> </template>
不要复制进去,因为我们这里是本身log.vue
文件已经有了<template> </template>
,所添加的外部组件无需代入<template> </template>
。
这里解释一下图中的
prop属性
和label
属性 以及:data
-
label
这个label属性呢就是表格的每列的字段值,所以我们可以根据需要label改成我们想要的名词,例如:
<el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName"> <el-table-column prop="index" label="序号" width="60px" /> <el-table-column prop="stringDateTime" label="时间" /> <el-table-column prop="level" label="事件紧急等级" /> <el-table-column prop="logger" label="日志发生地址"/> <el-table-column prop="message" label="日志消息"/> <el-table-column prop="exception" label="异常消息"/>
这样我们对应的表格就会显示:
-
:data
这部分进行数据绑定,上面代码的
tableData
是我们自定义的一个数组,用于存储我们从后端API返回的数据。这样el-table
组件绑定返回的数据,以便后续能够处理数据。 -
prop
上面我们提到
:data
是绑定返回的数据给el-table
组件,这个prop
就是每个返回数据的名称,以这个名称来渲染出返回的具体数据。接下来我们看后端API返回的结果来加深理解。这个
prop
参数内容就是黄色箭头对应的键的名称。
向后端发起请求
我们将使用
http
库axios
来进行发起网络请求的操作。首先我们要在对应项目文件下的终端输入
npm install axios
以安装axios
库
那我们的操作步骤就两步:
1.发起请求
2.存储返回的数据
先说
存储返回数据
部分吧,这里我们是通过一个数组来存储返回的数据的,所以我们定义一个空的数组常量:
import {ref,onMounted} from "vue";
const tableData = ref([]);
接下来我们讲解发起
axios
请求的内容:
import axios from "axios"; //导入axios库
const currentPage = ref(0);//存储当前是哪一页
const pageSize = ref(10);//存储页面的大小
const recordCount = ref();//存储总的数据数量
const searchQuery = ref({
currentPage: 1,
pageSize: 5,
recordCount: 1,
}); //初始化数据
const logQuery = async()=>{
let url = `/SystemLog/${searchQuery.value.currentPage}/${searchQuery.value.pageSize}`;
var service = axios.create({ baseURL: "https://localhost:7260/" });
let response = await service.get(url);//返回获取的数据
let result = response.data; //存储返回的数据到前端位置
tableData.value = result.dataList;//将返回的数据的列表的数据内容给tableData
searchQuery.value.recordCount = result.recordCount;//存储总的数据数量
}
}
接下来我将逐条解析以上代码:
const currentPage = ref(0);//存储当前是哪一页
const pageSize = ref(10);//存储页面的大小
const recordCount = ref();//存储总的数据数量
const searchQuery = ref({
currentPage: 1,
pageSize: 5,
recordCount: 1,
}); //初始化数据
这部分内容则是定义存储我们需要的数据变量,以便后续与相关的组件进行交互,比如我们的
currentPage
、pageSize
用于我们发起http
请求的参数,因为我们后端API在浪浪山管理系统开发---MVC架构设计文章中已经讲过我们用的是pageindex(当前页码) pageSize(当前页数据数量)** 参数去查询的数据库以返回数据。而这个recordCount
则存储返回的数据总数。
const logQuery = async()=>{
}
这里我们定义了一个名叫
logQuery
的方法,async
代表方法是异步的方法,因为们的axios
方法调用的时候是异步的,所以我们整个方法也得定义成异步方法。这就是为什么这里logQuery
方法我们要加async
异步标志的原因。
const logQuery = async()=>{
let url =`/SystemLog/${searchQuery.value.currentPage}/${searchQuery.value.pageSize}`;
}
这里我们定义了url变量,以存储我们要发起的url路径。这里我们用了一个反引号符号:``,这样我们就可以根据需要用
$
在字符串中插入我们之前定义的字符串变量,这个有点类似于C#里面的字符串插值的写法。这里的路径不是乱填的,我们得根据后端api的路径去添加:
我们在
url
填入黄色框框内的路径,这里因为我们的pageindex
和pageSize
参数是不固定的,它随时可能根据用户所需而改变,所以这里我们用了用$
在字符串中插入我们之前定义的字符串变量以达到动态变化路径的需求。
const logQuery = async()=>{
var service = axios.create({ baseURL: "https://localhost:7260/" });
let response = await service.get(url);//返回获取的数据
let result = response.data; //存储返回的数据到前端位置
}
这里就是我们发起请求的部分了,我们利用
var service = axios.create({ baseURL: "https://localhost:7260/" });
来创建一个请求,这里的baseURL
参数也得去看后端API的访问路径决定:
发现没,黄色框框就是我们的完整的请求URL,所以这里我们的
baseURL
填"https://localhost:7260/"
,这样 当我们在调用:let response = await service.get(url);//返回获取的数据
的是时候将会和我们上面定义的url=/SystemLog/${searchQuery.value.currentPage}/${searchQuery.value.pageSize};所拼接,比如我们这里的searchQuery.value.currentPage=1
,searchQuery.value.pageSize=2
的话,此时service.get(url)
所访问的完整路径拼接起来就是上图示例的:https://localhost:7260/SystemLog/1/2
,最后返回数据给response
.
这里我们通过监控
response
变量发现,我们所需要的页码数据存在了其data
变量中,所以我们最后使用:let result = response.data;
以方便我们用result变量去调用我们所需要的页码数据,
跨域问题
经过以上的操作之后就成功实现了前端发起请求,后端相应请求并返回数据的操作,但是真的没有问题吗?NO!这里会出现一个跨域的问题,它会阻止你得到后端返回的数据给前端,上面我讲解的时候返回了数据是我为了便于讲解提前解决了这个问题,接下来我将简单还原这个问题:
发现没,浏览器控制报错:
Access to XMLHttpRequest at 'https://localhost:7260/SystemLog/1/5' from origin 'http://localhost:4000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
。这个报错就是意味着目前程序存在跨域问题。接下来我们先来了解一下跨域问题的起源吧~
跨域问题的起源
跨域问题的根本限制是同源策略。
-
同源策略
同源策略 (Same-Origin Policy) 最早由 Netscape 公司提出, 所谓同源就是要求, 域名, 协议, 端口相同. 非同源的脚本不能访问或者操作其他域的页面对象(如DOM等). 作为著名的安全策略, 虽然它只是一个规范, 并不强制要求, 但现在所有支持 javaScript 的浏览器都会使用这个策略. 以至于该策略成为浏览器最核心最基本的安全功能, 如果缺少了同源策略, web的安全将无从谈起.并且,浏览器不是阻止请求的发送,而是对请求的拦截。
简单来说就是我们满足以下三点就可以解决这个同源策略的限制。
-
同域
即host相同, 顶级域名, 一级域名, 二级域名, 三级域名等必须相同, 且域名不能与 ip 对应;
-
同协议
要求,http与https协议必须保持一致;
-
同端口
要求, 端口号必须相同.
能够解决跨域问题的方法有很多,但是本章节我们主讲前后端分类项目的对接,所以我这里将不详细讲解这个部分。后续我会单开一章节来专门讲解如何解决跨域问题。
解决跨域问题
Access to XMLHttpRequest at 'https://localhost:7260/SystemLog/1/5' from origin 'http://localhost:4000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我们来翻译一下浏览器控制台关于跨域问题的报错代码,其大致意思是说 我从前端接受后端相应的请求被同源策略给阻止了,阻止的原因是我们响应数据的表头没有Access-Control-Allow-Origin
。这里我们抓包看看相应情况:
这里我们就可以很清晰的知道了,请求后端的状态代码是:200,这说明我们的请求是正常发送了,所以跨域问题的罪魁祸首是浏览器阻止了后端发送回的数据给前端。接下来我们看相应标头,里面的确没有报错提示的
Access-Control-Allow-Origin
标记。这就给我们提供了一个解决方案,我们只要在后端返回的时候给响应标头加上这个标记不就能解决了?是的,这就是我们的解决思路。我们去打开后端api,找到对应的api控制器文件:
打开
SystemLogController.cs
文件,这个文件我们在前面章节:浪浪山管理系统开发---依赖注入部分创建的,这部分内容去看看前面几章。我们打开
SystemLogController.cs
,我们其public IActionResult SystemLogPage(int pageindex,int pageSize)
类中写入:HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
。这样我们相应标头就有Access-Control-Allow-Origin
了。现在我们刷新一下前端页面、重启后端api看看相应情况:
可以看到数据部分显示出来了,同时响应标头也有了
`Access-Control-Allow-Origin
标记了,标记的:*****意思是允许所有域名访问。这样我们的跨域问题就完美解决了。以上内容就是我们将前后端分离架构的项目对接起来的讲解了~~~
停留在世界边缘,与之惜别