您好,登錄后才能下訂單哦!
這篇文章主要介紹了Vue中怎么實現回車鍵切換焦點,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
Vue是一套用于構建用戶界面的漸進式JavaScript框架,Vue與其它大型框架的區別是,使用Vue可以自底向上逐層應用,其核心庫只關注視圖層,方便與第三方庫和項目整合,且使用Vue可以采用單文件組件和Vue生態系統支持的庫開發復雜的單頁應用。
幾乎在所有瀏覽器中,都具有 Tab 鍵切換焦點的功能。
但是任性的用戶強烈要求一定要有 Enter 鍵切換焦點的功能。
為了交付上線拿到錢,我們只好再一次毫無原則性的接受了客戶的需求。
在上一代人中,大多都有這種操作習慣。習慣把保存成為編輯,習慣用回車替換 Tab。這是受到微軟 excel 荼毒的結果。
起初我以為這個功能很簡單,無非就是把 Enter 鍵的功能轉接到 Tab 鍵上面,分分鐘就可以解決掉的問題。
可困難馬上就出現了,我發現這條路是走不通的。
我們經常可以主動觸發某個事件,比如 el.click()
就可以調用點擊事件,或者使用 dispatchEvent
。但是鍵盤和鼠標事件卻不行。
我查閱了很多資料,也做了很多嘗試。最后總結出來一個結論,在瀏覽器中,JavaScript 無法操作用戶的鍵盤或者鼠標,這是出于安全策略的考慮。仔細想一下,如果可以用一段 JavaScript 腳本控制用戶鍵盤和鼠標的話,那么用戶只需要打開一個黑客網站,黑客就可以瞬間得到他想得到的一切。
所以,如果要通過除 Tab 鍵以外的其他方式來觸發焦點切換, focus
幾乎是唯一的選擇。
在原生頁面中實現回車鍵切換焦點
項目是基于 vue 和 element-ui 做的,為了把實現思路先講清楚,暫時把這些拋開,從原生的頁面中尋找答案。
以下是一個原生的 html 頁面。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width" /> <title>Demo</title> </head> <body> <form> <input placeholder="姓名" /> <input placeholder="性別" /> <input placeholder="年齡" /> </form> </body> </html>
接下來要實現通過回車鍵切換焦點,我把思路梳理如下:
監聽回車鍵按下事件。
獲取當前聚焦元素。
獲取下一個要被聚焦的元素。
切換焦點。
思路有了,實現起來也非常簡單。
在文檔中添加 script 標簽,寫入如下代碼。
function enterCallback(e) { if (e.keyCode === 13) { // 按下回車后的邏輯 } } window.addEventListener("keydown", enterCallback);
要注意, enterCallback
單獨拿出來,用于注銷監聽事件。
監聽按鍵事件最常用的方法就是使用事件委托,將事件綁定到 window
對象上。相比較給每一個元素都綁定一個事件的方式,這樣做的最大好處就是節省內存空間,性能更好。
判斷按下哪個鍵的方式有很多,比如判斷 e.key
、 e.code
或者 e.keyCode
等方式。但絕大多數的情況下都建議使用 e.keyCode
。下面是一張來自網絡的 keyCode
表。
很容易就可以做到這一步。
常見的有兩種方式。第一種是 e.target
,第二種是 document.activeElement
。這種情況下,個人更推薦使用第二種。
function enterCallback(e) { if (e.keyCode === 13) { let activeEl = document.activeElement; } }
這一步也比較容易。使用 el.nextElementSibling
API 即可獲取。
function enterCallback(e) { if (e.keyCode === 13) { let activeEl = document.activeElement; let nextEl = activeEl.nextElementSibling; } }
切換焦點調用 focus
即可實現。
function enterCallback(e) { if (e.keyCode === 13) { let activeEl = document.activeElement; let nextEl = activeEl.nextElementSibling; nextEl && nextEl.focus(); } }
至此一個最簡單的 Demo 已經實現了,接下來看看項目中實際的情況。
在 element-ui 項目中實現回車鍵切換焦點
因為是使用組件開發,加上樣式等因素,dom 節點并不像上面寫的原生 Demo 那么簡單,實際情況是多層嵌套的。下面是實際生成的代碼結構。
<div class="el-form-item el-form-item--small" > <label for="pactcode" class="el-form-item__label" >協議號</label > <div class="el-form-item__content" > <div class="el-input el-input--small"> <!----> <input type="text" autocomplete="off" id="el-input" placeholder="未填寫協議號" class="el-input__inner" /> <!----> </div> </div> </div>
可以看到,如果每一個輸入框都是這種類型的嵌套結構,上面的方法是無法直接解決的。因為 nextElementSibling
API 只能找到下一個兄弟元素,而在這里 input 明顯找不到下一個兄弟元素。
思路是,通過回溯的手段朝外層尋找,直到找到一個類名包含 el-form-item
和 el-form-item--small
的祖級元素,然后再從這個祖級元素的下一個兄弟元素中尋找類名包含 el-input__inner
的 input 元素。
所以要再寫兩個函數,分別是尋找組件元素的 findFormItem
和尋找 input 元素的 findInput
。
findFormItem:
function findFormItem(el) { const parent = el.parentElement; if (!parent) return document.body; if ( parent.className.includes("el-form-item") && parent.className.includes("el-form-item--small") ) { return parent; } return findFormItem(parent); }
findInput:
function findInput(container) { let nextEl = container.nextElementSibling; if (!nextEl) return; let input = nextEl.querySelector("input"); while (input.id === "el-select") { nextEl = nextEl.nextElementSibling; if (!nextEl) return; input = nextEl.querySelector("input"); } if (input.className.includes("el-input__inner")) return input; }
有了這兩個函數以后,實現回車切換焦點就非常簡單了。只需要執行兩行代碼。
const container = findFormItem(document.activeElement); findInput(container) && findInput(container).focus();
完整的代碼大概是這樣的。
在 methods
中聲明三個方法。
methods: { addEnterListener() { if (window.__completeEnterBind__) return; window.addEventListener("keydown", this.enterCallback); window.__completeEnterBind__ = true; }, removeEnterListener() { window.removeEventListener("keydown", this.enterCallback); window.__completeEnterBind__ = false; }, enterCallback(e) { function findFormItem(el) { const parent = el.parentElement; if (!parent) return document.body; if ( parent.className.includes("el-form-item") && parent.className.includes("el-form-item--small") ) { return parent; } return findFormItem(parent); } function findInput(container) { let nextEl = container.nextElementSibling; if (!nextEl) return; let input = nextEl.querySelector("input"); while (input.id === "el-select") { nextEl = nextEl.nextElementSibling; if (!nextEl) return; input = nextEl.querySelector("input"); } if (input.className.includes("el-input__inner")) return input; } if (e.keyCode === 13) { const container = findFormItem(document.activeElement); findInput(container) && findInput(container).focus(); } } }
然后在 mounted
中添加回車監聽和在 destroy
中移除回車鍵聽。
mounted() { this.addEnterListener(); }, destroy() { this.removeEnterListener(); },
需要注意的是,項目是多標簽頁的形式,表單組件可能會被渲染多次,所以通過在 window 對象上添加一個 __completeEnterBind__
字段來確保回車換行事件正確綁定。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Vue中怎么實現回車鍵切換焦點”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。