JSON数据格式
- JSON 是什么?
在 JS 语言中,一切都是对象。因此,任何支持的类型都可以通过 JSON 来表示,例如字符串、数字、对象、数组等。但是对象和数组是比较特殊且常用的两种类型
- JSON: JavaScript Object Notation(JS 对象表示法)
- JSON 独立于任何编程语言, 几乎所有编程语言都提供了访问 JSON 数据的 API 接口
- JSON 是一种语法,用来序列化其它语言创建的数据类型
- JSON 仅支持 6 种数据类型:对象,数组,数值,字符串,布尔值,null
- JSON 只是借用了 JS 中的一些数据表示语法,与 JS 并无关系
- JSON 数据类型
序号 | 类型 | 描述 |
---|---|---|
1 | 简单值 | 数值,字符串,布尔,null |
1 | 复合值 | 对象,数组 |
- JS 解析 JSON 的 API
序号 | 方法 | 描述 |
---|---|---|
1 | JSON.stringify() |
将 JS 对象,序列化为 JSON 字符串 |
2 | JSON.parse() |
将 JSON 字符串,解析为 JS 对象 |
要实现从对象转换为 JSON 字符串,使用 JSON.stringify() 方法:
要实现从 JSON 转换为对象,使用 JSON.parse() 方法:
JSON 键值对是用来保存 JS 对象的一种方式,和 JS 对象的写法也大同小异,键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值
data.json
{
"name":"zhansan",
"age":12,
"lover":["coding","swimming","singing"],
"friend":{
"high":"180cm",
"weight":"80kg",
"lover":["swimming","singing","dancing"],
"friend":{}
}
}
JSON方法
JavaScript中JSON对象与JSON字符串相互转换
var obj = new Object();
obj.Name = "八戒"
obj.Age = 500;
//通过字面量的形式来定义对象
var obj1 = { "Name": "八戒", "Age": "500" };
var arr = [{ "Name": "八戒", "Age": "500" }, { "Name": "八戒1", "Age": "1000" }];
//JSON格式:将json的字面量表示形式,当做字符串存放,则为json格式字符串
var str = '{ "Name": "八戒", "Age": "500" }';
var jsonstrarr = '[{ "Name": "八戒", "Age": "500" }, { "Name": "八戒1", "Age": "1000" }];';
//将json字符串转换成js对象(数组)
var resobj = JSON.parse(str);
alert(resobj.Name);
JS对象转换成为JSON
JSON.stringify()
var data = {
name:"zhansan",
age:12,
lover:["coding","swimming","singing"],
friend:{
high:"180cm",
weight:"80kg",
lover:["swimming","singing","dancing"],
friend:{}
}
};
var arr = [
{id: 1,name: "admin",age: 18},
{id: 2,name: "php",age: 26},
{id: 3,name: "js",age: 15},
{id: 3,name: "ajax",age: 3},
];
var json_data = JSON.stringify(data);
console.log(json_data);
console.log(JSON.stringify(arr));
JSON.stringify()第二个参数是个可选参数,被称为replacer。这个参数可以是数组或者函数。它提供了一个过滤机制制定了应该或者不应该包含哪些属性
const obj = {
a: 0,
b: 1,
c: [0, 1, 2]
}
JSON.stringify(obj,['a', 'c']) // "{"a":0,"c":[0,1,2]}"
JSON.stringify(obj,(key,value)=>{
if(key !== 'b'){
return value
}
})
// "{"a":0,"c":[1,2,3]}"
第三个可选的参数也可以传递给JSON.stringify(),被称为space,被用作缩进,是为了使得输出有格式更加漂亮。
const a = {
b: 42,
c: "42",
d: [1,2,3]
};
JSON.stringify( a, null, 3 );
// "{
// "b": 42,
// "c": "42",
// "d": [
// 1,
// 2,
// 3
// ]
// }"
JSON.stringify( a, null, "-----" );
// "{
// -----"b": 42,
// -----"c": "42",
// -----"d": [
// ----------1,
// ----------2,
// ----------3
// -----]
// }"
JSON转换为JS对象
JSON.parse()
var resobj = JSON.parse(str);
FormData方法
将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
一、创建formData对象
1、创建一个空对象:
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//可以通过append()方法来追加数据
formdata.append("name","laotie");
//通过get方法对值进行读取
console.log(formdata.get("name"));//laotie
//通过set方法对值进行设置
formdata.set("name","laoliu");
console.log(formdata.get("name"));//laoliu
2、通过表单对formData进行初始化
<form id="advForm">
<p>广告名称:<input type="text" name="advName" value="xixi"></p>
<p>广告类别:<select name="advType">
<option value="1">轮播图</option>
<option value="2">轮播图底部广告</option>
<option value="3">热门回收广告</option>
<option value="4">优品精选广告</option>
</select></p>
<p><input type="button" id="btn" value="添加"></p>
</form>
通过表单元素作为参数,实现对formData的初始化:
//获得表单按钮元素
var btn=document.querySelector("#btn");
//为按钮添加点击事件
btn.onclick=function(){
//根据ID获得页面当中的form表单元素
var form=document.querySelector("#advForm");
//将获得的表单元素作为参数,对formData进行初始化
var formdata=new FormData(form);
//通过get方法获得name为advName元素的value值
console.log(formdata.get("advName"));//xixi
//通过get方法获得name为advType元素的value值
console.log(formdata.get("advType"));//1
}
二、formData操作方法
1、通过get(key)与getAll(key)来获取相对应的值
// 获取key为age的第一个值
formdata.get("age");
// 获取key为age的所有值,返回值为数组类型
formdata.getAll("age");
2、通过append(key,value)在数据末尾追加数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//通过append()方法在末尾追加key为name值为laoli的数据
formdata.append("name","laoli");
//通过append()方法在末尾追加key为name值为laotie的数据
formdata.append("name","laotie");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoliu
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoliu", "laoli", "laotie"]
3、通过set(key, value)来设置修改数据
key的值不存在,会添加一条数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//如果key的值不存在会为数据添加一个key为name值为laoliu的数据
formdata.set("name","laoli");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoli
key的值存在,会修改对应的value值
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//通过append()方法在末尾追加key为name值为laoliu2的数据
formdata.append("name","laoliu2");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoliu
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoliu", "laoliu2"]
//将存在的key为name的值修改为laoli
formdata.set("name","laoli");
//通过get方法读取key为name的第一个值
console.log(formdata.get("name"));//laoli
//通过getAll方法读取key为name的所有值
console.log(formdata.getAll("name"));//["laoli"]
4、通过has(key)来判断是否存在对应的key值
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
//判断是否包含key为name的数据
console.log(formdata.has("name"));//true
//判断是否包含key为age的数据
console.log(formdata.has("age"));//false
5、通过delete(key)可以删除数据
//通过FormData构造函数创建一个空对象
var formdata=new FormData();
//通过append()方法在末尾追加key为name值为laoliu的数据
formdata.append("name","laoliu");
console.log(formdata.get("name"));//laoliu
//删除key为name的值
formdata.delete("name");
console.log(formdata.get("name"));//null
三、通过XMLHttpRequest发送数据
创建表单:
<form id="advForm">
<p>广告名称:<input type="text" name="advName" value="xixi"></p>
<p>广告类别:<select name="advType">
<option value="1">轮播图</option>
<option value="2">轮播图底部广告</option>
<option value="3">热门回收广告</option>
<option value="4">优品精选广告</option>
</select></p>
<p>广告图片:<input type="file" name="advPic"></p>
<p>广告地址:<input type="text" name="advUrl"></p>
<p>广告排序:<input type="text" name="orderBy"></p>
<p><input type="button" id="btn" value="添加"></p>
</form>
发送数据:
var btn=document.querySelector("#btn");
btn.onclick=function(){
var formdata=new FormData(document.getElementById("advForm"));
var xhr=new XMLHttpRequest();
xhr.open("post","http://127.0.0.1/adv");
xhr.send(formdata);
xhr.onload=function(){
if(xhr.status==200){
//...
}
}
}
AJax请求
一、Ajax定义
1、什么是Ajax
Ajax:即异步 JavaScript 和XML。Ajax是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。而传统的网页(不使用 Ajax)如果需要更新内容,必需重载整个网页面。
2、同步与异步的区别
同步提交:当用户发送请求时,当前页面不可以使用,服务器响应页面到客户端,响应完成,用户才可以使用页面。
异步提交:当用户发送请求时,当前页面还可以继续使用,当异步请求的数据响应给页面,页面把数据显示出来 。
3、ajax的工作原理
客户端发送请求,请求交给xhr,xhr把请求提交给服务,服务器进行业务处理,服务器响应数据交给xhr对象,xhr对象接收数据,由javascript把数据写到页面上,如下图所示:
二、实现AJAX的基本步骤
要完整实现一个AJAX异步调用和局部刷新,通常需要以下几个步骤:
- 创建XMLHttpRequest对象,即创建一个异步调用对象.
- 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
- 设置响应HTTP请求状态变化的函数.
- 发送HTTP请求.
- 获取异步调用返回的数据.
- 使用JavaScript和DOM实现局部刷新.
1、创建XMLHttpRequest对象const xhr = new XMLHttpRequest();
2、创建HTTP请求
创建了XMLHttpRequest对象之后,必须为XMLHttpRequest对象创建HTTP请求,用于说明XMLHttpRequest对象要从哪里获取数据。通常可以是网站中的数据,也可以是本地中其他文件中的数据。
创建HTTP请求可以使用XMLHttpRequest对象的open()方法,其语法代码如下所示:xhr.open(method,URL,flag,name,password);
代码中的参数解释如下所示:
- method:该参数用于指定HTTP的请求方法,一共有get、post、head、put、delete五种方法,常用的方法为get和post。
- URL:该参数用于指定HTTP请求的URL地址,可以是绝对URL,也可以是相对URL。
- flag:该参数为可选,参数值为布尔型。该参数用于指定是否使用异步方式。true表示异步、false表示同步,默认为true。
- name:该参数为可选参数,用于输入用户名。如果服务器需要验证,则必须使用该参数。
- password:该参数为可选,用于输入密码。若服务器需要验证,则必须使用该参数。
xhr.open("get","./ajax.htm",true);
3、处理 xhr 响应: xhr.onload = (...) => {...}
4、发送 xhr 请求: xhr.send(...)
xhr 对象常用属性
序号 | 方法 | 描述 |
---|---|---|
1 | responseType |
设置响应类型 |
2 | response |
响应正文 |
xhr 对象常用方法
序号 | 方法 | 描述 |
---|---|---|
1 | open(type,url) |
配置请求参数 |
2 | send(data/null) |
发送请求 |
xhr 对象常用事件
序号 | 事件 | 描述 |
---|---|---|
1 | load() |
请求成功 |
2 | error() |
请求失败 |
http请求类型:
GET :向指定资源请求数据,一般用来获取,查询资源信息
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)
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 就只产生一次
get请求参数
<form>
<input type="text" name="username" id="username">
<input type="password" name="password" id="password">
<span id="info">提示信息</span>
<input type="button" id="btn" value="登录">
</form>
var btn = document.getElementById('btn');
btn.onclick = function(){
var uname = document.getElementById('username').value;
var pw = document.getElementById('password').value;
// 1、创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();
/*
参数一:请求方式(get获取数据;post提交数据)
参数二:请求地址
参数三:同步或者异步标志位,默认是true表示异步,false表示同步
如果是get请求那么请求参数必须在url中传递
encodeURI()用来对中文参数进行编码,防止乱码
*/
// 2、准备发送
var param = 'username='+uname+'&password='+pw;
xhr.open('get','./getDemo.php?'+encodeURI(param),true);
// 3、执行发送动作
xhr.send(null); // get请求这里需要添加null参数
// 4、指定回调函数
xhr.onreadystatechange = function(){
/*
readyState:
2 浏览器已经收到了服务器响应的数据
3 正在解析数据
4 数据已经解析完成
*/
if(xhr.readyState == 4){
/* http的常见状态码
200 响应成功
404 没有找到请求资源
500 服务器端错误*/
if(xhr.status == 200){
let data = xhr.responseText;
let info = document.querySelector("#info");
if(data == '1'){
info.innerText = "登录成功";
}else{
info.innerText = '用户名或密码错误';
}
}
}
}
}
$uname = $_GET['username'];
$pw = $_GET['password'];
if($uname == 'admin' && $pw == '123'){
echo "1";
}else{
echo $uname;
}
<!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-get</title>
</head>
<body>
<input type="text" placeholder="请输入ID号,例如:1">
<button>Ajax-GET请求</button>
<p></p>
<script>
const btn = document.querySelector("button");
const id = document.querySelector("input");
btn.onclick = () => {
// 1. 创建 xhr 对象:
const xhr = new XMLHttpRequest();
// 2. 配置 xhr 参数:
xhr.open("get", "test1.php?id="+id.value);
// 设置请求返回数据格式
xhr.responseType = "json";
// 3. 处理 xhr 响应:
xhr.onload = () => {
// xhr.response: 响应的返回值,是json字符串
// console.log(typeof xhr.response);
// 如果显式的设置了响应类型,如json,这里就是直接自动转为js对象
console.log(xhr.response);
// 是将json转为js对象
// console.log(JSON.parse(xhr.response));
let user = `用户名:${xhr.response.name} ( 邮箱:${xhr.response.email} )`;
document.querySelector("p").textContent = user;
};
xhr.onerror = () => console.log("Error");
// 4. 发送 xhr 请求: `xhr.send(...)`
xhr.send(null);
};
</script>
</body>
</html>
// 以二维数组模拟数据表信息
$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]);
post请求参数
<form>
<input type="text" name="username" id="username">
<input type="password" name="password" id="password">
<span id="info">提示信息</span>
<input type="button" id="btn" value="登录">
</form>
var btn = document.getElementById('btn');
btn.onclick = function(){
var uname = document.getElementById('username').value;
var pw = document.getElementById('password').value;
// 1、创建XMLHttpRequest对象
xhr = new XMLHttpRequest();
/*
参数一:请求方式(get获取数据;post提交数据)
参数二:请求地址
参数三:同步或者异步标志位,默认是true表示异步,false表示同步
post请求参数通过send传递,不需要通过encodeURI()转码
必须设置请求头信息
*/
// 2、准备发送
var param = 'username='+uname+'&password='+pw;
xhr.open('post','postDemo.php',true);
// 3、执行发送动作
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(param); // post请求参数在这里传递,并且不需要转码
// 4、指定回调函数
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
if(xhr.status == 200){
document.querySelector("#info").innerText = xhr.responseText;
}
}
}
}
$uname = $_POST['username'];
$pw = $_POST['password'];
if($uname == 'admin' && $pw == '123'){
echo "登录成功";
}else{
echo '用户名或密码错误';
}
<!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-POST</title>
<style>
body {
background-color: lightcyan;
}
.login {
width: 20em;
/*border: 1px solid;*/
box-shadow: 0 0 8px #888;
padding: 0 1em 1em;
background-color: lightseagreen;
color: white;
margin: 2em auto;
display: grid;
place-items: center;
}
.login form {
display: grid;
grid-template-columns: 3em 1fr;
gap: 1em 0;
}
.login form input {
border: none;
outline: none;
}
.login form input:focus,
.login form input:hover {
box-shadow: 0 0 5px lime;
}
.login form button {
background-color: lightsalmon;
color: white;
outline: none;
border: none;
height: 2em;
}
.login form button:hover {
background-color: salmon;
cursor: pointer;
box-shadow: 0 0 5px lime;
}
/* 按钮与提示信息显示在第二列 */
.login form button,
.tips {
grid-area: auto / 2;
}
</style>
</head>
<body>
<div class="login">
<p>用户登录</p>
<form action="" onsubmit="return false">
<label for="email">邮箱:</label>
<input type="email" name="email" id="email" placeholder="请输入邮箱" />
<label for="password">密码:</label>
<input type="password" name="password" id="password" placeholder="请输入密码" />
<button>提交</button>
<span class="tips"></span>
</form>
<script>
const form = document.querySelector(".login form");
const btn = document.querySelector(".login button");
const tips = document.querySelector(".tips");
// FormData: 表单数据的序列化
let data = new FormData();
data.append("email", "20602138376@qq.com");
data.append("password", "123456");
console.log(data.get("email"), data.get("password"));
console.log(data);
btn.onclick = (ev) => {
// 默认的提交行为
ev.preventDefault();
// 1. 创建 xhr 对象:
const xhr = new XMLHttpRequest();
// 2. 配置 xhr 参数:
xhr.open("post", "test2.php");
// xhr.responseType = "text";
// 3. 处理 xhr 响应:
xhr.onload = () => {
tips.textContent = xhr.response;
};
xhr.onerror = () => console.log("Error");
// 4. 发送 xhr 请求:
xhr.send(new FormData(form));
};
</script>
</div>
</body>
</html>
<?php
// print_r($_POST);
// 使用二维数组模拟用户数据表信息
$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 ? '验证成功' : '验证失败';
cors跨域请求
- CORS: 跨域资源共享
- 跨域请求可以是 get,也可以是 post,只不过 get 居多
- cors-post 时,需要在服务器端进行头部设置
- jsonp 只能是 get
跨域的含义
同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指”协议+域名+端口”三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略限制内容有:
- Cookie、LocalStorage、IndexedDB 等存储性内容
- DOM 节点
- AJAX 请求不能发送
但是有三个标签允许跨域加载资源:
<img src="...">
<link href="...">
<scripts src="...">
当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,就算作“跨域”。常见跨域场景如下图所示:
特别说明两点:
第一:如果是协议和端口造成的跨域问题“前端”是处理不了的。
第二:在跨域问题上,仅仅是通过“URL的首部”来识别而不会根据域名对应的IP地址是否相同来判断。“URL的首部”可以理解为“协议, 域名和端口必须匹配”。
这里你或许有个疑问:请求跨域了,那么请求到底发出去没有?
跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回响应,只是响应被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不行?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。
// 1. 创建xhr对象
const xhr = new XMLHttpRequest();
// 2. 配置xhr参数
xhr.open('get','http://shuai.com/demo.php?username="apassword="123"',true);
// 3. 处理xhr响应
xhr.onload = function(){
console.log(xhr.response);
}
// 4. 发送xhr请求
xhr.send(null);
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 AJAX 跨域请求资源的方式
php如何设置允许跨域请求?
在php文件头部加入header("Access-Control-Allow-Origin: *");
如果想设置只允许某个网站通过的话可以这样设置header("Access-Control-Allow-Origin: http://test.com"); // 只允许test.com发起的跨域请求,其他的都不通过
<!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-GET-CORS</title>
</head>
<body>
<button>跨域请求CORS</button>
<script>
// cors: 跨域资源共享
// 同源策略: 为请求的安全,浏览器禁止通过脚本发起一个跨域的请求
// 只允许通过脚本发起基于同源的请求
// 同源指: 协议相同,域名/主机名相同,端口相同
// http://www.abc.com http
// https://www.abc.com https
// 协议不同
// https://www.a.com
// https://www.b.com
// 主机不同
// https://a.cn:8080
// https://a.cn:9090
// 端口不同
const btn = document.querySelector("button");
btn.onclick = (ev) => {
// 1. xhr对象
const xhr = new XMLHttpRequest();
// 2. 配置xhr, 跨域请求
xhr.open("get", "http://world.io/cors1.php");
// 3. 处理xhr响应
xhr.onload = () => console.log(xhr.response);
// 4. 发送xhr请求
xhr.send(null);
};
</script>
</body>
</html>
// header('Access-Control-Allow-Origin: http://hello.io');
header('Access-Control-Allow-Origin: *');
echo 'CORS: 跨域请求成功';
JavaScript实战案例
新闻选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新闻选项卡</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
a {
text-decoration: none;
color: #555;
}
a:hover {
text-decoration: underline;
color: red;
}
li {
list-style: none;
line-height: 1.6em;
}
li:hover {
cursor: default;
}
.tabs {
width: 330px;
height: 300px;
margin: 30px auto;
background-color: #e6e6e6;
display: flex;
flex-direction: column;
}
.tab {
height: 36px;
display: flex;
}
.tab li {
flex: auto;
text-align: center;
line-height: 36px;
background-color: #fff;
}
.tab li.active {
background-color: #e6e6e6;
border-bottom: 2px solid orange;
}
.tab li:hover {
cursor: pointer;
}
/* 默认所有选项卡只有一个显示,其它隐藏 */
.item {
padding: 20px;
display: none;
}
.item li {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-bottom: 16px;
}
.item.active {
display: block;
}
</style>
</head>
<body>
<div class="tabs">
<!-- 导航 -->
<ul class="tab">
<li data-index="1" class="active">省内新闻</li>
<li data-index="2">国内新闻</li>
<li data-index="3">国际新闻</li>
</ul>
<!-- 与导航标签页对应的详情列表 -->
<ul class="item active" data-index="1">
<li>
<a href="">数百只东方白鹳飞临安徽省合肥市巢湖花塘湖湿地</a>
</li>
<li>
<a href="">数百只东方白鹳飞临安徽省合肥市巢湖花塘湖湿地</a>
</li>
<li>
<a href="">数百只东方白鹳飞临安徽省合肥市巢湖花塘湖湿地</a>
</li>
<li>
<a href="">数百只东方白鹳飞临安徽省合肥市巢湖花塘湖湿地</a>
</li>
<li>
<a href="">数百只东方白鹳飞临安徽省合肥市巢湖花塘湖湿地</a>
</li>
</ul>
<ul class="item" data-index="2">
<li>
<a href="">寻亲行动继续!已为51位烈士找到亲人</a>
</li>
<li>
<a href="">寻亲行动继续!已为51位烈士找到亲人</a>
</li>
<li>
<a href="">寻亲行动继续!已为51位烈士找到亲人</a>
</li>
<li>
<a href="">寻亲行动继续!已为51位烈士找到亲人</a>
</li>
<li>
<a href="">寻亲行动继续!已为51位烈士找到亲人</a>
</li>
</ul>
<ul class="item" data-index="3">
<li>
<a href="">“感谢中国”成网络热词 中国疫苗在埃塞俄比亚有多受欢迎?</a>
</li>
<li>
<a href="">“感谢中国”成网络热词 中国疫苗在埃塞俄比亚有多受欢迎?</a>
</li>
<li>
<a href="">“感谢中国”成网络热词 中国疫苗在埃塞俄比亚有多受欢迎?</a>
</li>
<li>
<a href="">“感谢中国”成网络热词 中国疫苗在埃塞俄比亚有多受欢迎?</a>
</li>
<li>
<a href="">“感谢中国”成网络热词 中国疫苗在埃塞俄比亚有多受欢迎?</a>
</li>
</ul>
</div>
<script>
const tab = document.querySelector(".tab");
const items = document.querySelectorAll('.item');
tab.onclick = function(ev) {
// 事件触发者
console.log(ev.target);
// 1. 清空之前的激活样式,并将当前的导航设置为激活状态
[...tab.children].forEach(item => {
item.classList.remove('active');
})
ev.target.classList.add('active');
// 2.根据data-index来确定应该将哪个列表进行激活并显示
[...items].forEach(item => {
item.classList.remove('active');
});
[...items].filter(item => item.dataset.index === ev.target.dataset.index)[0].classList.add('active')
}
</script>
</body>
</html>
效果图:
百度一键换肤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>一键换肤</title>
<style>
body {
background-image: url(https://dss0.bdstatic.com/l4oZeXSm1A5BphGlnYG/skin/755.jpg?2);
}
.box {
width: 800px;
height: 300px;
background-color: white;
margin: 60px auto;
padding: 30px;
border-radius: 20px;
overflow: hidden;
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 3px;
}
.box img {
width: 100%;
height: 100%;
cursor: pointer;
}
.box img:first-child {
grid-area: 1/1/span 2/span 2;
}
.box img:last-child {
grid-area: 2/4/span 2/span 2;
}
</style>
</head>
<body>
<div class="box">
<img src="https://dss3.bdstatic.com/iPoZeXSm1A5BphGlnYG/skin/750.jpg?2" alt="">
<img src="https://dss0.bdstatic.com/l4oZeXSm1A5BphGlnYG/skin/755.jpg?2" alt="">
<img src="https://dss2.bdstatic.com/lfoZeXSm1A5BphGlnYG/skin/757.jpg?2" alt="">
<img src="https://dss0.bdstatic.com/k4oZeXSm1A5BphGlnYG/skin/759.jpg?2" alt="">
<img src="https://dss2.bdstatic.com/lfoZeXSm1A5BphGlnYG/skin/749.jpg?2" alt="">
<img src="https://dss3.bdstatic.com/lPoZeXSm1A5BphGlnYG/skin/74.jpg?2" alt="">
<img src="https://dss0.bdstatic.com/k4oZeXSm1A5BphGlnYG/skin/71.jpg?2" alt="">
<img src="https://dss2.bdstatic.com/lfoZeXSm1A5BphGlnYG/skin/29.jpg?2" alt="">
<img src="https://dss2.bdstatic.com/kfoZeXSm1A5BphGlnYG/skin/65.jpg?2" alt="">
<img src="https://dss3.bdstatic.com/lPoZeXSm1A5BphGlnYG/skin/258.jpg?2" alt="">
<img src="https://dss3.bdstatic.com/iPoZeXSm1A5BphGlnYG/skin/278.jpg?2" alt="">
<img src="https://dss0.bdstatic.com/k4oZeXSm1A5BphGlnYG/skin/447.jpg?2" alt="">
</div>
<script>
document.querySelector('.box').onclick = (ev) => {
document.body.style.backgroundImage = `url(${ev.target.src})`
}
</script>
</body>
</html>
效果图: