介绍
常规的前后端交互都是直接传输html文档直接前端解析,但是做了前后端分离后,绝大部分都是通过JSON来进行数据交互的。简易的示例图如下:

特点
使用json有以下特点:
- 通用,轻量, 利于交互和传输
- 独立于语言,主流语言都提供了与 json 的编程接口
- json 本质上就是一个格式化字符串
- 类型:
number,string,boolean,null,array,object - 注: 没有
undefined
转换
- js->json:
JSON.stringify(obj) - json->js:
JSON.parse(jsonStr)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>JSON</title>
</head>
<body>
<script>
// 客户端 -> 服务器
// js对象 -> json格式字符串,这样才能和服务器进行数据交换
// php服务器,不可能认识js对象,但是它认识 json 字符串
// js对象
let obj = {
name: "电脑",
price: 5000,
desc: {
brand: "HUAWEI",
cpu: `i7-1200`,
},
};
console.log(obj);
// (1) js -> json
// JSON.stringify() js对象转换为json字符串
let jsonStr = JSON.stringify(obj);
// 序列化为JSON格式的字符串
console.log(jsonStr);
console.log(typeof jsonStr);
// 格式化json字符串
let json = JSON.stringify(obj, null, 4);
console.log(json);
// 过滤name和price属性,参数4是格式化
json = JSON.stringify(obj, ["name", "price"], 4);
console.log(json);
/**
* JSON特点
* 1. 所有属性必须使用双引号
* 2. 值,如果是字符串,必须使用双引号
*/
console.log(JSON.stringify([1, 2, 3, 4]));
console.log(JSON.stringify(true));
console.log(JSON.stringify("hello"));
// =======================================
// (2) json -> js
// 假设下面的json字符串是从服务器返回的数据
json = `
{
"course": "PHP",
"score": 90,
"content": ["html", "css", "js"]
}
`;
// JSON.parse()
// 将json字符串转换为js对象
obj = JSON.parse(json);
console.log(obj);
// 渲染到页面中
let str = `
<ul>
<li>课程: ${obj.course} </li>
<li>分数: ${obj.score} </li>
<li>科目: ${obj.content} </li>
</ul>
`;
//插入到元素element里面的第一个子节点之前
// document.body.insertAdjacentHTML("afterbegin", str);
//也可以直接把str贴到body里面
document.body.innerHTML = str;
</script>
</body>
</html>
跨域 cors: jsonp

- 同源
- 同源策略,禁止跨域: 浏览器最基本的安全机制
- 同源:协议,域名,端口全部相同,才可互相访问
下面域名全部跨域
https://php.cn
http://php.cn
http://php.net
https://php.cn:443
https://php.cn:888
- CORS
- CORS: 跨域资源共享(Cross-origin Resource Sharing)
- 突破了浏览器同源访问的安全策略
- JSONP:
JSON with Padding(用 JSON 填充参数)

demo1.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cors: jsonp</title>
<!-- http://hello.io/ -->
<!-- http://code.jquery.com -->
<!-- script标签具有天然的跨域属性,可以利用script来跨域请求 -->
<link rel="stylesheet" href="" />
<a href=""></a>
<img src="" alt="" />
<script src="https://lib.baomitu.com/jquery/1.12.4/jquery.js"></script>
</head>
<body>
<button onclick="getData()">跨域请求</button>
<script>
// jsonp: JSON with Padding
// 函数
function hello(user) {
console.log(user);
}
// 假设以下的数据,来自另外一台服务器,就要用到跨域了
const user = { uname: "朱老师", email: "zls@qq.com" };
hello(user);
</script>
<!-- <script src="http://world.io/test.php?fn=hello"></script> -->
<!-- 剩下工作极其简单, 就是动态创建上面的script语句就可以了 -->
<script>
function getData() {
// 1. 创建script
const script = document.createElement("script");
// 2. 设置跨域请求的url地址
// 返回的是一个执行hello函数的语句:hello({"uname":"灭绝老师","email":"mj@qq.com"})
script.src = "http://world.io/php23/0331/cors/test.php?fn=hello";
// 3. 将新创建的script元素追加到页面中
document.body.append(script);
}
</script>
</body>
</html>
test.php:
<?php
// jsonp
// 供前端调用的数据,以及函数调用语句,全部在服务器动态生成并返回就可以了
// 1. 准备数据
$user = json_encode(['uname' => '灭绝老师', 'email' => 'mj@qq.com'], 301);
// 获取函数名称
$fn = $_GET['fn'];
// 输出函数调用语句
echo "$fn($user)";
cors: 服务器端跨域

- 服务器允许:
Access-Control-Allow-Origin
demo2.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cors: 服务器端跨域</title>
</head>
<body>
<button onclick="getData()">跨域请求-1</button>
<script>
function getData() {
//异步请求
fetch(`http://world.io/php23/0331/cors/test1.php`)
.then((res) => res.json())
.then((res) => {
console.log(res);
});
}
</script>
</body>
</html>
test1.php:
<?php
// 允许跨域
header('Access-Control-Allow-Origin: *');
echo json_encode(['uname' => '马老师', 'email' => '5678@qq.com']);
Ajax(XHR): 了解(已淘汰)
- 创建对象:
new XMLHttpRequest() - 响应类型:
xhr.responseType = 'json' - 配置参数:
xhr.open("GET / POST", url, true) - 请求回调:
xhr.onload = () => console.log(xhr.response) - POST:
xhr.setRequestHeater('content-type','application/json') - 失败回调:
xhr.onerror = () => console.log('Error') - 发起请求:
xhr.send(null / jsonString)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ajax-xhr: 了解(已淘汰)</title>
</head>
<body>
<button onclick="getData(this)">Ajax(XHR)</button>
<script>
function getData(ele) {
// 1. 创建xhr对象
const xhr = new XMLHttpRequest();
// 2. 设置响应类型(返回的数据是什么类型: json)
xhr.responseType = "json";
// 3. 配置参数(请求方式,get/post,以及请求的url)
xhr.open("GET", "https://jsonplaceholder.typicode.com/todos/20");
// 4. 处理请求成功的回调函数
xhr.onload = function () {
console.log(xhr.response);
// dom操作,将数据渲染到页面
ele.insertAdjacentHTML("afterend", `<li>${xhr.response.title}</li>`);
};
// 5. 处理请求失败的回调函数
xhr.onerror = function () {
console.error("XHR Error");
};
// 6. 发送请求
xhr.send(null);
}
</script>
</body>
</html>
Fetch
- 异步请求:
fetch().then().then().catch() - 异步函数:
async,await - 注意:await 必须用在 async 声明的函数内部

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>fetch</title>
</head>
<body>
<button onclick="getData(this)">fetch api</button>
<script>
function getData(ele) {
/**
* 1. fetch(url): promise
* 2. then(): 按同步的方式去执行异步任务
* 3. then():
*/
/**
* 同步: 按顺序执行
* 异步: 任务是乱序执行,通过不断的添加回调来控制异步任务执行的顺序
*/
/**
* fetch 功能
* 1. fetch(url): 向一个url发请异步请求
* 2. then(response=>response.json())
* 3. then(json=>console.log(json))
*/
// 用法一:
fetch("https://jsonplaceholder.typicode.com/todos/20")
.then(function (response) {
// 将请求的结果转为json,将第2步的结果json,返回到第3步进一步处理
return response.json();
})
.then(function (json) {
console.log(json);
console.log(typeof json);
ele.insertAdjacentHTML("afterend", `<li>${json.title}</li>`);
});
// 用法二(简化):
const url = "https://jsonplaceholder.typicode.com/todos/20";
fetch(url)
.then((res) => res.json())
.then((json) =>
ele.insertAdjacentHTML("afterend", `<li>${json.title}</li>`)
)
.catch((err) => console.log(err));
// 将这种链式的异步的书写方式,改成传统的可读性更好的同步风格
}
</script>
</body>
</html>
async函数
这个方法是将上面fetch部分的链式的异步的书写方式,改成传统的可读性更好的同步风格。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>async函数</title>
</head>
<body>
<button onclick="getData(this)">async</button>
<script>
// 异步函数
async function getData(ele) {
const url = "https://jsonplaceholder.typicode.com/todos/15";
try {
// 1. 发起异步请求,等待返回结果的响应对象
const response = await fetch(url);
// 2. 如果响应成功,将响应结果转为json
const result = await response.json();
// 3. 对响应结果进行处理,例如渲染到到页面,或打印到控制台查看
console.log(result);
ele.insertAdjacentHTML("afterend", `<li>${result.title}</li>`);
} catch {
console.error("请求失败");
}
}
</script>
</body>
</html>
fetch api
不多介绍了,可以自行百度查阅,讲得比我还清楚,这边只作学习笔记的记录。

html.php:
<ul style="display:flex;list-style:none;gap:1em">
<li><a href="">首页</a></li>
<li><a href="">教学视频</a></li>
<li><a href="">社区问答</a></li>
</ul>
json.php:
<?php
$data = [
['id' => 1, 'name' => '外套', 'price' => 300],
['id' => 2, 'name' => '鞋子', 'price' => 200],
['id' => 3, 'name' => '袜子', 'price' => 50],
];
// 序列化为json格式字符串返回前端
echo json_encode($data);
insert.php:
<?php
// 获取的是json,并不是通过传统的表单键值对过来的
// $_POST 不能用
$jsonStr = file_get_contents('php://input');
// json字符串独立于任何编程语言,要想在当前的语言中使用
// 必须转为当前语言支持的数据类型
// json->php 加true,转为数组
$item = json_decode($jsonStr, true);
$data = [
['id' => 1, 'name' => '外套', 'price' => 300],
['id' => 2, 'name' => '鞋子', 'price' => 200],
['id' => 3, 'name' => '袜子', 'price' => 50],
];
// 将前端上传的数据,添加到数组中
array_push($data, $item);
// 将数组转为json字符串
echo json_encode($data);
style.css:
.container {
width: 300px;
min-height: 180px;
border: 1px solid #aaa;
}
.container .nav {
display: flex;
height: 30px;
border-bottom: 1px solid #aaa;
}
.container .nav > button {
flex: 1;
border: none;
background-color: #fff;
border-right: 1px solid #aaa;
}
.container .nav > button:last-child {
border-right: none;
}
.container .nav > button:hover {
cursor: pointer;
background-color: #eee;
transition: 0.5s;
}
fetch.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>fetch api</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container">
<!-- 导航区 -->
<div class="nav">
<button onclick="getHtml()">get-html</button>
<button onclick="getJson()">get-json</button>
<button onclick="postJson()">post-json</button>
</div>
<!-- 内容显示区 -->
<div class="box"></div>
<script>
const box = document.querySelector(".box");
// (1) 获取html
async function getHtml() {
// fetch, await
// 1. 发送请求fetch
let url = "http://fetch.edu/php23/0403/api/html.php";
// const response = await fetch(url)
const response = await fetch(url, {
method: "get",
});
// 2. 解析响应对象 response
// text() -> html / plain
let data = await response.text();
console.log(data);
// 3. 渲染
box.innerHTML = data;
}
// ================================
// (2) 获取json
async function getJson() {
// 1. 发送请求fetch
let url = "http://fetch.edu/php23/0403/api/json.php";
// fetch 默认就是get请求
// const response = await fetch(url)
const response = await fetch(url, {
method: "get",
});
// 2. 解析响应对象 response
// json() : json字符串-> js对象
let data = await response.json();
console.log(data);
// 3. 渲染 使用map方法遍历数组,将数组中的每一项拼接为li标签,再将li标签拼接为ul标签
const items = data.map(
(item) => `<li>${item.id}: ${item.name} (${item.price}) 元</li>`
);
// 拼接字符串
data = `<ul>${items.join("")}</ul>`;
console.log(items.join(""));
console.log(data);
box.innerHTML = data;
}
// ================================
// (3) post请求(以添加数据为例)
async function postJson() {
// 1. 发送请求fetch
let url = "http://fetch.edu/php23/0403/api/insert.php";
const response = await fetch(url, {
// 请求类型
method: "post",
// 请求头
headers: {
// 内容类型
"content-type": "application/json;charset=utf-8",
},
// 将需要传到服务器上的数据解析为json进行发送
body: JSON.stringify({ id: 4, name: "蛋糕", price: 250 }),
});
// 2. 解析响应对象 response
// json() : json字符串-> js对象
let data = await response.json();
console.log(data);
// 3. 渲染
const items = data.map(function (item) {
return `<li>${item.id}: ${item.name} ${item.price} 元</li>`;
});
console.log(items.join(""));
data = `<ul>${items.join("")}</ul>`;
box.innerHTML = data;
}
</script>
</div>
</body>
</html>
本文地址:https://www.mainblog.cn/333.html
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
版权声明:本文为原创文章,版权归 阁主 所有,欢迎分享本文,转载请保留出处!
免责申明:有些内容源于网络,没能联系到作者。如侵犯到你的权益请告知,我们会尽快删除相关内容。
黔ICP备19006353号-2
贵公网安备 52052102000042号