AJAX

原创 2017年09月13日 11:14:28

准备知识

在学习AJAX前,我们先了解一下JSON和XML

JSON

定义

JSON(JavaScript Object Notation, JS对象标记),是一种轻量级的数据交换格式。

它基于 ECMAScript (w3c制定的JS规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

JSON对象和JSON字符串

我们知道python中有一个json模块,通过json.dumps()方法,我们可以将python中的基本数据类型序列化为一种标准格式的字符串,进而可以存储或通过网络传输;通过json.loads()方法,又可以将这些标准格式的字符串反序列化为原数据类型。这种标准格式的字符串就是JSON字符串,

JSON对象是JS对象的子集,它包含JS中的6种数据类型:number, string, Boolean, array, null, object。也就是JSON对象一定是JS对象。注意,JS可以接受单引号,双引号的string类型,但是JSON中只有双引号的string。

JSON字符串的格式很简单,将JSON对象加一对单引号' '包起来就是JSON字符串,比如:JS数字1 转为JSON字符串是’1’ ,JS对象{"name": "Seb"}转换为JSON字符串是’{“name”: “Seb”}` 。注意,对于JS中的单引号string,它会将其转换为双引号string,然后再用单引号包起来。比如:JS字符串'cat'"cat"转换为JSON字符串都是'"cat"'

在JS中,通过JSON.stringify()方法,可以将JSON对象转化为JSON字符串;通过JSON.parse()方法,可以将JSON字符串转化为JSON对象。

XML

XML(extensible markup language, 可扩展标记语言)也是一种数据交换的格式,它比JSON出现的更早,它的格式类似于HTML的标签。

图片1

对比JSON:
这里写图片描述

对比可知,同样的信息,JSON所用的字符要比XML少很多,因而在网络传输方面更具优势。目前,JSON已经成为各大网站交换数据的标准格式。

AJAX

AJAX(Asynchronous JavaScript And XML),异步JS和XML,即使用JS语言与服务器进行异步交互,传输数据格式为XML(不过目前JSON格式已经在大部分领域取代了XML)。AJAX除了支持异步交互,另一个特点就是浏览器页面的局部刷新,由于不需要重载整个页面,不仅提高了性能,还提升了用户体验。

比如,我们平常网站登录或则注册,对于我们输入内容的验证,就是基于AJAX技术,给服务器发送用户输入的数据,服务器将验证的结果用JSON格式的字符串发回响应,前端用JS来解析JSON数据,如果有错误信息,就通过JS在页面添加错误提示;如果验证通过,就跳转至首页。

这里写图片描述

AJAX是基于JS的一门技术,不过JS的语法比较繁琐,而且还要处理不同浏览器的兼容问题,因此,一般我们通过JQuery使用AJAX,JQuery语法简洁,而且解决了浏览器兼容问题。想了解更多JQuery知识,可以参考我的另一篇博文

Ajax的jQuery实现:

下面我们看一下,通过jQuery发送ajax请求的基本形式:
前端:

<form action="{% url 'login' %}" method="post">
    <div class="form-group">
        <label for="username">用户名</label>
        <input type="text" class="form-control" id="username" name="username" required>
    </div>
    <div class="form-group">
        <label for="password">密码</label>
        <input type="password" class="form-control" id="password" name="password" required>
    </div>
    <p>
    <button type="submit" class="btn btn-primary btn-block">登录</button>
    </p>
</form>

<script>
    // 点击提交按钮,ajax发送;验证成功,通过location.href = url来跳转
    $('form').submit(function(e){
        e.preventDefault();  //阻止默认提交
        var username = $("[name='username']").val(); // 注意,jquery筛选一定加引号,否则报错uncaught
        var password = $("[name='password']").val();
        $.ajax({
            url: "{% url 'login' %}",
            type: "POST",
            data: {
                "username": username,
                "password": password,
            },
            success: function(res) {  // res是server端发来json字符串响应
                response = JSON.parse(res); //将json字符串解析为json对象(即JS对象)
                if (response['errors']) { //在页面上显示错误信息
                    $('#error').html(response['errors']);
                    } else {
                        location.href = "/index/";  //跳转至首页
                    }
</script>

后端:

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password') 
        //如果前端发来的data中key对应的value是列表,要用getlist(key)来获取
        ajax_response = {'user': None, "errors": ""}
        if username == 'egon' and password == '123':
            ajax_response['user']='egon'
        else:
            ajax_response['errors']='用户名或密码错误'
        return HttpResponse(json.dumps(ajax_response))
    if request.method == 'GET':
        return render(request, 'login.html')

通过jQuery发送ajax请求的几个基本参数:
url, 请求的地址
type, 请求的方法:默认是get
data, 请求要携带的数据,是一个json的object对象,类似python中的字典
基本流程:1. ajax发送请求 2. server接收响应 3. server处理数据 4. server返回响应 5. ajax接收响应
如果以上都顺利进行(server返回200 ok 状态码),就会执行success参数对应的函数。可选的还有error, server端错误时执行的函数; complete, 无论是否错误,都执行complete对应的函数; statusCode, 根据状态码执行不同的函数,比如:statusCode: {'403': function(){}, '401': function(){}}
其它参数:
processData, 声明当前的data数据是否进行转码或预处理,默认为true,即预处理
contentType, 发送信息至服务器时内容编码类型,默认值: “application/x-www-form-urlencoded”。
traditional, 一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:[“x”,”y”]}, traditional为false会对数据进行深层次迭代;

ajax的JS实现

XMLHttpRequest

ajax的所有操作都是基于XMLHttpRequest对象,用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

创建XMLHttpRequest 对象

var xmlHttp = new XMLHttpRequest();

所有的现代浏览器都内建了XMLHttpRequest 对象,但是IE7以前的版本有所不同。为了照顾浏览器的兼容性问题,可以用以下方式来创建XMLHttpRequest对象:
方式一:判断浏览器是否支持XMLHttpRequest 对象

var xmlhttp;
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }

方式二:基于异常捕捉的方式

function createXMLHttpRequest() {
        var xmlHttp;
        // 适用于大多数浏览器,以及IE7和IE更高版本
        try{
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            // 适用于IE6
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                // 适用于IE5.5,以及IE更早版本
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){}
            }
        }            
        return xmlHttp;
    }

使用流程

建立连接

var url = “/ajax_handler”;
var params = “lorem=ipsum&name=binny”;

open(method, url, async):

var xmlHttp = createXMLHttpRequest();
xmlHttp.open("GET", url+"?"+params, true); 

method请求方法,GET/POST;url, 请求的服务端路径;async参数可以不给,默认是true,执行异步请求

发送请求

xmlHttp.send(null);

对于GET方式来说,没有请求体,参数是放在在url的”?”后面,即查询字符串;出于兼容性考虑,如果send()方法没有参数,建议给出null。对于POST方式,参数要放在send()方法中,这个下面再说。

接收响应

onreadystatechange 事件
该事件在XMLHttpRequest对象的状态发生变化时被调用。XMLHttpRequest有五种状态:
- 0:创建了XMLHttpRequest对象;
- 1:open()方法建立连接;
- 2:send()方法发送数据;
- 3:读取服务器响应开始;
- 4:读取服务器响应结束;
事件会在状态1 - 4 时触发:
readyState属性,获取对象状态
该属性用来获取XMLHttpRequest对象的状态,下面的alert会执行4次,并显示每次的状态:

xmlHttp.onreadystatechange = function() {
            alert(xmlHttp.readyState);
        };

status属性,获取响应状态码
服务器响应状态码如果是200,表示请求被成功处理,这通常也是我们所关心的。通过XMLHttpRequest对象的status属性,可以获取服务器的状态码
responseText属性,获取响应内容

xmlHttp.onreadystatechange = function() {
            if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                alert(xmlHttp.responseText);    
            }
        };

在XMLHttpRequest中使用POST方法

不同于GET方式,POST请求时,没有查询字符串,参数放到send()方法内,也就是请求体。
而且,需要设置请求头:

var url = "/ajax_handler";
var params = "lorem=ipsum&name=binny";

var xmlHttp = new XMLHttpRequest();
xmlHttp .open("POST", url, true);

//设置请求头 setRequestHeader(key, value)
xmlHttp .setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 注意 :form表单会默认"Content-type"键值对不设定,会导致Web服务器忽略请求体的内容,因此必须加上上面这行
// 表示客户端提交给服务器文本内容的编码方式是URL编码,即除了标准字符外,每字节以双字节16进制前加个“%”表示
xmlHttp .setRequestHeader("Content-length", params.length);
xmlHttp .setRequestHeader("Connection", "close");

xmlHttp .send(params);

xmlHttp .onreadystatechange = function() {
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
}

为什么要设置请求头

因为客户端与服务端的通信使用HTTP协议,HTTP协议规定,客户端发出的请求,必须有请求头,用来告诉
服务器客户端要的资源及相关的参数。XMLHttpRequest对象遵循HTTP协议,因此需要发送请求头给服务器。
但是 XMLHttpRequest默认的情况下有些参数可能没有说明在HTTP头里,比如提交form表单时,是没有”Content-type”这个键和值的。因此我们需要通过XMLHttpRequest提供的setRequestHeader 方法,来手动添加。

发送二进制数据

{% extends 'base.html' %}
{% load staticfiles %}
/* 如果不加这个,下面的staic报错 */

{% block title %}注册{% endblock %}

<style>
    .reg-button {
        margin-top: 20px;
    }
</style>

{% block page_content %}
    <div class="page-header">
        <h1>Register</h1>
    </div>
    <div class="col-md-4">
        <!-- 注册表单 开始 -->
        <form action="{% url 'register' %}" method="post" id="register">
            {% csrf_token %}
            <div class="form-group">
                <label for="id_email">邮箱&nbsp;</label><span class="error-info"></span>
                {{ form_obj.email }}
<!--  span 标签用于放置错误信息 -->
            </div>

            <div class="form-group">
                <label for="id_username">用户名&nbsp;</label><span class="error-info"></span>
                {{ form_obj.username }}
            </div>

            <div class="form-group">
                <label for="id_password">密码&nbsp;</label><span class="error-info"></span>
                {{ form_obj.password }}
            </div>

             <div class="form-group">
                <label for="id_password2">确认密码&nbsp;</label><span class="error-info"></span>
                 {{ form_obj.password2 }}
            </div>

            <div class="form-group file-avatar">
                <label for="file-img">头像</label>
                <img src="{% static 'img/default.jpg' %}" alt="" id="file-img" class="sol">
                <input type="file" id='file-choose' class="sol">
            </div>
<!--   通过绝对定位并设置宽高,令 上传按钮和图片重合,然后设置按钮透明度 -->
            <div class="form-group">
                <label for="id_valid_code" class="valid_code">验证码&nbsp;</label><span class="error-info"></span>
                <div class="row">
                    <div class="col-md-6">
                        {{ form_obj.valid_code }}
                    </div>
                    <div class="col-md-6 valid_code">
                        <img src="/valid_code" alt="valid_code">&nbsp;<a class="refresh">刷新</a>
                    </div>
                </div>
            </div>

            <p class="reg-button">
                <button type="submit" class="btn btn-primary btn-block">
                    注册
                </button>
            </p>
        </form>
        <!-- 注册表单 结束 -->
    </div>
{% endblock %}

{% block script %}
    <script>

     // 显示头像预览,在用户本地实现:拿到头像DOM对象 - - 转化为路径
        // - - 利用FileReader文件阅读器;
        // 利用onchange事件,每次用户重新选择了文件,改变预览
        $('#file-choose').change(function() {
            var reader = new FileReader(); //实例化对象
            var first_file = $(this)[0].files[0]; //$(this)0那个JQ对象集合的具体对象,files[0]取到DOM对象 ----拿到文件对象
            reader.readAsDataURL(first_file); //文件对象转化为路径对象

            reader.onload=function(){
                $("#file-img")[0].src = this.result //这里的this是reader对象
            }
        });


    $("#register").submit(function(e){
        e.preventDefault();
        var email = $("#id_email").val();
        var username = $("#id_username").val();
        var password = $("#id_password").val();
        var password2 = $("#id_password2").val();
        var valid_code = $('#id_valid_code').val();
        console.log(email, username, password, password2, valid_code);

        //ajax上传二进制文件:FormData  HTML5 的文件上传
        var formdata = new FormData(); //实例化对象
        formdata.append("email", email); //添加数据
        formdata.append("username", username); //添加数据
        formdata.append("password", password); //添加数据
        formdata.append("password2", password2); //添加数据
        formdata.append("valid_code", valid_code); //添加数据
        formdata.append("img", $("#file-choose")[0].files[0]); //添加数据
        formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); //添加数据


        //发送数据:
        $.ajax({
            url: "{% url 'register' %}",
            type: "POST",
            data: formdata, //发送上面的对象
            processData: false, //告诉jQuery不要处理发送的数据
            contentType: false, //告诉jQuery不要去设置Content-Type请求头
            success: function (res) {
                res = JSON.parse(res);
                if (res['user']){
{#                if (res){#}
                    location.href = "{% url 'login' %}";
                } else { //显示错误信息
                    console.log(res['errors']);
                    var errors_dict = res['errors'];
                    for (var i in errors_dict) {    //千万不要使用 for( var i, j in dict)这种形式来循环字典,不支持!!!
                        if (i =='valid_code') {
                            $('label.valid_code').next().text(errors_dict[i][0])
                        } else if (i=="__all__") { //全局的错误,额外处理
                            $("#id_password2").prev().text(errors_dict[i][0])
                        } else {
                            $("#id_"+i).prev().text(errors_dict[i][0]);
                        //因为form_obj表单对象渲染的元素有id属性:id="id_fieldname"
                        }
                    }
                    //设置定时清除
                    setTimeout(function () {
                        $("span.error-info").text("");
                    },3000);

                // 更新验证码,选中验证码dom对象,重新赋值
                    $(".valid_code img")[0].src += "?";
                }
            }
        });
    });

    $(".refresh").click(function () {
        $("div.valid_code img")[0].src+="?";
    })

    </script>
{% endblock %}






版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

基于http的在线版日期计算器+云笔记

1、HTTP概念超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。1、http的请求报文格式2...

Java之多线程编程核心技术的6点整理(一)

开心一笑【服务员来个西红柿炒鸡蛋,服务员:没有西红柿了。 那来一个白菜炖豆腐,服务员:没有豆腐了…… 那好,来个鸡蛋炒白菜。 服务员:好的,您稍等,菜马上好!】提出问题java多线程编程核心技术...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

我也来谈谈分布式并行计算---------one

今天中午回学校食堂吃饭,女朋友问我分布式并行计算式什么?说下背景,女朋友考上研究生现在正在选导师。我就给她举了个例子,比如一个大规模的问题,一台计算机计算需要一个月,现在分解成30个可以同时进行的子问...

云计算的核心技术

云计算是一种以数据和处理能力为中心的密集型计算模式,它融合了多项ICT技术,是传统技术“平滑演进”的产物。其中以虚拟化技术、分布式数据存储技术、编程模型、大规模数据管理技术、分布式资源管理、信息安全、...

科普:并行计算、分布式计算、集群计算和云计算

1. 并行计算(Parallel Computing)     并行计算或称平行计算是相对于串行计算来说的。并行计算(Parallel Computing)是指同时使用多种计算资源解决计算问题的过程...

Java 多线程编程核心技术--第一章

进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在...

分布式计算、并行计算及集群、网格、云计算的区别

转自: http://blog.163.com/litianyichuanqi@126/blog/static/1159794412012387453794/ 并行计算:并行计算是相对于...

用 JSON 来避免中文乱码问题

问题来源 第一步 深坑 迷茫后的光芒 如何解决 光明 总结问题来源最近在用别人提供的 API 搞事情(用姓名和身份证号查准考证号), 用 Postman 进行测试,提交的是表单里面含有中文。具体如下图...

IP地址分类与子网掩码

IP 地址与子网掩码点分十进制数表示的IPv4地址被分为几类,以适应大型、中型、小型的网络。这些类的不同之处在于不同类别的网络地址所占位数。
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)