javascript ajax

AJAX

AJAX(Asynchronous JavaScript And XML)翻译成中文就是"异步的Javascript和XML"。

即使用JavaScript语言与服务器进行异步交互,传输的数据为XML(当前不只是XML)

AJAX 不是新的编程语言,而是一种使用现有标准的新方法

AJAX最大的有点在于,整个页面不重新加载的情况下,可以与服务器进行交互数据并且更新部分数据内容。

(这一特点 用户在不知不觉中完成了前后端 请求和响应的过程)

AJAX不需要任何浏览器插件,只需要用户允许JavaScript在浏览器执行。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发送第二个请求。
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发送第二个请求。

示例

页面输入内容,通过AJAX传输到后端进行计算并返回结果

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Title</title>
</head>
<body>

{% csrf_token %}

<input type="text" name="i1" value="{{ i1 }}"> +
<input type="text" name="i2" value="{{ i2 }}"> =
<input type="text" name="i3" value="{{ i3 }}">
<button id="b1">计算</button>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="/static/ajax_setup.js"></script>

<script>
    $('#b1').click(function () {
        // 获取前面input框 计算出的值 发送给后端
        // 发送ajax请求
        $.ajax({
            url:'/calc/', // 请求的地址
            type:'post', // 请求方式 默认不写为get请求
            data: {
                l1: $('[name="i1"]').val(),
                l2: $('[name="i2"]').val(),
            }, // 提交的数据
            success:function (res) {
                $('[name="i3"]').val(res)
            } // 响应成功,回调的函数 res响应体
        })
    });
</script>

</body>
</html>

views.py

def index(request):
    return render(request,'index.html')

def calc(request):
    l1 = request.POST.get('l1')
    l2 = request.POST.get('l2')
    return  HttpResponse(int(l1) + int(l2))

urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index, name='index'),
    url(r'^calc/', views.calc,name='calc'),
]

AJAX常见应用情景

索引擎根据用户输入的关键字,自动提示检索关键字。

还有一个很重要的应用场景就是注册时候的用户名的查重。

其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

img

当输入用户名后,把光标移动到其他表单项上时,浏览器会使用AJAX技术向服务器发出请求,服务器会查询名为lemontree7777777的用户是否存在,最终服务器返回true表示名为lemontree7777777的用户已经存在了,浏览器在得到结果后显示“用户名已被注册!”。

  • 整个过程中页面没有刷新,只是局部刷新了;
  • 在请求发出后,浏览器不用等待服务器响应结果就可以进行其他操作;

AJAX的优缺点

优点:

  • AJAX使用JavaScript技术向服务器发送异步请求;
  • AJAX请求无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;

$.ajax参数

  $("#b1").on("click", function () {
    $.ajax({
      url:"/ajax_add/",
      type:"GET",
      data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])},
      success:function (data) {
        $("#i3").val(data);
      }
    })
  })

JS实现ajax

var b2 = document.getElementById("b2");
  b2.onclick = function () {
    // 原生JS
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("POST", "/ajax_test/", true);
    xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlHttp.send("username=q1mi&password=123456");
    xmlHttp.onreadystatechange = function () {
      if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
        alert(xmlHttp.responseText);
      }
    };
  }; 

AJAX请求如何设置csrf_token

方式一

通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  data: {
    "username": "Q1mi",
    "password": 123456,
    "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
  },
  success: function (data) {
    console.log(data);
  }
})

方式二

通过获取返回的cookie中的字符串 放置在请求头中发送。

注意:需要引入一个jquery.cookie.js插件

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 从Cookie取csrftoken,并设置到请求头中
  data: {"username": "Q1mi", "password": 123456},
  success: function (data) {
    console.log(data);
  }
})

或者用自己写一个getCookie方法:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

注意:

如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。

如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。

这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。

django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def login(request):
    pass

更多细节详见:Djagno官方文档中关于CSRF的内容

AJAX上传文件

// 上传文件示例
$("#b3").click(function () {
  var formData = new FormData();
  formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
  formData.append("f1", $("#f1")[0].files[0]);
  $.ajax({
    url: "/upload/",
    type: "POST",
    processData: false,  // 告诉jQuery不要去处理发送的数据
    contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
    data: formData,
    success:function (data) {
      console.log(data)
    }
  })
})

views.py

def file_upload(request):
    if request.method == 'POST':
        print(request.FILES)
        f1 = request.FILES.get('f2')
        with open(f1.name,mode='wb') as f:
            for i in f1.chunks():
                f.write(i)
    return render(request,'file_upload.html')

例子 用户名是否已注册

在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回这个用户名是否已经被注册过。

urls.py

urlpatterns = [
    ...
    url(r'^regist/$',views.Register.as_view(), name='register'),
    url(r'^user_test/$',views.user_test,name='user_test'),
	...
]

views.py

def user_test(request):
    register = request.POST.get('user')
    print(register)
    userobj = models.User.objects.filter(username=register)
    if userobj:
        return HttpResponse('用户已存在')
    return HttpResponse('')


class Register(View):
    http_method_names = ['get', 'post']

    def get(self, request, *agrs, **kwargs):
        return render(request, 'register.html')

    def post(self, request, *args, **kwargs):
        reg_user = request.POST.get('username')
        reg_passwd1 = request.POST.get('password1')
        reg_passwd2 = request.POST.get('password2')

        if reg_passwd2 != reg_passwd1:
            return render(request, 'register.html', {'password_error': '密码输入不匹配'})

        models.User.objects.create(username=reg_user, password=reg_passwd2)
        return redirect('login')

base.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    {% load static %}
    <title>注册页面</title>
</head>

<body>
<form class="text-center form-signin" action="" method="POST">
    <span class=" iconfont">&#xe617;</span>
    <div class="form-group row">
        <label for="inputPassword6" class="col-sm-3 col-form-label col-form-label-lg">Username</label>
        <input type="text" id="username" class="form-control
    form-control-sm" aria-describedby="passwordHelpInline" name="username">
        <br>
        <small id="passwordHelpInline" class="">{{ cc }}</small>
    </div>

    <div class="form-group row">
        <label for="inputPassword6" class="col-sm-2 col-form-label col-form-label-lg">Password</label>
        <input type="password" id="inputPassword6" class="form-control form-control-sm"
               aria-describedby=" passwordHelpInline" name="password1">
        <small id="passwordHelpInline" class="text-muted">
            请输入注册密码
        </small>
    </div>

    <div class="form-group row">
        <label for="inputPassword6" class="col-sm-2 col-form-label col-form-label-lg">Renew&nbsp;password</label>
        <input type="password" id="inputPassword7" class="form-control
        form-control-sm" aria-describedby="passwordHelpInline" name="password2">
        <small id="passwordHelpInline" class="text-muted">
            请重新输入密码
        </small>
    </div>
    <span style="color: red;" class="text-center ">{{ password_error }}&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <button class="btn btn-lg btn-primary btn-block" type="submit">注册</button>
</form>
</body>
    <script src="/static/plugins/jQuery3.4.1.js"></script>
    <script src="/static/plugins/ajax_setup.js"></script>
    <script src="/static/js/test.js"></script>
</html>

test.js

$('#username').focus(function () {
    var a = $('#passwordHelpInline');
    a.text('请输入注册用户!');
    a.css('color','red','font-size','14')
});

// 用户失去焦点触发ajax
$('#username').blur(function () {
    var input_user = $('#username').val();
    if (input_user.length === 0){
        $('#passwordHelpInline').text('不能为空!')
    } else {
        $.ajax({
            url: '/user_test/',
            type: 'post',
            data: {
                user: input_user
            },
            success: function (res) {
                var a = $('#passwordHelpInline');
                a.text(res)
            }
        })
    }
});

SweetAlert插件

img

点击下载Bootstrap-sweetalert项目

https://sweetalert.js.org/guides/

$(".btn-danger").click(function () {
    swal({
        title: "你确定要删除吗?",
        text: "一旦删除 赵臻儿子都帮你弄不回来!!!",
        icon: "warning",
        buttons: true,
        dangerMode: true,
    })
        .then((willDelete) => {
            if (willDelete) {
                $.ajax({
                    url: $(this).attr('href'),
                    type: 'get',
                    success: (res) => {
                        if (res.status) {
                            $(this).parent().parent().remove();
                            swal("删除成功", {
                                icon: "success",
                            });
                        }
                    }
                });
            } else {
                swal("欢迎再度光临!!");
            }
        });
});
posted @ 2019-12-02 16:04  Hyyyy  阅读(480)  评论(0编辑  收藏  举报