JSON、AJAX初学习+简上手
1. JSON基础知识
1.1 JSON 是什么?
- JSON:JavaScript Object Notation(JS 对象表示法)
- JSON 独立于任何变成语言,几乎所有变成语言都提提供了访问 JSON 数据的 API 接口
- JSON 是一种语法,用来序列化其他语言创建的数据类型
- JSON 仅支持 6 种数据类型:对象、数组、数值、字符串、布尔值、null
- JSON 只是借用了 JS 中的一些数据表示语法,与 JS 并无关系
1.2 JSON 数据类型
序号 | 类型 | 描述 |
---|---|---|
1 | 简单值 | 数值、字符串、布尔、null |
2 | 复合值 | 对象、数组 |
注意:不支持
undefined
(因为除了 JS 外,其他语言中没有这个undefined
定义)
1.3 JS 解析 JSON 的 API
序号 | 方法 | 描述 |
---|---|---|
1 | JSON.stringify() |
将 JS 对象,序列化为 JSON 字符串 |
2 | JSON.parse() |
将 JSON 字符串,解析为 JS 对象 |
—————————————————————————————————-
2. JSON示例
2.1 JSON.stringify(data,replacer,apace):将JS数据转为JSON。
data:JS数据(数组、对象都行);replacer:处理的方式(数组、函数都行);space:限定输出的格式;转为的json数据都是string类型
console.log(JSON.stringify(3.14),typeof JSON.stringify(3.14));//3.14 string
console.log(JSON.stringify("php.cn"),typeof JSON.stringify("php.cn"));//"php.cn" string
console.log(JSON.stringify(true),typeof JSON.stringify(true));//"php.cn" string
console.log(JSON.stringify(null),typeof JSON.stringify(null));//"php.cn" string
console.log(JSON.stringify({x:"a",y:"b"}),typeof JSON.stringify({x:"a",y:"b"}));//{"x":"a","y":"b"} string
console.log(JSON.stringify([1,2,3]),typeof JSON.stringify([1,2,3]));//[1,2,3] string
//>注意:json对象的属性必须加双引号,字符串也是
// 对JSON格式字符串的特殊操作,主要通过第二个参数;第二个参数支持数组和函数
// 数组
console.log(JSON.stringify({a:1,b:2,c:3},["a","b"]));//{"a":1,"b":2} 过滤数据,只要属性是a和b的
// 函数
console.log(JSON.stringify({a:1,b:2,c:3},(k,v)=>{
//将需要过滤的数据直接返回undefined
if(v<2) return undefined;
return v;
}));//{"b":2,"c":3} 过滤数据,只要值小于2的
// 第三个参数用来格式化输出JSON字符串
console.log(JSON.stringify({a:1,b:2,c:3},null,2));//在每组数据前加两个空格
console.log(JSON.stringify({a:1,b:2,c:3},null,"---"));//使用字符串的话则用对应字符串进行标识
2.2 JSON.parse(str,reviver) 将json转为js对象;str为JSON数据;
let obj=JSON.parse(`{"a":1,"b":2,"c":3}`);
console.log(obj,typeof obj);//Object { a: 1, b: 2, c: 3 } object
// reviver可以对json数据进行处理后再返回
obj=JSON.parse(`{"a":1,"b":2,"c":3}`,(k,v)=>{
// json对象是由内向外解析的
if(k==="") return v;
return v*2;
});//{ a: 2, b: 4, c: 6 }
———————————————————————
3. Ajax 异步请求 基础知识
注意:异步请求不要使用 vs code 的 live server 插件,必须创建一个本地服务器环境
3.1 同步与异步
以前端请求后,后端响应为例
- 同步:前端发请求,必须等到后端响应完成后,才允许发送另外一个请求
- 异步:前端发请求后不等待后端响应结果继续执行,后端响应完成通过事件通知前端处理
3.2 XMLHttpRequest
对象
XMLHttpRequest
是浏览器对象,而非 JS 内置对象
3.2.1 xhr 请求步骤
- 1.创建 xhr 对象:
const xhr=new XMLHttpRequest();
- 2.配置 xhr 参数:
xhr.open(type,url);
- 3.处理 xhr 响应:
xhr.onload=(...)=>{...};
- 4.发送 xhr 请求:
xhr.send(...);
3.2.2 xhr 对象常用属性
序号 | 方法 | 描述 |
---|---|---|
1 | responseType | 设置响应类型 |
2 | response | 响应正文 |
3.2.3 xhr 对象常用方法
序号 | 方法 | 描述 |
---|---|---|
1 | open(type,url) | 配置请求参数 |
2 | send(data/null) | 发送请求 |
3.2.4 xhr 对象常用事件
序号 | 事件 | 描述 |
---|---|---|
1 | load() | 请求成功 |
2 | error() | 请求失败 |
https://developer.mozilla.org/zh-CN/docs/Web/API/xmlhttprequest
3.3 FormData
对象
FormData
是表单数据构造器
|序号|方法|描述|
|—-|——|——|
|1|append(name,value)|请求成功|
|2|delete(name)|请求失败|
3.4 get/post
区别
- get 是 url 传参,post 是
request body
请求体传参 - get 回退无影响,post 回退会重复提交
- get 生成的 url 可以做书签,post 不行
- get 只能对 url 进行编码,post 支持多种编码
- get 请求参数会保留在历史记录中,post 请求参数不保留
- get 参数长度受限,post 参数长度无限制
- get 只接受 ASCII 码字符,post 无限制
- get、post 底层实现是一致的,都是基于 http 协议
- get 也可以带上
request body
,post 也可以带上 URL 参数 - get 产生一个 tcp 数据包,post 产生两个 tcp 数据包
- get 产生一个请求,post 产生两个请求
- get 请求,浏览器将
header,data
一起发出,服务器响应 200 成功 - post 请求,浏览器先发出
header
,得到响应 100 continue,在发出data
,得到响应 200 - 并非所有浏览器的 post 都产生二次 http 请求,firefox 就只产生一次
3.5跨域
- CORS:跨域资源共享
- 跨域请求可以是 get,也可以是 post,不过 get 居多
cors-post
时,需要在服务器端进行头部设置- jsonp 只能是 get
———————————————————————————-
4. AJAX 简单示例
4.1 get方式请求
HTML代码
<button>ajax-get</button>
<p></p>
JavaScript代码
const btn=document.querySelector("button");
btn.onclick=()=>{
// 1.创建 xhr 对象:
const xhr=new XMLHttpRequest();
// 2.配置 xhr 参数:
xhr.open('get',"test.php?id=1");
xhr.responseType='json';//默认,可不写
// 3.处理 xhr 响应:
// 成功
xhr.onload=()=>{
console.log(xhr.response);
//dom将响应结果渲染到页面
let user=`${xhr.response.name}的邮箱:${xhr.response.email}`;
document.querySelector("p").innerHTML=user;
};
// 失败
xhr.error=()=>console.log("Error");
// 4.发送 xhr 请求:
xhr.send(null);
}
PHP代码:test.php
// 以二维数组模拟数据表信息
$users = [
['id'=>1, 'name'=>'天蓬','email'=>'tp@php.cn','password' => md5('123456')],
['id'=>2, 'name'=>'灭绝','email'=>'mj@php.cn','password' => md5('abc123')],
['id'=>3, 'name'=>'西门','email'=>'xm@php.cn','password' => md5('abc888')],
];
// 查询条件
$id = $_GET['id'];
// 在id组成的数组中查询是否存在指定的id,并返回对应的键名
$key = array_search($id,array_column($users,'id'));
// 根据键名返回指定的用户信息
echo json_encode($users[$key]);
4.2 post方式请求
CSS代码
.login {
width: 20em;
border: 1px solid;
padding: 0 1em 1em;
background-color: lightcyan;
margin: 2em auto;
display: grid;
place-items: center;
}
.login form {
display: grid;
grid-template-columns: 3em 1fr;
gap: 1em 0;
}
/* 按钮与提示信息显示在第二列 */
.login form button,
.tips {
grid-area: auto / 2;
}
HTML代码
<div class="login">
<h3>用户登录</h3>
<form action="">
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" />
<label for="password">密码:</label>
<input type="password" name="password" id="password" />
<button>提交</button>
<span class="tips"></span>
</form>
</div>
JavaScript代码
const form=document.querySelector(".login form");
const btn=document.querySelector(".login button");
const tips =document.querySelector(".tips");
btn.onclick=(ev)=>{
// 要先禁用掉默认提交
ev.preventDefault();//或者在form里添加` onsubmit="return false"`
// 1.创建xhr对象
const xhr=new XMLHttpRequest();
// 2.设置xhr参数
xhr.open("post","test2.php");
// 3.处理xhr响应
xhr.onload=()=>(tips.innerHTML=xhr.response);
// 4.发送xhr请求
xhr.send(new FormData(form));
}
PHP代码:test2.php
// 使用二维数组模拟用户数据表信息
$users = [
['id' => 1, 'name' => '天蓬', 'email' => 'tp@php.cn', 'password' => md5('123456')],
['id' => 2, 'name' => '灭绝', 'email' => 'mj@php.cn', 'password' => md5('abc123')],
['id' => 3, 'name' => '西门', 'email' => 'xm@php.cn', 'password' => md5('abc888')],
];
// 将通过post获取的数据保存到临时变量中
$email = $_POST['email'];
$password = md5($_POST['password']);
// 使用数组过滤器查询是否存在指定的用户并返回结果
$res = array_filter($users, function ($user) use ($email, $password) {
return $user['email'] === $email && $user['password'] === $password;
});
// 将结果做为请求响应返回到前端
echo count($res) === 1 ? '验证成功' : '验证失败';
4.3 cors:跨域资源共享(get方式)
同源策略:为请求的安全,浏览器禁止通过脚本发起跨域请求;只允许通过脚本发起基于同源(协议相同、域名/主机名相同、端口相同)的请求
HTML
<button>ajax-get-cors</button>
<p></p>
JS
const btn=document.querySelector("button");
const p=document.querySelector("p");
btn.onclick=()=>{
// 1.创建xhr对象
const xhr=new XMLHttpRequest();
// 2.配置xhr参数
xhr.open("get","http://word.cn/index.php");
// 3.处理xhr响应
xhr.onload=()=>(document.querySelector("p").innerHTML=xhr.response);
// 4.发送xhr请求
xhr.send(null);
}
PHP
//在服务器端开启跨域许可;*表示许可任何来源
header("Access-Control-Allow-Origin:http://php.cn");
echo "CORS:跨域请求成功!";
4.4 cors:跨域资源共享(post方式)
HTML
<button>ajax-post-cors</button>
<p></p>
JS
const btn=document.querySelector("button");
const p=document.querySelector("p");
btn.onclick=()=>{
// 1.创建xhr对象
const xhr=new XMLHttpRequest();
// 2.配置xhr参数
xhr.open("post","http://word.cn/index2.php");
// 3.处理xhr响应
xhr.onload=()=>(document.querySelector("p").innerHTML=xhr.response);
// 4.发送xhr请求
const formData=new FormData();
formData.append("username","Jy");
formData.append("password","abc123");
xhr.send(formData);
}
PHP
//在服务器端开启跨域许可;*表示许可任何来源
header("Access-Control-Allow-Origin:http://php.cn");
print_r($_POST);
4.5 jsonp
HTML
<button>jsonp-cors</button>
<p></p>
JS
function getUser(data){
console.log(data);
let user=data.name+":"+data.email;
document.querySelector("p").innerHTML=user;
}
//从前端将这个前端需要调用的函数名称告诉服务器上的php,让php动态生成一个函数调用语句并返回
const btn=document.querySelector("button");
btn.onclick=()=>{
// 1.动态生成一个允许跨域请求的html元素
let script = document.createElement("script");
// 2.将跨域请求的url调价到这个script的src属性上
script.src="http://word.cn/jsonp.php?callback=getUser";
// 3.将script挂在到这个页面中 document.body.insertBefore(script,document.body.firstElementChild);//挂在到body第一个元素之前
}
PHP
// jsonp不需要授权给前端
// 只要返回一个使用json作为参数的函数调用语句就可以
// 将前端需要的数据以json格式放到这个函数中
// 必须要知道前端js要调用的函数名称
$callback = $_GET['callback'];
//从服务器返回需要的数据
$data = '{"name":"景云","email":"jy@php.cn"}';
// 格式为 getUser({"name":"景云","email":"jy@php.cn"});
// 进行拼接e
echo $callback . "(" . $data . ")";