• day058 ajax,介绍及其使用场景,操作示例


    本节内容:

    1、Ajax简介
    2、基于jQuery的ajax实现
    3、案例
    4、请求头ContentType(看完后,看后面的文件上传实例来看)
    5、文件上传
    

    一、Ajax简介

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。
    即使用Javascript语言与服务器进行异步交互,
    传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
    
    同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
    异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
    

    1、ajax的优点

    1、ajax使用Javascript技术向服务器发送异步请求(异步)
    2、可以局部刷新(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
    (实际上是:偷偷的发送请求,偷偷的响应,通过绑定事件及限定范围的刷新)
    

    2、应用场景:注册时输入用户名,光标移动就会验证,提示用户

    二、基于jQuery的ajax实现

    1、ajax的请求流程

    第一步:绑定一个事件,触发ajax,ajax请求将相关数据发送到服务器
    第二步:服务器根据url找到对应的视图函数,执行后返回结果给回调函数
    第三步:回调函数执行逻辑后,将最终结果返回给前端(浏览器)
    

    2、ajax示例,携带参数,input计算及发送json数据

    views.py文件示例

    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    
    import time
    import json
    from django.http import JsonResponse # 使用自带的json类,就不用我们手动json
    
    def index(request):
        #time.sleep(5)
    
        return render(request,"index.html")
    
    def ajax_handle(request):
        # time.sleep(5)
        return HttpResponse("Yuan!")
    
    def ajax_handle2(request):
        print(request.POST)
        print(request.GET)
        return HttpResponse("data has received!")
    
    def cal(request):
        res={"state":1000,"data":None,"msg":None}
        try:
            num1 = request.POST.get("num1") # 拿到前端发送的数字进行计算
            num2 = request.POST.get("num2")
            ret = str(int(num1)+int(num2))
            res["data"]=ret  # 修改数据,将计算的结果赋值给该键值对
        except Exception as e:
            res["state"]=1001
            res["msg"]="请输入合法的字符"
        return JsonResponse(res)  # 使用json类自动发送json字符串给前端
    
    Python

    index.html文件示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    </head>
    <body>
    {% csrf_token %}
    <h3>INDEX</h3>
    
    
    <hr>
    <button class="ajax">ajax</button>
    <p class="con"></p>
    
    <hr>
    
    <button class="ajax2">携参ajax</button>
    <hr>
    
    <input type="text" class="num1"> + <input class="num2" type="text"> = <input class="result" type="text">
    <input class="cal" type="button" value="计算">
    
    
    <script>
        // ajax简单使用
        (".ajax").click(function () {         // 发送Ajax请求         .ajax({
                url:"/ajax_handle/",  {# 请求路径 #}
                type:"get", {# 请求方式#}
                success:function (res) {  {# 请求成功后,执行的回调函数`#}
                    console.log(res);
                    (".con").html(res);             }         })     });      // ajax的携带参数访问     (".ajax2").click(function () {
            // 发送Ajax请求
            .ajax({             url:"/ajax_handle2/",             type:"post", {# 注意要加上csrf-token,Django默认都有#}             data:{                 a:1,                 b:2,                 csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()
                },
                success:function (res) {
                    console.log(res);
                }
            })
        });
    
        // 携参示例
        (".cal").click(function () { {#  绑定点击事件  #}        let num1=(".num1").val(); {#  拿到用户输入的两个要计算的值  #}
           let num2=(".num2").val();        .ajax({
               url:"/cal/",  {#  请求路径,可以理解为,执行视图函数的对应的路径  #}
               type:"post", {#  post方式发送请求  #}
               data:{
                   num1:num1,
                   num2:num2,
                   csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()            },            success:function (res) {                {#let response=JSON.parse(res)#}   {#  如果是自己手动在后端发送json字符串,要我们手动反序列化  #}                {# JSON.stringify()       这个就是前端的序列化,将数据变成json  #}                if (res.state=="1000"){                    (".result").val(res.data)
                   }else{
                       alert(res.msg)
                   }
               }
           })
        });
    </script>
    </body>
    </html>
    
    HTML

    三、案例及作业

    1、登录成功跳转个人首页,失败局部刷新提示用户

    login.html文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
        <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
        <script src="/static/jquery-3.1.js"></script>
    </head>
    <body>
    <h3>欢迎来到登录页面</h3>
    {% csrf_token %}
    <div class="col-md-4 col-md-offset-3">
        <label for="user">账号</label>
        <input type="text" id="user" placeholder="请输入您的账号" class="form-control">
    </div>
    
    <div class="col-md-4 col-md-offset-3">
        <label for="pwd">密码</label>
        <input type="password" id="pwd" placeholder="请输入你的密码" class="form-control">
    </div>
    
    <div class="col-md-4 col-md-offset-3">
        <br>
        <button class="ajax1 btn btn-default ">确认</button>
        <button class="ajax2 btn btn-default ">取消</button>
        <p class="con"></p>
    </div>
    
    <script>
    
        (".ajax1").click(function () {         .ajax({
                url:"/login/",
                type:"post",
                data:{        {# 这一步发送数据给服务器 #}
                    user:("#user").val(),                 pwd:("#pwd").val(),
                    csrfmiddlewaretoken:("[name='csrfmiddlewaretoken']").val()  {#  可以在settings文件中取消  #}             },             success:function (res) {  {# 服务器处理成功后,返回数据到这一步给前端 #}                 if (res.user) {                     location.href="/books/"  {# 让浏览器重新发送新的页面请求,类似redirect #}                 }else{                     {# #}                     (".con").html(res.msg).css("color","red");   {# 显示错误信息 #}
                        setTimeout(function () {   {## 定时一秒后,将错误提示去掉#}
                            $(".con").html("")
                        },1000)
                    }
                }
            })
        })
    </script>
    </body>
    </html>
    
    HTML

    views.py视图文件

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    import json
    from book import models
    from django.http import JsonResponse
    
    def login(requeset):
        if requeset.method == "GET":
            return render(requeset,"login.html")
        else:
            res={"user":None,"msg":None}
            user = requeset.POST.get("user") # 拿到用户名
            pwd = requeset.POST.get("pwd")  # 拿到用户的登录密码,进行比对
            user_obj=models.UserInfo.objects.filter(user=user,pwd=pwd).first()  # 跟数据库的数据进行比对,
            if user_obj:
                res["user"]="alex"
            else:
                res["msg"]="用户名或密码错误!"
            return JsonResponse(res)
    
    
    Python

    2、基于ajax删除已有书籍,局部刷新

    books.html文件(部分)

    <tbody class="tbody">
                {% for book in queryset %}
                    <tr>
                        <td>{{ forloop.counter }}</td>   {# forloop.counter,提供自动计数,保证删除是,Id可以跟着变动#}
                        <td>{{ book.title }}</td>
                        <td>{{ book.price }}</td>
                        <td>{{ book.publish }}</td>
                        <td>{{ book.pub_date|date:"Y-m-d " }}</td>
                        <td>
    {#      通过多表查询得到作者名字,因为有可能有多个作者,所以要用for循环取出#}
                            {% for author in book.authors.all %}
                            <span>{{ author.name }}</span>
                            {% endfor %}
                        </td>
                        <td>
                            <button class="ajax2"  pk="{{ book.pk }}">ajax删除</button>
                            <a href="/books/delete/{{%20book.pk%20}}">删除</a>
    {#      在生成显示页面的时候,book.pk就每次都更新了,点击的时候,就会对应的跳转#}
                            <a href="/books/edit/{{%20book.pk%20}}">编辑</a>
                        {#      a标签默认GET请求方式 #}
                        </td>
                    </tr>
                {% endfor %}
    
                </tbody>
    
    <script>
        (".ajax2").click(function () {         // 发送ajax请求         let num = (this).attr("pk");  {# 自定义一个值,用当前的ID赋值给其,在这里取出   #}
            let tr = (this).parent().parent();
            .ajax({             url:"/del_ajax/", {# 如何获取动态的url  #}                {#不写默认get请求 #}             data:{                 pk:num, {# 注意这里不能写(this),这个是js的语法,不是ajax的,值得名字随意,键要跟视图函数对齐,那边要取  #}
                },
                success:function (res) {
                    if (res.state){
                        $tr.replaceWith("<tr><td style='color:red'> 删除成功!</td></tr>")
                    }else{
                        alert("失败了")
                    }
                }
            })
        })
    </script>
    
    HTML

    views.py视图函数

    from django.shortcuts import render,HttpResponse,redirect
    
    from book import models
    from django.http import JsonResponse
    
    def del_ajax(request):
        res={"state":True}
        try:
            pk=request.GET.get("pk")  # 拿到主键ID
            models.Book.objects.filter(pk=pk).delete() # 根据主键从数据库中删除
        except Exception as e:
            res["state"]=False  # 如果不能删除,返回False状态进行报错
        return JsonResponse(res)
    
    Python

    3、案例

    1、用户名是否已被注册

    在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。
    服务器返回true或false,
    返回true表示这个用户名已经被注册过,返回false表示没有注册过。
    
    客户端得到服务器返回的结果后,
    确定是否在用户名文本框后显示“用户名已被注册”的错误信息!
    

    2、基于Ajax进行登录验证

    用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,
    
    客户端通过响应信息确定是否登录成功,成功,则跳转到首页,
    
    否则,在页面上显示相应的错误信息。
    

    四、请求头ContentType(看完后,看后面的文件上传实例来看)

    ContentType指的是请求体的编码类型,常见的类型共有3种:
    

    1、application/x-www-form-urlencoded(默认的,Django默认按这个解析)

    这应该是最常见的 POST 提交数据的方式了。
    浏览器的原生 
    

    <

    form> 表单,如果不设置 enctype 属性,
    那么最终就会以 application/x-www-form-urlencoded 方式提交数据。

    请求类似于下面这样(无关的请求头在本文中都省略掉了):
    
    POST http://www.example.com HTTP/1.1
    Content-Type: application/x-www-form-urlencoded;charset=utf-8
    
    user=yuan&age=22
    
    Bash

    2、multipart/form-data(用于提交文件)

    这又是一个常见的 POST 数据提交的方式。
    我们使用表单上传文件时,
    必须让form表单的 enctype 等于 multipart/form-data。
    直接来看一个请求示例:
    
    POST http://www.example.com HTTP/1.1
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="user"
    
    yuan
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="file"; filename="chrome.png"
    Content-Type: image/png
    
    PNG ... content of chrome.png ...
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
    
    Bash
    这个例子稍微复杂点。
    首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。
    然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。
    
    消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,
    紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。
    
    如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。
    关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。
    
    这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。
    
    上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式
    (通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。
    其实 enctype 还支持 text/plain,不过用得非常少)。
    
    Bash

    3、application/json(使用json字符串进行数据传输,现在也很常用)

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。
    
    实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。
    服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
    
    JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。
  • 相关阅读:
    SPI(1)——Documentation/spi/spi_summary.txt翻译
    TCP协议详解(TCP报文、三次握手、四次挥手、TIME_WAIT状态、滑动窗口、拥塞控制、粘包问题、状态转换图)
    Linux设备树(3)——Linux内核对设备树的处理
    Linux设备树(2)——设备树格式和使用
    [转]Android的taskAffinity
    [转]深入了解iPad上的MouseEvent
    NG2入门
    TypeScript 素描
    TypeScript 素描
    TypeScript 素描
  • 原文地址:https://www.cnblogs.com/yipianshuying/p/10252605.html
Copyright © 2020-2023  润新知