1. 数据存储
概念: 利用JS在客户端存储数据(限定为string类型)有三种办法:
- cookie:cookie存储的数据在同一域名下共享,默认是Session级别的存储,即随浏览器关闭而死亡,一个浏览器最多创建300个cookie,且每个cookie大小不能超过4KB,具体视浏览器而定,cookie存储方便,但不安全且占用带宽:
document.cookie="k=v":使用键值对存值,同名覆盖。document.cookie="k=v;expires=eDay":expires可以指定过期日期,-1表示立即失效。document.cookie:返回由;拼接的客户端所有cookie的字符串。
- sessionStorage:H5新特性,有兼容问题,默认是Session级别的存储,即随浏览器关闭而死亡,解决了cookie存储空间不足的问题:
sessionStorage.setItem("k", "v"):使用键值对存值,同名覆盖。sessionStorage.getItem("k"):根据key来取出对应的value。sessionStorage.removeItem("k"):根据key来删除对应的数据。sessionStorage.clear():清空sessionStorage中的所有值。
- localStorage:将数据直接存储到本地,最大支持5M,其余和sessionStorage几乎一致。
谷歌浏览器的Cookie可以在
F12-Application-Cookies中点击查看,若不支持本地测试Cookie,可以换成IE或者FF来测试。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="test-cookie" type="button">测试cookie</button>
<br/>
<button id="set-cookie" type="button">测试setCookie()</button>
<br/>
<button id="get-cookie" type="button">测试getCookie()</button>
<br/>
<button id="delete-cookie" type="button">测试delCookie()</button>
<br/>
<script type="text/javascript">
window.onload = () => {
document.querySelector("#test-cookie").onclick = () => {
document.cookie = "a=1";
document.cookie = "a=2";
document.cookie = "b=3";
console.log(document.cookie);
};
document.querySelector("#set-cookie").onclick = () => {
setCookie("a", "1");
setCookie("b", "2", 1);
setCookie("b", "3", 4);
setCookie("c", "4", -1);
console.log(document.cookie);
};
document.querySelector("#get-cookie").onclick = () => {
setCookie("user", "joe");
console.log(getCookie("user"));
console.log(getCookie("username"));
};
document.querySelector("#delete-cookie").onclick = () => {
setCookie("user", "joe");
console.log(getCookie("user"));
delCookie("user");
console.log(getCookie("user"));
};
};
//存值 :键值对的方法 和过期时间
function setCookie(key, value, eDay = 1) {
let now = new Date();
//当前日期和输入的天数
let new_data = now.getDate() + eDay;
now.setDate(new_data);
//存入 输入的值和过期时间
document.cookie = `${key}=${value};expires=${now}`;
}
//取值
function getCookie(key) {
let result = null;
//存入数组并用分号空格分离开来
let cookies = document.cookie.split("; ");
//循环数组的值
for (let i = 0, j = cookies.length; i < j; i++) {
//如果输入的值和已存在的值一样用=号连接
let kvs = cookies[i].split("=");
if (kvs[0] === key) {
result = kvs[1];
break;
}
}
return result;
}
//删除值
function delCookie(key) {
//如果存在就删除
if (getCookie(key)) {
setCookie(key, "", -1);
}
}
</script>
</body>
</html>
案例:七天免密
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<section>
<form id="login-form" action="http://www.baidu.com" method="get">
<label>
<input id="username-ipt" name="username"/>
</label>
<label>
<input id="password-ipt" name="password" type="password"/>
</label>
<label>
<input id="no-password-cbx" type="checkbox"/>七天免密
</label>
<button id="login-btn" type="button">登录</button>
</form>
</section>
<script type="text/javascript">
/* 需求:以帐号以 admin/123 为例:
1. 当第一次使用 admin/123 进行登录时:
- 如果不勾选[7天免密],直接跳入主页面,cookie中不会记录任何信息。
- 如果勾选了[7天免密],将帐号密码存入cookie中,并设置7天后过期。
2. 当我在该 admin/123 过期前(7天内),再次登录时:
- 帐号框键入admin之后,密码框自动注入123,[7天免密]自动勾选。
- 帐号框键入admin之后,手动取消了勾选[7天免密],则admin/123将从cookie中被移除。
*/
window.onload = () => {
let usernameIpt = document.querySelector("#username-ipt");
let passwordIpt = document.querySelector("#password-ipt");
let noPasswordCbx = document.querySelector("#no-password-cbx");
let loginBtn = document.querySelector("#login-btn");
let loginForm = document.querySelector("#login-form");
loginBtn.onclick = () => {
//如果选中了点击框 用checked
if (noPasswordCbx.checked) {
//选中后存所有值
setCookie(usernameIpt["value"], passwordIpt["value"], 7);
} else {
//没选中就删除当前存在的值
delCookie(usernameIpt["value"]);
}
//手动提交表单
loginForm.submit();
};
//当文本框丧失焦点时触发的事件。
//账号框丧失焦点后
usernameIpt.onblur = () => {
//账号登录过输入,第二次输入账号就会自动获取密码
let passwordFromCookie = getCookie(usernameIpt["value"]);
if (passwordFromCookie) {
//密码的值和账号如果匹配上
passwordIpt["value"] = passwordFromCookie;
//选中
noPasswordCbx.checked = "checked";
}
}
};
//存值 :键值对的方法 和过期时间
function setCookie(key, value, eDay = 1) {
let now = new Date();
//当前日期和输入的天数
let new_data = now.getDate() + eDay;
now.setDate(new_data);
//存入 输入的值和过期时间
document.cookie = `${key}=${value};expires=${now}`;
}
//取值
function getCookie(key) {
let result = null;
//存入数组并用分号空格分离开来
let cookies = document.cookie.split("; ");
//循环数组的值
for (let i = 0, j = cookies.length; i < j; i++) {
//如果输入的值和已存在的值一样用=号连接
let kvs = cookies[i].split("=");
if (kvs[0] === key) {
result = kvs[1];
break;
}
}
return result;
}
//删除值
function delCookie(key) {
//如果存在就删除
if (getCookie(key)) {
setCookie(key, "", -1);
}
}
</script>
</body>
</html>
sessionStorage代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="set-item-btn" type="button">sessionStorage存值</button>
<br/>
<script type="text/javascript">
/*需求:在session-storage-a.html中利用SessionStorage存值,并跳入session-storage-b.html页面。*/
window.onload = () => {
document.querySelector("#set-item-btn").onclick = () => {
if (!sessionStorage) {
alert("浏览器不支持sessionStorage!");
return false;
}
let strData = "纯字符串数据!";
let jsonData = {"name": "赵四", "age": 58};
sessionStorage.setItem("strData", strData);
sessionStorage.setItem("jsonData", JSON.stringify(jsonData));
location.href = "session-storage-b.html";
}
};
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
/*需求:将session-storage-a.html中在sessionStorage中存储的数据全部取出。*/
window.onload = () => {
if (!sessionStorage) {
alert("浏览器不支持sessionStorage!");
return false;
}
let strData = sessionStorage.getItem("strData");
console.log(strData);
sessionStorage.removeItem("strData");
strData = sessionStorage.getItem("strData");
console.log(strData);
let jsonData = sessionStorage.getItem("jsonData");
console.log(JSON.parse(jsonData));
sessionStorage.clear();
jsonData = sessionStorage.getItem("jsonData");
console.log(JSON.parse(jsonData));
};
</script>
</body>
</html>
2. AJAX
概念: AJAX(Asynchronous Javascript And XML),即异步的JS和XML组合技术,以异步的方式和服务器通信(交换数据),可以产生局部刷新页面数据的效果:
new XMLHttpRequest():创建AJAX核心对象,负责与服务器通信:new ActiveXobject('Microsoft.xmlHTTP'):IE7以下兼容写法。
xhr.onreadystatechange = () => {}:当请求状态码发生改变时触发:- 若使用此事件监听,则必须写于
open()之前,否则失效。
- 若使用此事件监听,则必须写于
xhr.readyState:请求状态码,初始状态为0,表示请求代理被创建,但尚未调用open():- 1:通信通道建立成功,即
open()已被成功调用。 - 2:请求已被服务器接收,即
send()已被成功调用,此时头部和状态信息均可获得。 - 3:请求处理中,此时
responseText属性已经包含部分数据。 - 4:请求已完成,表示响应已就绪。
- 1:通信通道建立成功,即
xhr.status:响应状态码,其中只有200表示响应成功。xhr.responseText:获取文本类型的响应内容。xhr.responseXML:获取XML类型的响应内容。xhr.open(type, url, async):建立通信通道,需指定请求方式,目标地址和是否异步。xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"):POST请求需要在open()之后,send()之前设置此请求头内容类型,GET请求不需要。xhr.send(data):发送请求,POST请求数据在此传递,GET请求数据使用url查询串传递。- url后面使用
?传值 都属于get请求,?后面的键值对 叫做查询串
AJAX不支持直接本地文件的读取,测试时请将所有文件都拷贝到
tomcat根目录/webapps/root中,并启动tomcat服务器。
ajax:tomcat用法
把主网页和测试网页放到Webapps>ROOT
然后回到BIN里打开startup.ba如果关闭点击shutdown.bat
然后网页打开127.0.0.1:8080是ajax端口号 连接 `/` 和主网页名字
如果没错误response :"这是显示的是测试网页代码说明开启成功"
ajax核心对象
<button id="xhr-test" type="button">ajax核心对象</button>
<script type="text/javascript">
window.onload = () => {
document.querySelector("#xhr-test").onclick = () => {
let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject('Microsoft.xmlHTTP');
console.log(xhr);
};
</script>
ajax发送get请求
<button id="get-ajax" type="button">ajax发送get请求</button>
<script type="text/javascript">
document.querySelector("#get-ajax").onclick = () => {
getAjax({
//url后面使用`?`传值 都属于get请求,`?`后面的键值对 叫做查询串
"url": "ajax-test.html?username=admin&password=123"
});
};
/* 需求:封装一个 `getAjax()`,负责利用AJAX发送GET请求(使用查询串进行传值),参数是一个json数据。
url:AJAX请求目标地址,必写。
type:AJAX发送请求的方式,默认为 `GET`。
async:AJAX是否开启异步,默认为异步 `true`。
*/
function getAjax(params) {
let url = params["url"];
if (!url) {
alert("参数url不能为空!");
return;
}
let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject('Microsoft.xmlHTTP');
let type = params["type"] ? params["type"].toUpperCase() : "GET";
let async = params["async"] ? params["async"] : true;
xhr.onreadystatechange = () => {
if (xhr.readyState === 1) console.log("1:通信通道建立成功,即 open() 已被成功调用...");
if (xhr.readyState === 2) console.log("2:请求已被服务器接收,即 send() 已被成功调用,此时头部和状态信息均可获得...");
if (xhr.readyState === 3) console.log("3:请求处理中,此时 `responseText` 属性已经包含部分数据...");
if (xhr.readyState === 4) console.log("4:请求已完成,表示响应已就绪...");
if (xhr.readyState === 4 && xhr.status === 200) {
console.log("200:响应成功");
console.log(xhr.responseText);
}
};
if ("GET" === type) {
xhr.open(type, url, async);
xhr.send();
}
}
</script>
ajax发送post请求
<button id="post-ajax" type="button">ajax发送post请求</button>
<script type="text/javascript">
document.querySelector("#post-ajax").onclick = () => {
postAjax({
"url": "ajax-test.html",
"data": {"username": "joe", "password": "456"},
"type": "post"
});
};
/* 需求:封装一个 `postAjax()`,负责利用AJAX发送POST请求(使用data传值),参数是一个json数据。
url:AJAX请求目标地址,必写。
type:AJAX发送请求的方式,默认为 `GET`。
data:POST方式使用JSON类型的 `data` 传值。
async:AJAX是否开启异步,默认为异步 `true`。
*/
function postAjax(params) {
let url = params["url"];
if (!url) {
alert("参数url不能为空!");
return;
}
let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject('Microsoft.xmlHTTP');
let type = params["type"] ? params["type"].toUpperCase() : "GET";
let async = params["async"] ? params["async"] : true;
xhr.onreadystatechange = () => {
if (xhr.readyState === 1) console.log("1:通信通道建立成功,即 open() 已被成功调用...");
if (xhr.readyState === 2) console.log("2:请求已被服务器接收,即 send() 已被成功调用,此时头部和状态信息均可获得...");
if (xhr.readyState === 3) console.log("3:请求处理中,此时 `responseText` 属性已经包含部分数据...");
if (xhr.readyState === 4) console.log("4:请求已完成,表示响应已就绪...");
if (xhr.readyState === 4 && xhr.status === 200) {
console.log("200:响应成功");
console.log(xhr.responseText);
}
};
if ("POST" === type) {
xhr.open(type, url, async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params["data"]);
}
}
</script>
ajax()测试
<button id="ajax" type="button">ajax()测试</button>
<script type="text/javascript">
document.querySelector("#ajax").onclick = () => {
ajax({
"url": "ajax-test.html",
"type": "get",
"data": {"username": "joe", "password": "456"},
"success": response => {
console.log(response);
}
});
};
/* 需求:封装一个 `ajax()`,负责利用AJAX发送请求,参数是一个json数据。
url:AJAX请求目标地址,必写。
type:AJAX发送请求的方式,默认为 `GET`。
async:AJAX是否开启异步,默认为异步 `true`,改为 `false` 则表示同步。
data:POST方式使用JSON类型的 `data` 传值,GET方式使用查询串进行传值。
dataType:表示本次请求允许接受的响应类型。
success:回调函数,ajax帮我们调用的一个函数,函数的第一个参数中包含了响应的数据。
*/
function ajax(params) {
let url = params["url"];
if (!url) {
alert("参数url不能为空!");
return;
}
let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject('Microsoft.xmlHTTP');
let type = params["type"] ? params["type"].toUpperCase() : "GET";
let async = params["async"] ? params["async"] : true;
let dataType = params["dataType"] ? params["dataType"].toUpperCase() : "TEXT";
let success = params["success"] ? params["success"] : null;
xhr.onreadystatechange = () => {
if (xhr.readyState === 1) console.log("1:通信通道建立成功,即 open() 已被成功调用...");
if (xhr.readyState === 2) console.log("2:请求已被服务器接收,即 send() 已被成功调用,此时头部和状态信息均可获得...");
if (xhr.readyState === 3) console.log("3:请求处理中,此时 `responseText` 属性已经包含部分数据...");
if (xhr.readyState === 4) console.log("4:请求已完成,表示响应已就绪...");
if (xhr.readyState === 4 && xhr.status === 200) {
console.log("200:响应成功...");
if ("TEXT" === dataType && success) {
success(xhr.responseText);
return;
}
if ("XML" === dataType && success) {
success(xhr.responseXML);
}
}
};
if ("GET" === type) {
xhr.open(type, url, async);
xhr.send();
} else {
xhr.open(type, url, async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params["data"]);
}
}
</script>
封装ajax.js
/*
url:AJAX请求目标地址,必写。
type:AJAX发送请求的方式,默认为 `GET`。
async:AJAX是否开启异步,默认为异步 `true`,改为 `false` 则表示同步。
data:POST方式使用JSON类型的 `data` 传值,GET方式使用查询串进行传值。
dataType:表示本次请求允许接受的响应类型。
success:回调函数,ajax帮我们调用的一个函数,函数的第一个参数中包含了响应的数据。
*/
function ajax(params) {
let url = params["url"];
if (!url) {
alert("参数url不能为空!");
return;
}
let xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject('Microsoft.xmlHTTP');
let type = params["type"] ? params["type"].toUpperCase() : "GET";
let async = params["async"] ? params["async"] : true;
let dataType = params["dataType"] ? params["dataType"].toUpperCase() : "TEXT";
let success = params["success"] ? params["success"] : null;
xhr.onreadystatechange = () => {
if (xhr.readyState === 1) console.log("1:通信通道建立成功,即 open() 已被成功调用...");
if (xhr.readyState === 2) console.log("2:请求已被服务器接收,即 send() 已被成功调用,此时头部和状态信息均可获得...");
if (xhr.readyState === 3) console.log("3:请求处理中,此时 `responseText` 属性已经包含部分数据...");
if (xhr.readyState === 4) console.log("4:请求已完成,表示响应已就绪...");
if (xhr.readyState === 4 && xhr.status === 200) {
console.log("200:响应成功...");
if ("TEXT" === dataType && success) {
success(xhr.responseText);
} else if ("XML" === dataType && success) {
success(xhr.responseXML);
}
}
};
if ("GET" === type) {
xhr.open(type, url, async);
xhr.send();
} else {
xhr.open(type, url, async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params["data"]);
}
}
8. JSONP
概念: JSONP是一种数据调用的方式,允许跨域访问本地的JSON数据(允许但不建议使用其他类型的数据),这是ajax不容易做到的。
流程:
- 编写一个带参JS函数,参数列表负责接收响应回来的JSON数据,名随意。
- 编写一个json文件,文件名随意,在数据外层包裹一层函数,格式为
函数名(数据列表),该函数名要和JS函数名一致。 - 利用
<script>的src属性访问json文件,并使用查询串的方式,将JS函数名发送到服务端或本地json文件,查询串的key值随意。 - 服务端将数据返回到JS函数的参数列表中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
function getUser(jsonDataA, jsonDataB) {
console.log(jsonDataA);
console.log(jsonDataB);
}
</script>
<script type="text/javascript" src="jsonp.json?callback=getUser"></script>
</body>
</html>
getUser({"name": "tom"},{"name": "jerry"})