来源:『轻笑Chuckle』

前言

  前后端交互本来是一个简单明了的概念,发请求与响应以及所用到的技术,但如百度等搜索结果大部分都抛出一堆菜鸟如我看不懂的概念与操作,上来就是用vue,或者新建一个MVC项目,实在不友好。
  本文旨在建立一个初步的、以前端为视角的前后端交互概念。


为什么要前后端交互

  以前的网页,用户在浏览器输入链接访问后,服务器一顿操作,渲染出页面扔给浏览器显示。而当页面内某段话,某个数字需要变,服务器又得重新渲染整个网页。
  这很麻烦,像PHPJSP,代码写在HTML中,也就是前后端不分离的表现。下面就是一个JSP的表格。

1
2
3
4
5
6
7
8
9
10
11
<tbody class="book-body">
<c:forEach items="${bookList}" var="book">
<tr class="book-tr">
<td>${book.bId}</td>
<td>${book.bName}</td>
<td>${book.auName}</td>
<td>${book.bType}</td>
<td>${book.bPress}</td>
</tr>
</c:forEach>
</tbody>

表单

  在这个前后端不分离的时代,所谓前端实现单纯的登录操作JS都不用写。弄个表单,点击表单内type="submit"的按钮,就能对action="doLogin"发起登录的get/post请求,然后再由服务器去处理,登录失败就渲染${errorMsg}

1
2
3
4
5
6
7
8
<form action="doLogin" method="get">
<p>用户名</p>
<input name="userName" type="text" placeholder="输入用户名/邮箱" />
<p>密码</p>
<input name="password" type="password" placeholder="输入密码" />
<button type="submit" class="btn1">登录</button>
<span>${errorMsg}</span>
</form>

 有时候需要触发事件而提交表单,比如删除操作,可以使用JQ伪造表单提交

1
2
3
4
5
6
7
8
btn.bind("click", function () {
var id = btn2.parent().parent().children("td").get(0).innerHTML;
var form = $("<form method='get'></form>");
form.attr({ "action": "/myBatisDemo/deleteBooksById" });
form.append($("<input type='hidden'>").attr("name", "bId").val(id));
$("body").append($(form));
form.submit();
});

  面对越来越复杂的网页页面,以及无刷更新内容提升体验的需求,后端提供数据前端去使用成了主流,这也大大减轻了服务器的压力,随着Ajax的出现,JS可以使用json来与服务器进行数据交互,真正的前后端分离出现了。


前端如何与后端交互

  和以前一样,后端会提供一个接口,就像是表单属性action="/myBatisDemo/deleteBooksById"里的一样。JS本身没有网络通信能力,但使用浏览器提供的对象和方法,遵循一定的规范协议(http),就可以通过这些接口与后端交互,也就是发请求和处理响应。
  后端响应后,拿到后端返回的内容(JSON),我们可以判断密码是否正确,或者通过DOM操作改变网页内容等等。


Ajax

  Ajax是最早出现的向后端发送请求的技术,其核心是浏览器提供的XMLHttpRequest(xhr)对象。我们可以直接原生地使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//既然xhr是个对象,当然要先new再使用里面的方法
let xhr = new XMLHttpRequest();
//定义我们的请求,与一个url建立连接,true代表异步请求
xhr.open('GET', '/url', true);
//readyStated,它一共有五个值,当等于4时代表请求已完成
//readyStated的变化会触发onreadystatechange事件
xhr.onreadystatechange = function(){
//当readyState为4以及http状态码为200代表请求成功,响应已就绪
if(this.readyState === 4 && this.status==200){
//对DOM的操作,比如替换个P标签的内容
console.log(this.responseText);//打印响应返回的文本
}
}
//把请求发送一下
//因为没有请求体的所以为null
xhr.send(null);

  利用Ajax进行前后端交互看起来非常简单,拿到响应后进行DOM操作即可,当然,在实际的开发中,很少写原生的Ajax,而是使用封装好的第三方库和框架,比如jQueryaxios

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
 $.ajax({
//获取数据url地址
url: "/url",
//获取数据的方式
type: "GET",
//获取数据类型
dataType: "JSON",
//接口所需参数
data:{"id":1},
beforeSend: function () {
console.log("发起请求之前在控制台打印");
},
//请求数据成功调用的方法
//传参data代表请求成功的数据
success:function(data){
console.log(data);
},
//请求失败
error: function(err) {
console.log(err);
},
complete: function () {
console.log("请求完成时在控制台打印");
}
})

可以看到,使用已经封装好的Ajax更加方便、简单。

一个非常好的Ajax基础教程:Ajax基础


Fetch

  在ES6中,新增了一种HTTP数据请求的方式:Fetch
  不同于Ajax是一种技术,使用XMLHttpRequest去实现,Fetch从定义上本身就是一个真实存在的API,它使用了ES6提出的promise对象(链式处理解决回调地狱)。关于AjaxFetch区别,说法五花八门,还是以后再深入了解吧。也可先看此知乎问题的第二个回答fetch底层也是基于XMLHttpRequest吗

  如何使用Fetch发请求,以登录为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
fetch('/login', {
method: "POST",
//请求的主体,转换为json对象
body: JSON.stringify({ username: account.value, password: password.value }),
//http头部的内容类型
headers: {
"Content-Type": "application/json"
},
})
.then(response => {
//判断响应是否成功
if (response.ok) {
//转换成js可操作的json数据并返回对象
return response.json();
} else {
return Promise.reject('QAQ出错啦');
}
})
.then(data => {
//拿到json对象后进行处理
console.log(data);
//这里的data是服务器返回的json
});

axios

axios官方文档

  Ajax只是一种技术,最开始单纯通过xhr去实现,而当promise出现后,出现了axios,它通过promise实现对ajax技术的一种封装,底层仍然是xhr,但支持了promise等一系列新功能与API
  与Ajax(xhr版)、Fetch不同的是,axios是第三方库,所以需要npm安装或者cdn引入后才可使用。

  简单的get

1
2
3
4
5
6
7
8
9
axios.get('/url', {
params: {
username: 'chuckle'
}
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});

  简单的post:

1
2
3
4
5
6
7
8
axios.post('/url', {
username: 'chuckle',
password: '123456'
}).then(function (response) {
console.log(response);
}).catch(function (error) {
console.log(error);
});

  相较于Ajax的老旧,Fetch的稚嫩,axios是目前最流行的网络请求库,vuereact都使用它,但如果简单发个请求获取个一言啥的,还是用fetch方便,毕竟能少引用一个库。


实战一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const btn = document.querySelector('button')
const p = document.querySelector('p')
btn.addEventListener('click', () => {
fetch('https://api.uixsj.cn/hitokoto/get?type=hitokoto&code=json', {
method: "GET",
})
.then(response => {
if (response.ok) {
return response.json();
} else {
return Promise.reject('QAQ出错啦');
}
})
.then(data => {
p.innerHTML = data.content;
});
})


1
2
3
<button>点击获取一言</button>
<p>一言测试</p>

1
2
3
button {
width: 100%;
color:

后记

  本文只简单概述了下前后端交互(前端发请求)的概念与实现方式,让有可能需要的人建立一个初步的、以前端为视角的前后端交互概念,也就是AjaxFetchaxios的初步认识。具体的HTTPES6JSONPromise等等,再说,在学。

参考文章: