1. 程式人生 > >前端踩的一些坑

前端踩的一些坑

今天用bootstrap modal 進行ajax傳送資料時,傳送資料時第一次點選,傳送一次ajax提交,第二次點擊發送兩次ajax提交,第三次點擊發送3次ajax提交...),原來是在標籤上綁定了太多事件,用jq方法 .off()即可去除。

參考博文:

本節內容

  1. 事件代理
  2. 清除標籤的所有事件
  3. bootstrap的模態框自定義方法
  4. ajax在django裡面實現post提交
  5. ajax提交資料巢狀

1.事件代理

之前寫前端的時候發現在ajax裡面獲取到的部分html插入到主頁面中,插入的部分html中的button始終無法繫結click事件。。。各種找問題,最後發現鍋是在頁面剛請求到的時候,那部分ajax請求到的頁面還沒有載入到主html中,js繫結事件的時候找不到這個標籤,於是就繫結失敗。

之後在網上找相關資料,原來js裡面有一個概念叫做事件代理和委託,能夠解決我的問題。

既然說到了事件代理和委託,那就得涉及到事件冒泡和捕獲的概念了。這裡應用的部分內容:

事件冒泡及捕獲

之前的介紹中已經說到了瀏覽器的事件冒泡機制。這裡再詳細介紹一下瀏覽器處理DOM事件的過程。對於事件的捕獲和處理,不同的瀏覽器廠商有不同的處理機制,這裡我們主要介紹W3C對DOM2.0定義的標準事件。

DOM2.0模型將事件處理流程分為三個階段:一、事件捕獲階段,二、事件目標階段,三、事件起泡階段。如圖: 技術分享

事件捕獲:當某個元素觸發某個事件(如onclick),頂層物件document就會發出一個事件流,隨著DOM樹的節點向目標元素節點流去,直到到達事件真正發生的目標元素。在這個過程中,事件相應的監聽函式是不會被觸發的。

事件目標:當到達目標元素之後,執行目標元素該事件相應的處理函式。如果沒有繫結監聽函式,那就不執行。

事件起泡:從目標元素開始,往頂層元素傳播。途中如果有節點綁定了相應的事件處理函式,這些函式都會被一次觸發。如果想阻止事件起泡,可以使用e.stopPropagation()(Firefox)或者e.cancelBubble=true(IE)來組織事件的冒泡傳播。

也就是說既然我無法在請求到的部分html中繫結click事件,那麼我可以在它的父標籤上面繫結click事件,當子標籤的click事件被觸發之後,如果子標籤沒有繫結,那麼這個時間將會冒泡到父標籤上(或者先被父標籤捕獲,而不到達子標籤上)。這樣就可以實現繫結ajax獲取的html裡面的標籤的click事件了。

jquery程式碼實現如下:

$(".body_right").click(".btn",function (env){
    var btn=$(env.target); 
    console.log(btn) 
})

這裡面的.body_right就是父標籤,在父標籤上繫結click事件,監聽下面的所有(.btn)按鈕,當事件被觸發的時候,在function的引數裡面會傳遞一個env引數,這個引數裡面有一個target屬性,通過env.target可以直接拿到被點選的按鈕element。之後就可以為所欲為了,哈哈哈。

當然,事件代理也可以用在需要繫結多個子標籤的事件上,如果需要繫結多個子標籤的click事件,那麼js裡面需要迴圈遍歷子標籤,給每個子標籤繫結事件,jquery可以使用each繫結一組子標籤,但是事件代理直接繫結這些子標籤的父標籤,當有事件觸發時可以直接找到被點選的子標籤,可以大大簡化js程式碼。

2.清除標籤的所有事件

上面說發現了一個好東西,事件代理,那麼這個好東西當然要用在程式碼裡面去了,但是我發現一個問題,那就是當一個標籤綁定了多個事件代理之後,會出現一個問題。。。就是一個事件被多次觸發。。。(現實效果是第一次點選,傳送一次ajax提交,第二次點擊發送兩次ajax提交,第三次點擊發送3次ajax提交...)為了解決這個問題,就需要在標籤被繫結事件之前,先清除其它所有繫結事件對該標籤的影響,這裡有一個土辦法,那就是在jquery裡面有一個方法.off()這個方法可以將繫結標籤的所有事件清除。下面是jquery程式碼:

$(".modal-content").off().click("button",function(ev) { 
  console.log($(ev.target))
 })

3.bootstrap的模態框自定義方法

專案裡面用到了模態框,覺得bootstrap的模態框挺漂亮的,於是拿過來用了用,確實不錯,但是當我想自定義模態框裡面的東西的時候,發現了一個問題,那就是自己設計的(確定)按鈕點選之後模態框並沒有關閉,之後去官網找文件,發現bootstrap的模態框裡面提供了一些方法來幫助我們實現自定義模態框的操作。 下面是官方文件的內容:

.modal(options)

將頁面中的某塊內容作為模態框啟用。接受可選引數 object。

$(‘#myModal‘).modal({
  keyboard: false
})
.modal(‘toggle‘)

手動開啟或關閉模態框。在模態框顯示或隱藏之前返回到主調函式中(也就是,在觸發 shown.bs.modal 或 hidden.bs.modal 事件之前)。

$(‘#myModal‘).modal(‘toggle‘)
.modal(‘show‘)

手動開啟模態框。在模態框顯示之前返回到主調函式中 (也就是,在觸發 shown.bs.modal 事件之前)。

$(‘#myModal‘).modal(‘show‘)
.modal(‘hide‘)

手動隱藏模態框。在模態框隱藏之前返回到主調函式中 (也就是,在觸發 hidden.bs.modal 事件之前)。

$(‘#myModal‘).modal(‘hide‘)
也就是說繫結(確定)按鈕的時候,可以觸發模態框的hide事件:

$(‘#Mymodal‘).modal(‘hide‘) //隱藏模態框 
$(‘#Mymodal‘).modal(‘show‘) //顯示模態框

4.ajax在django裡面實現post提交

由於django默然開啟了csrf攻擊防護,其實就是在post提交的時候檢查如果請求體裡面沒有它發給你的token,那麼就不接受這個post提交併返回403 forbidden錯誤,那麼在ajax提交post資料的時候,需要自己構造一個鍵值對{csrfmiddlewaretoken: {% csrftoken %}},但是這樣用的話js就必須放在html裡面讓django進行模板渲染,如果js想放在js檔案裡面的話就需要在html裡面定義一個{% csrftoken %},這樣會生成一個hidden的input標籤,通過js找到這個標籤,拿到value,再拼接到ajax的data裡面去,就可以實現了。jquery程式碼如下:

$.ajax("/del_student/",{
    type:"POST", 
    data:{id:id,csrfmiddlewaretoken: csrf_token},
    success:show_student, 
    complete:$(‘#Mymodal‘).modal(‘hide‘)
 });

5.ajax提交資料巢狀

如果ajax提交的資料裡面有巢狀,那麼在提交的時候需要設定一個引數traditional:"true",默然traditional是false的,那麼後端獲取巢狀資料的時候將會出問題,將traditional設定成true就可以了。