簡體   English   中英

無法使用preventDefault()以編程方式檢查單選按鈕

[英]Can't check radio button programmatically with preventDefault()

我有一些元素(例如帶有類.label的div),每個元素都有單選按鈕。 當用戶單擊此“標簽”時,我以編程方式將其中的無線電設置為已選中。 但是如果我使用preventDefault()進行點擊事件,如果用戶完全點擊無線電,則無法選擇收音機。

請幫我理解這種奇怪的行為。 我知道解決方案,我知道為什么在父元素上的preventDefault()不允許檢查無線電,但我想明白,為什么無線電上的click事件可以禁止以編程方式設置其狀態 你會看到單擊單選按鈕會說收音機已被選中,但事實並非如此。

 $(function () { $('.label').on('click', function(e) { var $radio = $(this).find(':radio') console.log('before prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`); e.preventDefault(); if (!$(this).hasClass('checked')) { $('.checked').removeClass('checked'); $(this).addClass('checked'); } $radio.prop('checked', true); console.log('after prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`); setTimeout(function () { console.log('after timeout', `checked=${$radio.prop('checked')}`); }, 500); }); $(':radio').on('click', function (e) { console.log('click', `prevented=${e.isDefaultPrevented()}`); }); }); 
 .label { padding: 10px; margin-bottom: 10px; border: 1px solid #000; } .label.checked { background-color: green; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="label"> Label 1 <input type="radio" name="radio" value="1"> </div> <div class="label"> Label 2 <input type="radio" name="radio" value="2"> </div> 

更新 我怎么看這種情況:

  1. 用戶點擊廣播
  2. 首先在無線電上觸發事件,並將輸入設置為已檢查。
  3. 然后事件冒泡並在.label上觸發
  4. 調用preventDefault()會設置內部cancelled標志。
  5. div將類'.checked'和radio設置為再次檢查,現在以編程方式。
  6. 事件泡沫,但沒有任何事情發生。
  7. 由於事件已取消,因此不應執行默認操作,並將復選框重置為其先前狀態。

我對嗎?

我如何看待這種情況(受https://stackoverflow.com/a/15767580/11357125啟發):

  1. 你點擊收音機
  2. 它被檢查
  3. 該事件將在文檔根目錄上分派
  4. 捕獲階段,處理程序沒有任何反應
  5. 事件到達<input>
  6. ......並開始冒泡
  7. <div> ,它被處理。 事件偵聽器調用preventDefault方法,設置內部cancelled標志。 <div>將類'.checked'和radio設置為再次檢查,現在以編程方式
  8. 事件泡沫,但沒有任何事情發生。
  9. 由於事件已取消,因此即使在以編程方式檢查后,也不會發生默認操作,並且復選框將重置為其先前狀態。

在父元素上使用preventDefault()可以防止觸發原始事件,但不會停止傳播。 了解層次結構和事件傳播至關重要。

您的代碼段中包含部分解決方案。 如果您注釋掉該特定行,則代碼可以正常工作,就像您期望的那樣。 但如果你使用

e.stopPropagation();

它也有效。

為了不重復網上已有的信息,我在這里找到了一個非常相似的案例( 為什么在父元素點擊'禁用'一個復選框?上的preventDefault()?這可能有助於你理解更好的事件傳播和冒泡。

您還可以在此處找到更好的解釋( https://medium.freecodecamp.org/a-simplified-explanation-of-event-propagation-in-javascript-f9de7961a06e )。

MDN文檔也很少令人印象深刻( https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault )。

您只需要添加e.stopPropagation()以再次返回checked單選按鈕的默認功能

行為是你有radiodiv的孩子,你click監聽器是基於父div ,當你preventDefault ,孩子也繼承了預防。

檢查一下

如果按下一個元素上的按鈕並在另一個元素上釋放,則會在包含這兩個元素的最具體的祖先元素上觸發該事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM