zoukankan      html  css  js  c++  java
  • 深入浅出解析AJAX

    AJAX完全依赖于XMLHttpRequest对象

    GET请求

            // 创建xhr对象
            var xhr = new XMLHttpRequest();
            // 监听xhr对象
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
                        console.log(xhr.responseText);
                    }
                }
            }
            
            xhr.open("get", URL)
            xhr.send(null)

    这里监听要写在send之前,先监听后向服务器发起请求,相反如果请求发出在监听则本末倒置,即便在开发上并无区别。

    xhr对象一旦开始open,就有了readyState属性,readyState属性一旦发生改变,就能够触发onreadystatechange事件,所以要先监听,这也是所有轮子的标准模板。

    在open时http请求并没有发出,直到send后才会发出。

    readyState 状态

    0: 请求未初始化

    1: 服务器连接已建立

    2: 请求已接收

    3: 请求处理中

    4: 请求已完成,且响应已就绪

    我们只会关心就绪状态为4时

    浏览器执行到Ajax代码,发出了一个HTTP请求,欲请求服务器上的数据服务器的此时开始I/O,所谓的I/O就是磁盘读取,需要花一些时间,所以不会立即产生下行HTTP报文。

    由于Ajax是异步的,所以本地的JavaScript程序不会停止运行,页面不会假死,不会傻等下行HTTP报文的出现。后面的JavaScript语句将继续运行。进程不阻塞。

    服务器I/O结束,将下行HTTP报文发送到本地。

    如果时post请求必须手动设置请求头,模拟form表单提交

            xhr.open("post", URL)
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.send("name=" + encodeURIComponent("夏彬"))

    这里尽量将中文转译,防止服务器错乱,后台程序语言,都能够自动处理转译。

    每个XMLHttpRequest对象只能监听一条HTTP请求,直到这条请求结束,才能发起下一条,强行发起上一条请求会被注销。

    因为同源策略所以XMLHttpRequest对象是不能跨域的,我们可以使用JSONP来跨域,JSON+Padding,用一种逆思维来跨域

    fun({
        "result" : [
            {
                "name" : "小明",
                "age" : 12,
                "sex" : "男"
            },
            {
                "name" : "小红",
                "age" : 13,
                "sex" : "女"
            },
            {
                "name" : "小绿",
                "age" : 16,
                "sex" : "女"
            }
        ]
    });
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            function fun(data) {
                console.log(data)
            }
        </script>
        <script src="jsonp.txt"></script>
    </body>
    
    </html>

    我们可以将JSONP封装为轮子以达到正向编程的目的

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            jsonp('jsonp.txt', "name=xiabin", "fun", function(data) {
                console.log(data)
            })
    
            function jsonp(URL, queryString, callbackName, callback) {
                // 将JSONP定义函数绑定到window上
                window[callbackName] = callback;
                var dom = document.createElement('script');
                dom.src = queryString ? URL + "?m=" + Math.random() + "&" + queryString : URL + "?m=" + Math.random();
                document.body.appendChild(dom)
                document.body.removeChild(dom);
            }
        </script>
    </body>
    
    </html>

    当然如果一些数据不同源,且返回的不是JSONP数据,那么我们仍然可以使用服务器语言进行偷数据,现在很多网站都防偷。。。

    例如:PHP中

    <?php
        header("Content-Type:text/json;charset=gb2312");
        $phone = $_GET["phone"];
        $a = file_get_contents("http://chongzhi.jd.com/json/order/search_searchPhone.action?mobile=".$phone);
        print_r($a);
    ?>

     例:AJAX实现瀑布流两种算法

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            body {
                background-color: #ccc;
            }
            
            .waterfall {
                 790px;
                margin: 0 auto;
                position: relative;
            }
            
            .grid {
                position: absolute;
                 230px;
                background-color: white;
                padding: 10px;
                border-radius: 15px;
            }
            
            .grid img {
                 230px;
            }
            
            .grid .title {
                font-weight: bold;
                font-size: 18px;
                line-height: 32px;
            }
            
            .grid .neirong {
                line-height: 150%;
                font-size: 14px;
                margin-bottom: 20px;
            }
            
            .grid .zuozhe {
                float: right;
                color: orange;
                font-size: 12px;
            }
            
            .loading {
                margin: 0 auto;
                 400px;
                line-height: 30px;
                text-align: center;
                font-size: 14px;
                background-color: gold;
                color: white;
            }
        </style>
    </head>
    
    <body>
        <div class="waterfall" id="waterfall">
    
        </div>
        <div class="loading">
            正在加载...
        </div>
    
        <script type="text/template" id="grid_template">
            <div class="grid">
                <img src="<%=imgurl%>" alt="" />
                <p class="title">
                    <%=title%>
                </p>
                <p class="neirong">
                    <%=content%>
                </p>
                <p class="zuozhe">
                    <%=author%>
                </p>
            </div>
        </script>
        <script src="js/jquery-1.12.3.min.js"></script>
        <script src="js/underscore.js"></script>
        <script>
            var container = document.getElementById("waterfall");
            var templateStr = document.getElementById("grid_template").innerHTML;
            var $loading = $(".loading");
    
            // 生成数据绑定函数
            var template = _.template(templateStr);
            gotoPage(1)
                // AJAX数据请求函数
            function gotoPage(num) {
                $loading.hide();
                $.get("json/json" + num + ".txt", function(data) {
                    data = JSON.parse(data);
                    // 没有数据则直接退出
                    console.log(data.news)
                    if (data.news.length == 0) {
                        $loading.show().html("没有更多了");
                        return;
                    }
                    _.each(data.news, function(dictionary) {
                        var IMG = new Image();
                        IMG.src = dictionary.imgurl;
                        // 那张图先加载完渲染那张
                        $(IMG).load(function() {
                            var templateStr = template(dictionary);
                            var $grid = $(templateStr);
                            var top = 0;
                            $(container).append($grid);
                            // 计算位置
                            for (var i = $grid.index() - 3; i >= 0; i -= 3) {
                                top += $(".grid").eq(i).outerHeight() + 20;
                            }
                            $grid.css({
                                "left": $grid.index() % 3 * 270,
                                "top": top
                            })
                            $(container).height($(document).height())
                            $loading.hide();
                        })
                    })
                    lock = true;
                })
            }
            var lock = true;
            // 页面滚动加载流
            var page = 0;
            $(window).scroll(function() {
                if (!lock) return;
                var ratio = $(window).scrollTop() / ($(document).height() - $(window).height());
                if (ratio > 0.7) {
                    lock = false;
                    page++
                    gotoPage(page)
                }
            })
        </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>Document</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            body {
                background-color: #ccc;
            }
            
            .waterfall {
                 790px;
                margin: 0 auto;
                position: relative;
            }
            
            .grid {
                position: absolute;
                 230px;
                background-color: white;
                padding: 10px;
                border-radius: 15px;
            }
            
            .grid img {
                 230px;
            }
            
            .grid .title {
                font-weight: bold;
                font-size: 18px;
                line-height: 32px;
            }
            
            .grid .neirong {
                line-height: 150%;
                font-size: 14px;
                margin-bottom: 20px;
            }
            
            .grid .zuozhe {
                float: right;
                color: orange;
                font-size: 12px;
            }
            
            .loading {
                margin: 0 auto;
                 400px;
                line-height: 30px;
                text-align: center;
                font-size: 14px;
                background-color: gold;
                color: white;
            }
        </style>
    </head>
    
    <body>
        <div class="waterfall" id="waterfall">
    
        </div>
        <div class="loading">
            正在加载...
        </div>
    
        <script type="text/template" id="grid_template">
            <div class="grid">
                <img src="<%=imgurl%>" alt="" />
                <p class="title">
                    <%=title%>
                </p>
                <p class="neirong">
                    <%=content%>
                </p>
                <p class="zuozhe">
                    <%=author%>
                </p>
            </div>
        </script>
        <script src="js/jquery-1.12.3.min.js"></script>
        <script src="js/underscore.js"></script>
        <script>
            var container = document.getElementById("waterfall");
            var templateStr = document.getElementById("grid_template").innerHTML;
            var $loading = $(".loading");
    
            // 生成数据绑定函数
            var template = _.template(templateStr);
            // 位置数组
            var positionArr = [0, 0, 0];
            gotoPage(1)
                // AJAX数据请求函数
            function gotoPage(num) {
                $loading.hide();
                $.get("json/json" + num + ".txt", function(data) {
                    data = JSON.parse(data);
                    // 没有数据则直接退出
                    console.log(data.news)
                    if (data.news.length == 0) {
                        $loading.show().html("没有更多了");
                        return;
                    }
                    _.each(data.news, function(dictionary) {
                        var IMG = new Image();
                        IMG.src = dictionary.imgurl;
                        // 那张图先加载完渲染那张
                        $(IMG).load(function() {
                            var templateStr = template(dictionary);
                            var $grid = $(templateStr);
                            var minValue = _.min(positionArr);
                            var index = _.indexOf(positionArr, minValue);
                            $(container).append($grid);
                            $grid.css({
                                "left": index * 270,
                                "top": minValue,
                            })
                            positionArr[index] += $grid.innerHeight() + 20;
                            $(container).height($(document).height())
                            $loading.hide();
                        })
                    })
                    lock = true;
                })
            }
            var lock = true;
            // 页面滚动加载流
            var page = 0;
            $(window).scroll(function() {
                if (!lock) return;
                var ratio = $(window).scrollTop() / ($(document).height() - $(window).height());
                if (ratio > 0.7) {
                    lock = false;
                    page++
                    gotoPage(page)
                }
            })
        </script>
    </body>
    
    </html>

     百度招聘分页查询

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>Document</title>
        <style type="text/css">
            * {
                margin: 0;
                padding: 0;
            }
            
            body {
                background-color: #ccc;
            }
            
            .content {
                background-color: white;
                 1100px;
                margin: 0 auto;
                font-size: 12px;
                padding: 20px;
            }
            
            .content .jobtable {
                position: relative;
            }
            
            .content .row {
                overflow: hidden;
                line-height: 40px;
                position: relative;
            }
            
            .content .hd {
                font-weight: bold;
            }
            
            .content .row .cols {
                overflow: hidden;
                position: relative;
                border-bottom: 1px solid #ccc;
            }
            
            .content .row .col {
                float: left;
            }
            
            .content .row .col1 {
                 30%;
            }
            
            .content .row .col2 {
                 15%;
            }
            
            .content .row .col3 {
                 20%;
            }
            
            .content .row .col4 {
                 20%;
            }
            
            .content .row .col3 {
                 15%;
            }
            
            .content .info {
                overflow: hidden;
                font-size: 16px;
                line-height: 32px;
            }
            
            .content .info h3 {
                float: left;
            }
            
            .content .info p {
                float: right;
            }
            
            .content .row_btn {
                position: absolute;
                 21px;
                height: 10px;
                background-color: red;
                right: 10px;
                top: 50%;
                margin-top: -5px;
                background: url(images/banner-icon.png) -28px -146px;
                cursor: pointer;
            }
            
            .content .row_btn.up {
                background-position: -2px -145px;
            }
            
            .content .detail {
                display: none;
                border-bottom: 1px solid #ccc;
            }
            
            .content .pageNav {
                margin-top: 10px;
                 259px;
                margin: 20px auto;
            }
            
            .content .pageNav ul {
                list-style: none;
                overflow: hidden;
            }
            
            .content .pageNav ul li {
                float: left;
                 30px;
                height: 30px;
                line-height: 30px;
                text-align: center;
                margin-right: 5px;
                cursor: pointer;
                border: 1px solid #ccc;
            }
            
            .content .pageNav ul li.cur {
                background-color: yellowgreen;
            }
            
            .mask {
                position: absolute;
                top: 0;
                left: 0;
                 100%;
                height: 100%;
                background: url(images/busy.gif) no-repeat center center;
                z-index: 999;
                display: none;
            }
        </style>
    </head>
    
    <body>
        <div class="content">
            <div class="info">
                <h3>职位信息</h3>
                <p>一共有444个职位</p>
            </div>
            <div class="jobtable" id="jobtable">
                <div class="mask"></div>
                <div class="row hd">
                    <div class="cols">
                        <div class="col col1">职位名称</div>
                        <div class="col col2">职位类别</div>
                        <div class="col col3">工作地点</div>
                        <div class="col col4">招聘人数</div>
                        <div class="col col5">更新时间</div>
                    </div>
                </div>
            </div>
            <div class="pageNav">
                <ul>
                    <li class="cur"></li>
                    <li></li>
                    <li></li>
                    <li></li>
                    <li></li>
                    <li></li>
                    <li></li>
                </ul>
            </div>
        </div>
    
        <script type="text/template" id="row_template">
            <div class="row">
                <div class="cols">
                    <div class="col col1">
                        <a href='<%=link%>'>
                            <%=name%>
                        </a>
                    </div>
                    <div class="col col2">
                        <%=postType%>
                    </div>
                    <div class="col col3">
                        <%=workPlace%>
                    </div>
                    <div class="col col4">
                        <%=recruitNum%>
                    </div>
                    <div class="col col5">
                        <%=publishDate%>
                    </div>
                    <div class="row_btn"></div>
                </div>
                <div class="detail">
                    <div className="serviceCondition">
                        <h5>入职资格: </h5>
                        <%=serviceCondition%>
                    </div>
                    <div className="workContent">
                        <h5>工作内容: </h5>
                        <%=workContent%>
                    </div>
                </div>
            </div>
        </script>
    
        <script type="text/javascript" src="js/jquery-1.12.3.min.js"></script>
        <script type="text/javascript" src="js/underscore.js"></script>
        <script>
            // 生成数据绑定函数
            var templateDataFun = _.template($("#row_template").html());
    
            // 设置截流开关
            var lock = true;
    
            // 封装tabRow类
            function RowCell(dictionary) {
                this.dictionary = dictionary;
                // 修正数据对象
                this.dictionary.link = "http://talent.baidu.com/external/baidu/index.html#/jobDetail/2/" + this.dictionary.postId;
                // 绑定DOM元素
                this.$rowDom = $(templateDataFun(dictionary));
                this.$btn = this.$rowDom.find(".row_btn");
                this.$detail = this.$rowDom.find(".detail");
                // 详情页开关状态
                this.state = 0;
                this.bindEvent();
                this.render();
                // 将每个实例存放入rowList管理
                rowList.addRow(this);
    
            }
            // 渲染方法
            RowCell.prototype.render = function() {
                rowList.$dom.append(this.$rowDom)
            };
            // 给按钮绑定事件
            RowCell.prototype.bindEvent = function() {
                var self = this;
    
                // 点击事件
                this.$btn.click(function() {
                    if (self.state == 0) {
                        self.$btn.addClass("up");
                        self.$detail.stop(true).slideDown();
                        self.state = 1;
                    } else {
                        self.$btn.removeClass("up");
                        self.$detail.stop(true).slideUp();
                        self.state = 0;
                    }
                })
            };
            // 清理DOM
            RowCell.prototype.kill = function() {
                this.$rowDom.remove();
            };
            // 封装rowTable类作为中介者
            function RowTable() {
                this.$dom = $("#jobtable")
                this.rowArr = [];
                this.navPage = new NavPage();
                // 获取当前页面hash值
                if (window.location.hash == "") {
                    window.location.hash = 1;
                }
                var pageNum = window.location.hash.substring(1);
                this.getPage(pageNum);
            };
            // 向服务器发起数据请求
            RowTable.prototype.getPage = function(num) {
                lock = false;
                var self = this;
                $.get("JSON/getPostList" + num, function(data) {
                    data = JSON.parse(data);
                    self.navPage.upDate(num, data.totalPage);
                    // 先清理
                    _.each(self.rowArr, function(v) {
                            v.kill();
                        })
                        // 后渲染
                    _.each(data.postList, function(v, i) {
                        new RowCell(v)
                    });
                    lock = true;
                })
    
            };
            // 添加实例到数组
            RowTable.prototype.addRow = function(obj) {
                this.rowArr.push(obj);
            }
    
    
    
            // 分页导航类
            function NavPage(currentPage, totalPage) {
                this.currentPage = currentPage;
                this.totalPage = totalPage;
                this.$pageList = $(".pageNav li");
                this.render();
                this.bindEvent();
            }
    
            // 分页导航渲染
            NavPage.prototype.render = function() {
                if (this.currentPage < 4) {
                    this.$pageList.eq(0).html(1);
                    this.$pageList.eq(1).html(2);
                    this.$pageList.eq(2).html(3);
                    this.$pageList.eq(3).html(4);
                    this.$pageList.eq(4).html("...");
                    this.$pageList.eq(5).html(this.totalPage - 1);
                    this.$pageList.eq(6).html(this.totalPage);
                    this.$pageList.eq(this.currentPage - 1).addClass("cur").siblings().removeClass("cur");
                } else if (this.currentPage > this.totalPage - 3) {
                    this.$pageList.eq(0).html(1);
                    this.$pageList.eq(1).html(2);
                    this.$pageList.eq(2).html("...");
                    this.$pageList.eq(3).html(this.totalPage - 3);
                    this.$pageList.eq(4).html(this.totalPage - 2);
                    this.$pageList.eq(5).html(this.totalPage - 1);
                    this.$pageList.eq(6).html(this.totalPage);
                    this.$pageList.eq(this.currentPage - this.totalPage - 1).addClass("cur").siblings().removeClass("cur");
    
                } else {
                    this.$pageList.eq(0).html(1);
                    this.$pageList.eq(1).html("...");
                    this.$pageList.eq(2).html(this.currentPage - 1);
                    this.$pageList.eq(3).html(this.currentPage);
                    this.$pageList.eq(4).html(this.currentPage + 1);
                    this.$pageList.eq(5).html("...");
                    this.$pageList.eq(6).html(this.totalPage);
                    this.$pageList.eq(3).addClass("cur").siblings().removeClass("cur");
                }
    
            }
    
            // 分页导航更新
            NavPage.prototype.upDate = function(currentPage, totalPage) {
                this.currentPage = currentPage;
                this.totalPage = totalPage;
                this.render();
            }
    
            // 分页导航事件绑定
            NavPage.prototype.bindEvent = function() {
                var self = this;
                this.$pageList.click(function() {
                    if (!lock) return;
                    if ($(this).html() == "...") return;
                    window.location.hash = $(this).html();
                    self.currentPage = parseInt($(this).html());
                    self.render();
                    rowList.getPage(self.currentPage);
                })
            }
    
            var rowList = new RowTable();
        </script>
    </body>
    
    </html>
  • 相关阅读:
    W3C help
    css值解析
    css中的格式上下文Formatting Context
    css中绝对定位中的left和top属性
    事件模型
    程序员应该如何更有效率
    css的边偏移距离
    css插入框
    css中的whitespace属性
    源码安装nginx 方法二
  • 原文地址:https://www.cnblogs.com/tengx/p/12419461.html
Copyright © 2011-2022 走看看