从零开始学习前端JAVASCRIPT — 14闭包与继承

Posted 大仲马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从零开始学习前端JAVASCRIPT — 14闭包与继承相关的知识,希望对你有一定的参考价值。

(注:本章讲解涉及部分后端知识,将以php提供数据的方式进行相应的demo实现)

一、ajax的概念

全称:Asynchronous javascript And Xml

AJAX不是一种新的编程语言,而是一种用于创建更快更好以及交互性更强的WEB应用程序技术,该技术在98年前后得到了应用。通过AJAX,你的JS可以通过JS的XMLHttpRequest对象在页面不重载的情况下与服务器直接进行通信。这样可以在服务器请求到想要的数据,而不是整个页面。AJAX的核心就是JS的XMLHttpRequest对象。xhr对象是在IE5中首次引入,它是一种支持异步请求的对象。

二、ajax的优势

  • 无刷新更新数据。
  • 异步与服务器通信。
  • 基于标准被广泛支持。
  • 前端与后端分离。
  • 节省带宽。

三、编写步骤

1.创建XMLHttpRequest对象。

所有现代浏览器(IE7+,chrome,firefox,opera,safari)均内建XMLHttpRequest对象。但是IE5、6使用ActiveXObject对象。

function getAjax() {

var  xmlhttp = null;

if(window.ActiveXObject){

   //针对IE

         xmlhttp = new ActiveXObject(’Microsoft.XMLHTTP’);

} else if(window.XMLHttpRequest){

         xmlhttp = new XMLHttpRequest();

}

return  xmlhttp;

}

2.打开与Server的连接,指定发送方式、URL以及权限等。

open方法:创建新的HTTP请求,并指定此请求的方法,URL以及验证信息。

xhr.open(type, url, async, user, password);

type:HTTP请求方式,GET、POST等。大小写不敏感。

url:请求地址。(get请求如果有传值直接以url?param=value的方式传递。post的方式直接在发送指令的时候传递)

async:布尔型,请求是否为异步方式。默认为true。如果为真,当状态改变时会调用onreadystatechange属性指定的回调函数。(可选)

注释:当您使用 async=false 时,请不要编写 onreadystatechange 函数 - 把代码放到 send() 语句后面即可:

xmlhttp.open("GET","test.txt",false);
xmlhttp.send();
document.getElementById("myDiv").innerhtml=xmlhttp.responseText;

     user:如果服务器需要验证,此处指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。少用仅了解

password:验证信息中的密码部分,如果用户名为空,则此值将会被忽略。(少用仅了解)

注:在AJAX中,其实我们就是来模拟正常的表单提交数据。正常的表单在POST数据时,会发送Content-Type字段,所以我们在AJAX中就要指定该字段值为application/x-www-form-urlencoded。并且对字段名称和值进行编码处理在发送。使用setRequestHeader:单独指定请求的某个HTTP头。

注:一些特殊字符可能与代码中的字符冲突(如URL中分隔符&等等),故数据应使用encocdeURIComponent()函数进行编码。

3.发送指令。

send():发送请求到HTTP服务器并接收回应。

此方法的同步或异步方式取决于open方法中的async参数,如果async为true,此方法将立即返回,如果为false,此方法将会等待请求完成或者超时时才会返回。

xhr.send(body);

body:通过此请求发送的数据。GET请求设置为null即可。

post和get方式实现ajax的不同之处 

xmlhttp.open("GET","demo_get2.asp?fname=Bill&lname=Gates",true);
xmlhttp.send();

xmlhttp.open("POST","ajax_test.asp",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Bill&lname=Gates");

//传参方式的不同以及编码方式的不同post提交需要被别,则需要指定编码方式与get的方式一样

   4.等待并接收服务器返回的处理结果。

5.客户端接收。

6.释放XMLHttpRequest对象。

四、回调函数

通过onreadystatechange属性指定readystate属性改变时的事件处理回调函数。

xhr.onreadystatechange = function(){}

readyState属性:返回请求的当前状态。

  • 0:对象已建立,尚未初始化(未调用open方法)。
  • 1:对象已建立,尚未调用send方法。
  • 2:send方法已调用。但是当前的状态以及HTTP状态未知。
  • 3:开始接收数据,因为响应以及HTTP头不全,这时通过responseBody和responseText获取部分数据会出现错误。
  • 4:数据接收完毕,此时可以通过responseBody和responseText获取完整的响应数据。

status属性:返回当前请求的状态码。

  • 200 OK:请求文档已经找到,并正确返回。
  • 304 Not Modified:拥有一个本地的缓存副本,服务器端内容与此相同。
  • 403 Forbidden:请求者对所请求的文档不具有相应的权限。
  • 404 Not Found:请求的文档没找到。

statusText属性:返回当前请求的响应行信息。

responseXML属性:将响应信息格式化为XML Document对象返回。

responseText属性:将响应信息作为字符串返回。

 

五、JS解析JSON 

 JSON:Javascript Object Notation,一种轻量级的基于文本的数据交换格式,易于人阅读和编写,也能提高网络传输速率。

 ES5新增的两个方法:

 JSON.parse:将JSON字符串数据转换为JSON对象。

 JSON.stringify:将JSON对象转换为JSON字符串。

 注:1、浏览器支持:IE8+。

  2、JSON格式的字符串里面的key或者字符串型的value都必须用双引号包裹

六、局部数据刷新 

demo讲解上述提到的知识点:操作相应的DOM节点(例如评论列表的分页效果)

html页面

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新闻列表</title>
    <style type="text/css">
        *{
            margin:0;
            padding:0;
        }
        .box{
            width: 80%;
            margin: 0 auto;
        }
        .newsTitle{
            font-size: 24px;
            text-align: center;
            margin: 0 auto;
            padding: 20px 10px;
            font-weight: normal;
            letter-spacing: 10px;
        }
        .newsList{
            display: block;
            margin: 0 auto;
            line-height: 50px;
            font-size: 16px;
            list-style: none;
        }
        .newsList li{
            border-top: 1px dashed #f4f4f4;
            padding: 0 20px;
        }
        .newsList li:nth-child(odd){
            background: #f3f3f3;
        }
        .newsPage{
            display: block;
            margin: 0 auto;
            text-align: center;
        }
        .newsPage li{
            margin:20px 5px;
            display: inline-block;
            padding: 5px  10px;
            border:1px solid #f3f3f3;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="box">
        <h3 class="newsTitle">新闻列表</h3>
        <ul id="newsList" class="newsList">
            <li>东航首位外籍女机长:来中国是最好的选择</li>
            <li>东航首位外籍女机长:来中国是最好的选择</li>
            <li>东航首位外籍女机长:来中国是最好的选择</li>
            <li>东航首位外籍女机长:来中国是最好的选择</li>
            <li>东航首位外籍女机长:来中国是最好的选择</li>
        </ul>    
        <ul id="newsPage" class="newsPage">
            <li data-page="1">1</li>
            <li data-page="2">2</li>
            <li data-page="3">3</li>
            <li data-page="4">4</li>
            <li data-page="5">5</li>
            <li data-page="6">6</li>
            <li data-page="7">7</li>
            <li data-page="8">8</li>
            <li data-page="9">9</li>
            <li data-page="10">10</li>
        </ul>        
    </div>
</body>
<script type="text/javascript" src="ajax.js"></script>
</html>

 js页面

var oNewsPage=document.getElementById(\'newsPage\');
var oNewsPage=Array.from(oNewsPage.children);
var oNewsList=document.getElementById(\'newsList\');

oNewsPage.forEach(function (value) {
    value.onclick=function () {
        oNewsList.innerHTML = "";
        //获取页码值
        var pageNum = value.getAttribute("data-page");

        /*步骤一:创建XMLHttpRequest对象*/
        var xhr = new XMLHttpRequest();

        /*步骤二:请求配置*/
        var pageNum = "pageNum="+ pageNum;
        //xhr.open(\'get\',\'ajax.php?\'+pageNum,true);
        xhr.open(\'post\',\'ajax.php\',true);

        /*步骤四:接受返回结果*/
        xhr.onreadystatechange=function () {
            //根据状态返回码判定请求的状态
            if (xhr.readyState === 4 && xhr.status === 200) {
                //获取返回结果
                var newsList = JSON.parse(xhr.responseText)//返回结果通过json将字符串进行转换
                //数据结果渲染到页面
                newsList.forEach( v => {
                    var oLi = document.createElement(\'li\');
                    oLi.innerHTML = v.title;
                    oNewsList.appendChild(oLi);
                });
            }
        }

        /*步骤三:发送请求*/
        //post请求需要设置编码格式  否则无法解析数据
        xhr.setRequestHeader(\'Content-Type\', \'application/x-www-form-urlencoded\');
        xhr.send(pageNum);//post方式将参数传递的方式
    }
})

 php后台页面

<?php
    $pageNum=$_POST[\'pageNum\']; //接收参数页码
    //通过页码判断加载的内容
    if ($pageNum == 1) {
        //通过二维数组存储数据
        $arr = [
            [
                \'id\' => 1,
                \'title\' => \'东航首位外籍女机长:来中国是最好的选择\'
            ],
            [
                \'id\' => 2,
                \'title\' => \'南航首位外籍女机长:来中国是最好的选择\'
            ],
            [
                \'id\' => 3,
                \'title\' => \'国际航空首位外籍女机长:来中国是最好的选择\'
            ]
        ];        
    }
    else if ($pageNum == 2) {
        $arr=[
            [
                \'id\' =>4,
                \'title\'=>\'世界那么大不如出去走走\'
            ],
            [
                \'id\'=>5,
                \'title\'=>\'今天阳光明媚适合出去走走\'
            ]
        ];
    }
    else{        
        $arr=[
            [
                \'id\' =>6,
                \'title\'=>\'我是第三页以后的内容\'
            ],
            [
                \'id\'=>7,
                \'title\'=>\'我是第三页以后的内容\'
            ]
        ];
    }
    echo json_encode($arr);
?>

七、前后端分离(ajax函数的封装)

 后台只管数据输出和业务逻辑处理,前端负责交互逻辑和界面展示。简单的说:前端静态页面中没有有后台程序代码,后台输出不带有HTML标签的数据。前后端分离靠ajax来实现数据的交互。

demo通过封装的ajax实现加载更多的功能以及通过事件源对象删除单条数据(本来打算将源码托管到GitHub,账号丢失)

*文件夹目录 

 1.html页面

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新闻列表</title>
    <link rel="stylesheet" href="styles/ajax.css">
</head>
<body>
    <div class="box">
        <h3 class="newsTitle">新闻列表</h3>
        <ul id="newsList" class="newsList">
            <li>
                冬天来了,春天还会远么 
                <a class="deleteBtn" href="#">&times;</a>
            </li>
            <li>
                面朝大海,幸福花开 
                <a class="deleteBtn" href="#">&times;</a>
            </li>
            <li>
                Nothing is impossible! 
                <a class="deleteBtn" href="#">&times;</a>
            </li>
            <li>
                水能载舟亦能覆舟 
                <a class="deleteBtn" href="#">&times;</a>
            </li>
            <li>
                中国是最好的选择 
                <a class="deleteBtn" href="#">&times;</a>
            </li>
        </ul>    
        <div id="loadMoreInfo" class="loadMoreInfo">
            <img id="loadingImg" class="loading" src="images/timg.gif" />
            加载更多...
        </div>    
    </div>
</body>
<script type="text/javascript" src="scripts/common.js"></script>
<script type="text/javascript" src="scripts/ajax.js"></script>
</html>
ajax.html

 2.css文件

@charset "utf-8";
/* CSS Document */
*{
    margin:0;
    padding:0;
}
body{
    background: #7CCD7C;
}
.box{
    width: 80%;
    margin: 0 auto;
}
.newsTitle{
    font-size: 24px;
    text-align: center;
    margin: 0 auto;
    padding: 20px 10px;
    font-weight: normal;
    letter-spacing: 10px;
}
.newsList{
    display: block;
    margin: 0 auto;
    line-height: 50px;
    font-size: 16px;
    list-style: none;
}
.newsList li{
    padding: 0 20px;
    box-shadow: 0 0 10px #eeeeee;
}
.box .newsList li:hover{
    background: #B0E2FF;
}
.newsList li:nth-child(odd){
    background: #f3f3f3;
}
.newsList li:nth-child(even){
    background: #eeeeee;
}

.deleteBtn{
    float: right;
    text-decoration: none;
    font-size: 16px;
    color: #555555;
}
.loadMoreInfo{
    margin-top: 10px;
    text-align: center;
    line-height: 50px;
    font-size: 16px;
    background: #ffffff;
    cursor: pointer;
    vertical-align: middle;
    margin-bottom: 20px;
}
.loadMoreInfo img{
    display: none;
    width: 20px;
    height: 20px;
    vertical-align: middle;
}
ajax.css

 3.公共js(封装的$函数以及ajax函数)

/* 
封装$函数
参数说明:
id:标签的id属性值
*/
function $(id) {
    return document.getElementById(id);
}

/*
封装ajax函数
参数说明:对象作为参数不用考虑参数顺序问题
type:请求类型;
url:请求访问地址;
param:请求数据,支持对象也支持字符串;
asyn:是否异步加载,boolean类型,true异步,false同步
beforesend:回调函数在发送请求之前执行
success:回调函数,请求成功时执行
complete:回调函数,请求完成后执行
*/
function ajax({type,url,param,asyn=true,beforesend,success,complete}) {
    //创建XMLHttpRequest对象
    var xhr = new XMLHttpRequest();
    //param参数为对象时进行拼接字符串
    if (param && typeof(param) === \'object\') {
        var str;
        for(var child in param){
            //encodeURIComponent编码参数,避免特殊字符分割时丢失
            str+=encodeURIComponent(child) + \'=\' + encodeURIComponent(param[child]) + \'&\'
        }
        param=str.slice(0,-1);//截取拼接完成后最后的&符
    }
    //get请求对url传参进行拼接
    if (type.toUpperCase()==="GET" && param) {
        url+=\'?\'+param;
    }
    //请求配置
    xhr.open(type , url, asyn);
    //获取返回的数据
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4 && xhr.status === 200) {
            //获取返回的数据并转换
            success(xhr.responseText);
        }
        //请求完成后的函数
        complete && complete();
    }
    //发送请求
    beforesend && beforesend();
    if (type.toUpperCase()==="POST") {
        //post请求设置编码方式
        xhr.setRequestHeader("Content-Type",\'application/x-www-form-urlencoded\')
        //post请求时通过send向body传参(无论param参数是否为空,必须传)
        xhr.send(param);
    }
    else{
        //get请求发送请求
        xhr.send();
    }
}
common.js

 4.页面js

var oLoadMoreInfo = $("loadMoreInfo");
var oNewsList = $("newsList");
var oLoadingImg = $("loadingImg");
oLoadMoreInfo.onclick=function () {
    ajax({
        type:\'post\',
        url:\'php/ajax.php\',
        beforesend:function () {
            //发送前显示加载过程中的动态效果
            oLoadingImg.style.display="inline-block"
        },
        success:function (data) {
            //接受返回的数据进行转换并渲染到页面
            var data=JSON.parse(data);
            data.forEach(function (value) {
                var li=document.createElement("li");
                li.innerHTML=value+\'<a class="deleteBtn" href="#">&times;</a>\';
                oNewsList.appendChild(li);
            })
        },
        //完成后显示渲染出来的网页效果,关闭等待效果
        complete:function () {
            oLoadingImg.style.display="none"
        }
    })
}
newsList.onclick=function (ev) {
    var e=ev||window.event;
    //获取事件原对象
    var tar=e.target||e.srcElement;
    //判断事件原对象是否为a标签nodenName的值都是大写
    if (tar.nodeName==="A") {
        oNewsList.removeChild(tar.parentNode);
    }
}
ajax.js

 5.php后台

<?php
  sleep(2);//本地测试资源加载速度过快无法看出加载的动态效果
  $news=[
      \'东航首位外籍女机长:来中国是最好的选择\',
      \'南航首位外籍女机长:来中国是最好的选择\',
      \'国际航空首位外籍女机长:来中国是最好的选择\',
      \'东航首位外籍女机长:来中国是最好的选择\',
      \'南航首位外籍女机长:来中国是最好的选择\',
      \'国际航空首位外籍女机长:来中国是最好的选择\',
      \'东航首位外籍女机长:来中国是最好的选择\',
      \'南航首位外籍女机长:来中国是最好的选择\',
      \'国际航空首位外籍女机长:来中国是最好的选择\',
      \'东航首位外籍女机长:来中国是最好的选择\',
      \'南航首位外籍女机长:来中国是最好的选择\',
      \'国际航空首位外籍女机长:来中国是最好的选择\'
  ];
  echo json_encode($news, JSON_UNESCAPED_UNICODE);
  /*  PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, 类似”\\u***”的格式,PHP5.4,JSON_UNESCAPED_UNICODE:Json不要编码Unicode*/
ajax.php

 6.图片资源

 

八、ajax的依赖调用

在使用ajax异步调用的时候,可能碰到同时调用多个ajax的情况,而且多个ajax之间还存在依赖关系。

引用回调函数的嵌套说明ajax的以来调用: 

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调函数的嵌套</title>
</head>
<body>
    
</body>
<script type="text/javascript">
    function a(d, e) {
        d && d(e);
    }

    function b(f) {
        console.log(\'函数b!从零开始学习前端JAVASCRIPT — 5JavaScript基础BOM

从零开始学习前端JAVASCRIPT — 1JavaScript基础

从零开始学习前端JAVASCRIPT — 1JavaScript基础

从零开始学习前端JAVASCRIPT — 6JavaScript基础DOM

从零开始学习前端JAVASCRIPT — 7JavaScript基础EVENT

从零开始学习前端JAVASCRIPT — 5JavaScript基础ES5