javascript(4)-数据操作

242 阅读4分钟

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:请求已完成,表示响应已就绪。
  • 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.18080是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不容易做到的。

流程:

  1. 编写一个带参JS函数,参数列表负责接收响应回来的JSON数据,名随意。
  2. 编写一个json文件,文件名随意,在数据外层包裹一层函数,格式为 函数名(数据列表),该函数名要和JS函数名一致。
  3. 利用 <script>src 属性访问json文件,并使用查询串的方式,将JS函数名发送到服务端或本地json文件,查询串的key值随意。
  4. 服务端将数据返回到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"})