1. 程式人生 > 其它 >基於jQuery的Ajax實現(重點)

基於jQuery的Ajax實現(重點)

目錄

基於jQuery的Ajax實現(重點)

  • 非同步提交
  • 區域性重新整理
"""

案例:github註冊示例,
	動態獲取使用者名稱,實時的跟後端確認並實時展示到前端(區域性重新整理)

傳送請求方式 
	1 瀏覽器位址列直接輸入url回車     GET請求
	2 a標籤href屬性				   GET請求
	3 form表單					POST請求/GET請求
	4 ajax						 POST請求/GET請求
	
"""

1、簡介

AJAX(Asynchronous Javascript And XML)翻譯成中文就是“非同步的Javascript和XML”。即使用Javascript語言與伺服器進行非同步互動,傳輸的資料為XML(當然,傳輸的資料不只是XML)。

AJAX 不是新的程式語言,而是一種使用現有標準的新方法。

AJAX 最大的優點是在不重新載入整個頁面的情況下,可以與伺服器交換資料並更新部分網頁內容。(這一特點給使用者的感受是在不知不覺中完成請求和響應過程)

AJAX 不需要任何瀏覽器外掛,但需要使用者允許JavaScript在瀏覽器上執行。

  • 同步互動:客戶端發出一個請求後,需要等待伺服器響應結束後,才能發出第二個請求;
  • 非同步互動:客戶端發出一個請求後,無需等待伺服器響應結束,就可以發出第二個請求。
Ajax只學習jQuery封裝好之後的版本,所以在前端頁面使用ajax的時候需要確保匯入jQuery

2、Ajax語法

案例引入:

"""
頁面有三個input框
    在前兩個框中輸入數字,點選按鈕,朝後端傳送到ajax請求
    後端計算出結果,再返回給前端動態展示到第三個input框
    (整個過程不允許有重新整理,也不能再前端計算)

"""
# index.html

<body>
<input type="text" id="d1">+
<input type="text" id="d2">=
<input type="text" id="d3">
<p>
    <button id="btn">Click</button>
</p>
<script>
    //給按鈕繫結點選事件
    $('#btn').click(function () {
        //朝後端傳送ajax請求
        $.ajax({

            //1 指定朝哪個後端傳送ajax請求
            url: '',//不寫朝當前地址提交,跟action三種書寫方式一致
            //2 請求方式
            type: 'post',//不指定,預設就是get
            //3 資料
            data: {'d1': $('#d1').val(), 'd2': $('#d2').val()},
            //4 回撥函式:當後端給你返回結果的時候會自動觸發 args接收後端的返回結果
            datatyp: 'JSON', //會自動反序列化
            success: function (args) {
                $('#d3').val(args)//通過DOM操作,動態渲染到第三個Input框
                #console.log(typeof (args))
                
            }
        })


    })
</script>
</body>

"""
針對後端,如果是用HttpResponse返回的json資料,前端回撥函式不會自動反序列化,
如果後端直接用的JsonResponse返回的資料,回撥函式會自動反序列化


HttpResponse解決方式
	1 自己再前端用JSON.parse()
	2.在ajax裡配置一個引數
		dataType:'JSON'  
    """

當利用ajax進行前後端互動的時候,後端無論返回什麼,都只會被回撥函式接收,而不再影響這個瀏覽器頁面

# views.py

from django.shortcuts import render, HttpResponse

from django.http import JsonResponse

# Create your views here.
def ab_ajax(request):
    if request.method == 'POST':
        # print(request.POST)
        # d1 = request.POST.get('d1')
        # d2 = request.POST.get('d2')
        # # 先轉成整型
        # d3 = int(d1) + int(d2)
        # print(d3)
        d={'code':100,'msg':666}
        # return HttpResponse(d3)
        # return HttpResponse(json.dumps(d))
        return HttpResponse(JsonResponse(d))
    return render(request, 'index.html')
# urls.py

from django.contrib import admin
from django.urls import path
from app01 import  views
urlpatterns = [
    path('admin/', admin.site.urls),
    #ajax相關
    path('ab_ajax/',views.ab_ajax)
]

3、前後端傳輸資料的編碼格式(contentType)

# 主要研究 post請求資料的編碼格式

"""
get請求資料就是直接放在url後面的  
	url?username=zhao&password=123
"""

#可以朝後端傳送post的請求方式
	"""
	1. form表單
	2. Ajax請求
	"""
    
# 前後端傳輸資料的編碼格式
	"""
	urlencoded
	fromdata
	json
	"""

3.0、程式碼

# index.html

<form action="" method="post" >
    <p>username:<input type="text" name="username" id="" class="form-control"></p>
    <p>password:<input type="text" name="password" id="" class="form-control"></p>
    <p>file:<input type="file" name="file" id=""></p>
    <input type="submit" name="" id="" class="btn btn-primary">
    <input type="button" name="" id="d1" class="btn btn-danger" value="click">
</form>


<script>
    $('#d1').click(function (){
        $.ajax({
            utl:'',
            type:'post',
            data:{'username':'tony','age':19},
            success:function (args){

        }
        })
    })
</script>
# views.py

from django.shortcuts import render
# Create your views here.
def index(request):
    if request.method =='POST':
        print(request.POST)
        print(request.FILES)
    return render(request,'index.html')
# urls.py 

from django.contrib import admin
from django.urls import path
from app01 import  views
urlpatterns = [
    path('admin/', admin.site.urls),
    #前後端編碼格式研究
    path('index/',views.index)
]

3.1、form表單

預設的編碼格式是urlencoded
資料格式:username=zhao&password=123
django後端針對符合urlencoded編碼格式的資料會自動的幫你解析封裝到request.POST中
	username=zhao&password=123  >>> request.POST
   
如果把編碼格式改成formdata,那麼針對普通的鍵值對還是解析到request.POST中而將檔案解析到request.FILES中


form表單沒有辦法傳送json格式
  • 預設的編碼格式
  • 資料格式
  • django後端針對符合urlencoded編碼格式的資料會自動的幫你解析封裝到request.POST中
  • 如果把編碼格式改成formdata,那麼針對普通的鍵值對還是解析到request.POST中,而將檔案解析到request.FILES中

3.2、ajax

預設編碼格式也是urlencoded
資料格式也是:username=tony&age=19
django後端針對符合urlencoded編碼格式的資料會自動的幫你解析封裝到request.POST中
	username=zhao&password=123  >>> request.POST
  • 編碼格式
  • 資料格式
  • django後端針對符合urlencoded編碼格式的資料會自動的幫你解析封裝到request.POST中

4、ajax傳送json格式資料

前後端傳輸資料的時候一定要確保編碼格式資料格式一致

"""
前後端傳輸資料的時候一定要確保編碼格式跟資料真正的格式是一致的


"""

request物件補充
	request.is_ajax()
	判斷當前請求是否是ajax請求,返回布林值
    
django對json格式的資料不會做任何的處理

程式碼:

<!--ab_json.html-->

<body>
<button class="btn btn-danger" id="d1">click me !!</button>

<script>
    $('#d1').click(function () {
        $.ajax({
            url: '',
            type: 'post',
            data: JSON.stringify({'username': 'zhao', 'age': 19}),
            contentType: 'application/json',//指定編碼格式
            success: function () {


            }
        })
    })
</script>
</body>
# views.py

def ab_json(request):
    # print(request.is_ajax())  # 判斷當前請求是否是ajax請求,返回布林值
    if request.is_ajax():
        # print(request.POST)
        # print(request.body)
        # 針對json格式資料需要自己手動處理
        json_bytes = request.body  # 二進位制資料
        # json_str = json_bytes.decode('utf-8')  # 將二進位制轉成字串
        # json_dic = json.loads(json_str)
        """json.loads括號內如果傳入了一個二進位制資料,那麼內部可以自動解碼再反序列化"""
        json_dic = json.loads(json_bytes)
        print(json_dic, type(json_dic))

    return render(request, 'ab_json.html')
# urls.py

from django.contrib import admin
from django.urls import path
from app01 import  views
urlpatterns = [
    path('admin/', admin.site.urls),

    #ajax傳送json格式的資料
    path('ab_json/',views.ab_json)
]

ajax傳送json格式資料需要注意以下幾點

  1. contentType引數指定成application/json
  2. 確保是真正的json格式資料,JSON.stringify()
  3. django後端不會自動處理json格式,需要去request.body中獲取資料並處理

  • 指定編碼格式
  • 但是此時要傳送的資料並不是json格式,需要轉成json格式
  • 前端使用JSON.stringify()將想要傳送的資料轉成json格式的資料
data: JSON.stringify({'username': 'zhao', 'age': 19}),
  • 檢視json格式資料
{"username":"zhao","age":19}
  • request.POST中找不到資料
  • request.body中獲取資料,轉成json格式
json.loads() 括號內如果傳入了一個二進位制資料,那麼內部可以 自動解碼再反序列化

5、ajax傳送檔案資料

"""ajax傳送檔案需要藉助於js內建物件FormData"""

<p>username:<input type="text" id="d1"></p>
<p>password:<input type="text" id="d2"></p>
<p><input type="file" id="d3"></p>
<button class="btn btn-info" id="d4">Click Me !!!</button>


<script>

    //點選按鈕朝後端傳送普通鍵值對和檔案資料
    $('#d4').on('click', function () {
        //1. 需要先利用FormData生成一個內建物件
        let formDataObj = new FormData();
        //2. 新增普通的鍵值對
        formDataObj.append('username', $('#d1').val());
        formDataObj.append('password', $('#d2').val());
        //3. 新增檔案物件
        formDataObj.append('myfile', $('#d3')[0].files[0])
        //4. 將物件基於ajax傳送給後端
        $.ajax({
            url: '',
            type: 'post',
            data: formDataObj,//直接將物件放在data後面即可
            //ajax傳送檔案必須指定兩個引數
            contentType: false, //不需要使用任何編碼,django後端能自動識別formdata物件
            processData: false, //告訴瀏覽器不要對資料進行任何處理

            success: function (args) {

            }
        })
    })
</script>
# views.py

def ab_file(request):
    if request.is_ajax():
        if request.method == 'POST':
            print(request.POST)
            print(request.FILES)
    return render(request, 'ab_file.html')

# urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),

    # ajax傳送檔案
    path('ab_file/', views.ab_file),
]

總結:

  1. ajax發文件需要利用內建物件FormData
       let formDataObj = new FormData();
        //2. 新增普通的鍵值對
        formDataObj.append('username', $('#d1').val());
        formDataObj.append('password', $('#d2').val());
        //3. 新增檔案物件
        formDataObj.append('myfile', $('#d3')[0].files[0])
  1. 需要指定兩個關鍵性引數
contentType: false, //不需要使用任何編碼,django後端能自動識別formdata物件
processData: false, //告訴瀏覽器不要對資料進行任何處理
  1. django後端能自動識別FormData物件,能夠將內部的普通鍵值自動封裝到request.POST中,檔案資料能自動解析封裝request.FILES

6、Ajax結合sweetalert實現刪除按鈕的二次確認

<style>
        div.sweet-alert h2 {
            padding-top: 15px;
        }
</style>


<h1 class="text-center">資料展示</h1>
<table class="table table-hover table-striped">
    <thead>
    <tr>
        <th>ID</th>
        <th>username</th>
        <th>age</th>
        <th>gender</th>
        <th>describe</th>
    </tr>
    </thead>
    <tbody>
    {% for user_obj in user_queryset %}
        <tr>
            <td>{{ user_obj.pk }}</td>
            <td>{{ user_obj.age }}</td>
            <td>{{ user_obj.username }}</td>
            <td>{{ user_obj.gender }}</td>
            <td>
                <button class="btn btn-toolbar btn-xs">編輯</button>
                <!--注意,繫結ajax事件在for迴圈中不能加id,每for迴圈一次出現一個按鈕,
                  如果繫結id就意味著for迴圈後出現的按鈕id值一致,使用class=del
                    我們需要實現使用者點選刪除按鈕,後端能夠知道使用者到底要刪那條資料,
                    後端怎麼知道?主鍵。
                   自定義屬性

                   ----->

                <button class="btn btn-danger btn-xs del" delete_id="{{ user_obj.pk }}">刪除</button>
            </td>

        </tr>
    {% endfor %}

    </tbody>
</table>


<script>
    $('.del').on('click', function () {
        //先將當前標籤物件儲存,用變數指代當前被點選物件
        let currentBtn = $(this);
        //二次確認彈框
        swal({
                title: "確定刪除??",
                text: "確定要刪嗎!!!",
                type: "warning",
                showCancelButton: true,    //延時效果
                confirmButtonClass: "btn-danger",
                confirmButtonText: "我就要刪!",
                cancelButtonText: "算了 算了 不刪了",
                closeOnConfirm: false,
                closeOnCancel: false
            },
            //isConfirm 判斷使用者有沒有點選二次確認刪除按鈕
            function (isConfirm) {
                if (isConfirm) {
                    // 朝後端傳送ajax請求刪除資料之後,後端判斷是否有資料,再談下面的提示框,
                    $.ajax({
                        // 向當前頁面傳送ajax請求,並攜帶需要產出資料的主鍵值,傳遞主鍵值第一種方式
                        {#url:'/delete/user/' + currentBtn.attr('delete_id'),#}
                        // 傳遞主鍵值第二種方式,放在請求體中
                        url: '/delete/user',
                        type: 'post',
                        data: {'delete_id': currentBtn.attr('delete_id')},
                        success: function (args) {
                            //判斷響應狀態碼做不同的處理。
                            if (args.code === 1000) {
                                swal("已刪除!", args.msg, "success");
                                // 2.利用DOM操作,動態重新整理
                                // 當前端點選刪除,後端找到標籤所在行,通過DOM操作刪除此行,
                                // delete_id 上一個標籤是td,再上一個標籤為tr,需要刪的是當前標籤delete_id所在的這一行。

                                // currentBtn指代的是當前被操作物件,parent()拿到父標籤,兩個parent()拿到父標籤的父標籤
                                currentBtn.parent().parent().remove()  //實時重新整理
                            } else {
                                swal("出現問題", "..", "info");
                            }
                        }
                    })

                } else {
                    swal("您已取消", "...........", "error");
                }
            });
    })
</script>
# views.py

def delete_user(request):
    """
    前後端在使用ajax進行互動的時候,後端通常給ajax回撥函式返回一個字典格式的資料
    字典返回到前端就是一個自定義物件,前端可以通過.的方式拿到想要的資料
    :param request:
    :return:
    """
    if request.is_ajax():
        if request.method == 'POST':
            # code:1000 為響應狀態碼
            back_dic = {'code': 1000, 'msg': ''}
            # 取到前端返回使用者想要刪除資料的主鍵值
            delete_id = request.POST.get('delete_id')
            models.User.objects.filter(pk=delete_id).delete()
            back_dic['msg'] = '資料已刪除'
            # 需要告訴前端操作的結果
            return JsonResponse(back_dic)

效果圖:

(drf:django rest framework)