JSON Ajax – 掌握
1.JSON
1.1概念
数据格式,实质是一个字符串
1.2注意
1)属性名必须使用双引号
2)当属性值是字符串形式时,必须使用双引号
3)JSON文件中不允许出现注释
4)JSON数据不支持undefined和函数,对比js对象 则可以
1.3例子
{
"title":"苹果手机",
"list":[
{
"id":1,
"name":"苹果13",
"price":"5799元"
},
{
"id":2,
"name":"苹果13 pro",
"price":"7799元"
},
]
}
1.4方法
1)JSON.parse(JSON的字符串) -- 将JSON数据格式转换为js对象 (串-->对象) 常用
2)JSON.stringify(object) -- 将js对象转换为JSON字符串
1.5 举例实现
<script>
//创建js对象
let obj = {
name: '李通',
age: 20,
marry: false,
girlFriend: undefined,
height: null,
hobby: ['唱', '跳', '篮球'],
friend: {
name: '海龙',
age: 19
},
job() {
console.log('一名小学生');
}
}
console.log(obj, typeof obj);
//js对象转换为JSON字符串
let str = JSON.stringify(obj);
console.log(str, typeof str);//{"name":"李通","age":20,"merry":false,"height":null,"hobby":["唱","跳","篮球"],"friend":{"name":"海龙","age":19}} string
let myJson='{"name":"李通","age":20,"merry":false,"height":null,"hobby":["唱","跳","篮球"],"friend":{"name":"海龙","age":19}}';
//JSON字符串转换为js对象
console.log(JSON.parse(myJson));
console.log(typeof JSON.parse(myJson));
</script>
2.ajax
2.1概念
异步的js和xml
2.2作用
客户端给服务端发送http请求
2.3特点(重点)
1)异步请求
同步请求--第一个请求没有完成,第二个请求不可以发送
异步请求--第一个请求没有完成,不影响后面的请求
2)局部刷新
form发送请求--刷新整个页面(不推荐)
ajax发送请求--局部刷新--登录、注册页面,快递单号查询、搜索等
2.4优点
局部刷新-->给客户端节省宽高,提高用户的体验度
2.5缺点
依赖于js,浏览器不支持js,ajax就无法运行,ajax应用程序中安全性较低
2.6原理
-
在前端请求和服务器 中间的中间商
1)前端创建ajax对象 2)让ajax对象去请求服务器 3)服务器接收到前端的请求,处理请求 4)服务器把处理的数据返回给ajax对象 5)客户端渲染Ajax对象拿到的数据
2.7Ajax请求步骤
- 创建xhr对象 – 秘书
let xhr = new XMLHttpRequest();
xhr 返回值对象,js实现获取对象的属性,.
-
准备发送请求 – 让秘书找小王
xhr.open('请求方式','url',true);
- 请求方式 post/get
- url 后台地址
- 第三个属性:是否同步与异步 ajax必须true
-
发送请求 – 秘书去找小王
xhr.send();
-
监听函数 – 监督秘书的工作
onreadystatechange
- 检查请求的发送与失败
-
状态执行完毕获取数据 – 秘书成功找到小王
xhr.onreadystatechange=function(){
//后台成功的响应正确的数据
if(xhr.readyState===4 && status === 200){
//成功获取后台的数据
xhr.response //返回后台的数据
}
}
2.8http协议状态码
200 -- 成功
404 -- 资源不存在
5XX -- 后台的错误
2.9Ajax对象和服务器交互时产生的状态值
0 -- 还没有发送请求
1 -- 开始发送请求
2 -- 服务器接收到请求
3 -- 服务器处理请求
4 -- 服务器响应请求
2.10 使用AJAX与传统web的区别
- 之前的页面请求都是form 表单post与get的形式,整个页面刷新,用户体验差
- jajx 请求,利用XMLHttpRequest 创建对象,对象访问服务器,局部刷新即可实现,同时,服务器处理后的信息,首先返回到对象,对象给客户端,然后js 渲染到页面
2.11 举例实现
<script>
//ajax使用步骤
//1.创建xhr对象 -- 秘书
let xhr = new XMLHttpRequest();
console.log(xhr);
//2.准备发送请求 -- 让秘书找一下小王
xhr.open('get', './06ajax.php', true);
//3.发送请求 -- 秘书去找小王
xhr.send();
//4.监听函数 -- 监督秘书的工作
//只要状态发生改变,就会触发事件,事件会触发多次
xhr.onreadystatechange = function () {
//5.状态执行完毕才可以获取数据 -- 秘书正确的找到了小王
if (xhr.readyState === 4 && xhr.status === 200){
//成功获取后台的数据
console.log(xhr.response);
}
}
</script>
3.Ajax传递参数
3.1get传递参数
1)语法
后边的数据太长,可以使用一个变量传递
xhr.open('get','url?后台参数=前端参数值&后台参数=前端参数值',true);
//get传参在地址栏中
//url?后台参数=前端参数值&后台参数=前端参数值
// 后台参数: $_POST或者$_GET中括号里边的参数
// 前端参数值 用户数输入的参数值 ,变量 模板字符串的拼接处理
let params = `username=${user}&password=${pwd}`;
// 模板字符串注意空格问题
xhr.open('get', './php/03get.php?' + params, true);
2)说明
get传递参数是在url地址栏中传参,所以直接操作地址栏
<body>
<div class="box">
<p>
<input type="text" placeholder="输入用户名" class="name">
</p>
<p>
<input type="text" placeholder="输入密码" class="pwd">
</p>
<p>
<input type="button" value="登录" class="btn">
</p>
</div>
<script>
// 点击button,利用ajax 提交数据到后台,并返回给前端
document.querySelector('.btn').onclick = function(){
// 开始aja请求
let user = document.querySelector('.name').value
let pwd = document.querySelector('.pwd').value
// 1. 创建对象
let xhr = new XMLHttpRequest()
// console.log(xhr);
// 2.打开
// 后台数据=前端数据& 后台数据=前端数据
let str = `user= ${user} & password = ${pwd} `
xhr.open('get','./php/ex-03get.php?'+str,true)
// 3.发送
xhr.send()
// 4.处理ajax数据
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status===200){
console.log(xhr.response);
}
}
}
</script>
</body>
3.2post传递参数
-
语法
xhr.open('post','url',true);
-
//设置请求头
请求头的位置位于必须位于open send 之间
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=utf-8");
xhr.send('后台参数=前端参数值&后台参数=前端参数值');
<script>
document.querySelector('.btn').onclick = function(){
let user = document.querySelector('.user').value;
let pwd = document.querySelector('.pwd').value;
// console.log(user,pwd);
// ajax 处理过程
let xhr = new XMLHttpRequest()
xhr.open('post','./php/ex-4post.php',true)
// post 设置请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=utf-8");
// post传递的参数
xhr.send(`username=${user}&password=${pwd}`)
// xhr.send(`username=${user}&password=${pwd}`);
xhr.onreadystatechange = function(){
if(xhr.readyState ===4 && xhr.status ===200){
console.log(xhr.response);
// console.log(xhr);
}
}
}
</script>
3.3 案例-快递单号查询
- 技术难点
-
单独抽离出来 时间函数,对时间的处理,参数传递,返回值
-
前后端数据处理,检测到数据后,数据渲染到页面
-
<h2>查找快递案例实现</h2>
<h3>快递单号:4307101743736</h3>
快递单号:<input type="text" class="num">
<input type="button" value="查询" class="btn">
<ul>
</ul>
<script>
// 分析
// 输入单号 点击查询 xhr请求到后端 查看是否有数据
// 没有数据 返回"没有单号信息
// 有数据: 将处理处理后渲染到 ul中
// 单独抽离出来事件函数
// 1点击开始查询
document.querySelector('.btn').onclick = function () {
// 获取用户输入的表单
let num = document.querySelector('.num').value
let ul = document.querySelector('ul')
// 判断用户是否输入数据
if (num === '') {
// 用户没有输入数据
alert('输入快递单号后,开始查询')
} else {
// 用户输入了数据
// 2 xhr
let xhr = new XMLHttpRequest()
xhr.open('post', './php/ex-05kuaidi.php', true)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=utf-8")
xhr.send(`num=${num}`)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 判断是否存在数据
if (xhr.response == 0) {
// 不存在物流信息
ul.innerHTML = `
<h4>物流追踪</h4>
<p>暂未查到与您单号相关的物流信息,请稍后再尝试。<p>
`
} else {
// 3 存在物流信息,开始处理信息
// 将json数据转为js 对象 找到对应的数据数组 循环数组 渲染到页面
let obj = JSON.parse(xhr.response)
// console.log(obj);
let arrData = obj.data.info.context
console.log(arrData);
let str = ''
for (let i = 0; i < arrData.length; i++) {
str += `
<li>
<h5>物流时间:${time(arrData[i].time)}</h5>
<p>物流信息:${arrData[i].desc}</p>
</li>
`
}
ul.innerHTML = str
}
}
}
// 对返回的数据单位处理
function time(date) {
// 对事件的处理,毫秒,返回数据,miao
let time = new Date(date * 1000)
let year = time.getFullYear()
let month = time.getMonth()
let day = time.getDate()
let hours = time.getHours()
let secondes = time.getMinutes()
let minus = time.getMinutes()
// 事件补零操作
secondes = secondes > 10 ? secondes : '0' + secondes
minus = minus > 10 ? minus : '0' + minus
return `${year}年${month}月${day}日${hours}时${secondes}分${minus}秒`
}
}
}
</script>
<?php
$num = $_POST['num'];
$data ='这里是后台给过来的数据';
if($num =='4307101743736'){
// 存在对应的单号,将数据返回给前端,前端处理数据
echo $data;
}
else{
// 不存在快递数据,返回0
echo 0;
}
4.jquery封装的Ajax
4.1语法
$.ajax({
type:'get|post',//请求方式 (必须属性)
url:'路径',//请求的地址 (必须属性)
data:{//传参 -- 没有参数可以省略,es6新语法,如果两个参数名一样,可以省略一个
后台参数:前端参数值,
后台参数:前端参数值,
后台参数:前端参数值,
},
dataType:'返回的数据类型',//可以省略
async:'是否异步',//默认true--异步--可以省略
success:function(res){//形参--用来接收后台成功时返回的数据
},
error:function(err){//形参--用来接收后台失败时返回的数据--可以省略
},
beforeSend:function(){//请求成功之前执行的函数--可以省略
},
complete:function(){//请求完成时执行的函数,不管成功还是失败--可以省略
}
});
5.自己封装Ajax
5.1参考jquery封装的ajax
jquery中的ajax:
$.ajax({
type:'',
url:'',
data:{},
success(res){}
})
5.2 封装原生ajax:
myAjax({
type:'',
url:'',
data:{},
success(res){}
});
5.3原生ajax:
1.创建xhr对象
let xhr=new XMLHttpRequest();
2.准备发送请求
xhr.open('method','url',true);
3.发送
xhr.send();
4.监听
xhr.onreadystatechange=function(){
//5.状态完成
if(xhr.readyState===4&&xhr.status===200){
xhr.response//获取后台返回的数据
}
}
5.4 封装
1)点击按钮,发送http请求
2)判断get请求还是post请求
2)get请求在open中传参,post请求在send中传参
技术难点
- 处理参数字符串 循环遍历data对象,遍历之后对串的拼接
- 拼接字符串注意空格问题
- str +=
${key}=${obj.data[key]}&
user=DD& password=21&
<script>
// 分析
// 点击button,发送请求
// 参考jquery封装的Ajax
// 自己封装Ajax,原生js实现
document.querySelector('#btn').onclick = function () {
let user = document.querySelector('#user').value
let pwd = document.querySelector('#pwd').value
// 调用函数 myAjax() 实参传递的参数是一个对象 调用对象的属性和方法,形参obj.属性方法
myAjax({
type: 'get',
url: './php/ex-03get.php',
data: {
user: user,
password: pwd
},
success: function (res) {
console.log(res);
}
})
}
// 封装函数
function myAjax(obj) {
// 原生js实现ajax封装
// console.log(obj);
// 1.创建对象
let xhr = new XMLHttpRequest()
// 3.处理字符串参数字符串
// console.log(obj.data); //获取前后台参数,返回对象
let str = ''
for (const key in obj.data) {
// console.log(key); //输出对象的属性 user passwprd
// console.log(obj.data[key]); // 输出兑现的属性值 (用户输入的部分)
// 后台属性 = 前台属性值
str += `${key}=${obj.data[key]}&`
}
// 去掉最后一个&
let params = str.slice(0, -1)
// console.log(str); user=DD&password=21&
// console.log(params); //user=DD&password=21
// 2.判断请求的类型
if (obj.type === 'get') {
xhr.open('get', obj.url + '?' + params, true)
xhr.send()
} else if (obj.type === 'post') {
xhr.open('post', obj.url, true)
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
xhr.send(params)
}
// 4.时间监听
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 给调用函数的返回值,函数的获取,对象 .
obj.success(xhr.response);
}
}
}
</script>
6跨域
6.1 理解跨域
-
当前域名下网站去访问其他域名下的网站,浏览器出于安全考虑的同源策略
-
同源:协议,域名,端口号 只有这三个全部相同,才能实现访问
-
跨域:协议,域名,端口号 不同时,不能访问,解决办法,跨域处理
6.2 解决跨域问题
不同域名之间的访问,大型项目的前端和后台的数据可能不在一个服务器上
- jsonp —对数据的格式有问题
- cors 资源共享 —后台配置
- proxy 反向代理 —框架
- 后台代理(php代理)
6.2.1 后台代理 解决跨域
- 思路
php 访问服务器,服务器将数据返回给php,php将数据响应给前端 - 语法
php访问服务器
file_get_contents(‘服务器路径’) - 直接访问出现的bug
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
6.2.2 jsonp 解决跨域
- 原理:
- 动态创建script标签 (创建之后得添加到页面)
- 设置src属性去访问资源(src 属性可以往上访问所有的资源,不会产生跨域问题)
- 后台给前端响应数据,前端定义函数 去接受返回的数据
- 补充
- 只支持get请求
- 返回的数据必须是一个函数
- 实现过程
<body>
<input type="text" id="text">
<button id="search">百度一下</button>
<script>
//jsonp解决跨域
//1.创建script 2.scr请求数据 3.前端用函数接收返回的数据
//1.绑定点击事件
document.getElementById('search').onclick = function () {
//2、获取当前值
let text = document.getElementById('text').value;
//3.网络请求
//3.1创建script
let script = document.createElement('script');
//3.2scr请求数据
//wd -- 后台定义接收前端参数的变量
//cb=callback -- cb:后台定义用来接收前端函数的变量,callback:前端接收数据的变量名
script.src = 'http://suggestion.baidu.com/su?cb=callback&wd=' + text;
//3.3添加到body中
document.body.appendChild(script);
}
//3.4前端定义接收数据的函数
function callback(res){
console.log(res);
}
</script>
</body>
6.2.3 jQuery 封装的jsonp 解决跨域问题
<body>
<input type="text" id="text">
<button id="search">百度一下</button>
<script src="./js/jquery-3.6.0.min.js"></script>
<script>
//1.绑定点击事件
$('#search').click(function () {
//2.获取当前值
let text = $('#text').val();
//3.网络请求
//使用jquery封装的jsonp解决跨域
$.ajax({
type: 'get',
url: 'http://suggestion.baidu.com/su?',
data: {
//后台参数:前端参数值
wd: text
},
dataType: 'jsonp',//返回的数据格式必须设置
jsonp: 'cb',//后台定义用来接收前端函数的变量名,默认为callback,如果是callback可以省略
// jsonpCallback:'callback',//前端接收数据的函数名--一直可以省略,省略后默认为:jquery+随机数字
success(res) {
console.log(res);
}
})
})
</script>
</body>