欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue中實(shí)現(xiàn)回車鍵切換焦點(diǎn)的方法

 更新時(shí)間:2020年02月19日 11:04:16   作者:瀾嵐  
這篇文章主要介紹了在Vue中實(shí)現(xiàn)回車鍵切換焦點(diǎn)的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

幾乎在所有瀏覽器中,都具有 Tab 鍵切換焦點(diǎn)的功能。

但是任性的用戶強(qiáng)烈要求一定要有 Enter 鍵切換焦點(diǎn)的功能。

為了交付上線拿到錢,我們只好再一次毫無原則性的接受了客戶的需求。

在上一代人中,大多都有這種操作習(xí)慣。習(xí)慣把保存成為編輯,習(xí)慣用回車替換 Tab。這是受到微軟 excel 荼毒的結(jié)果。

起初我以為這個(gè)功能很簡(jiǎn)單,無非就是把 Enter 鍵的功能轉(zhuǎn)接到 Tab 鍵上面,分分鐘就可以解決掉的問題。

可困難馬上就出現(xiàn)了,我發(fā)現(xiàn)這條路是走不通的。

我們經(jīng)??梢灾鲃?dòng)觸發(fā)某個(gè)事件,比如 el.click() 就可以調(diào)用點(diǎn)擊事件,或者使用 dispatchEvent 。但是鍵盤和鼠標(biāo)事件卻不行。

我查閱了很多資料,也做了很多嘗試。最后總結(jié)出來一個(gè)結(jié)論,在瀏覽器中,JavaScript 無法操作用戶的鍵盤或者鼠標(biāo),這是出于安全策略的考慮。仔細(xì)想一下,如果可以用一段 JavaScript 腳本控制用戶鍵盤和鼠標(biāo)的話,那么用戶只需要打開一個(gè)黑客網(wǎng)站,黑客就可以瞬間得到他想得到的一切。

所以,如果要通過除 Tab 鍵以外的其他方式來觸發(fā)焦點(diǎn)切換, focus 幾乎是唯一的選擇。

在原生頁面中實(shí)現(xiàn)回車鍵切換焦點(diǎn)

項(xiàng)目是基于 vue 和 element-ui 做的,為了把實(shí)現(xiàn)思路先講清楚,暫時(shí)把這些拋開,從原生的頁面中尋找答案。

以下是一個(gè)原生的 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>

接下來要實(shí)現(xiàn)通過回車鍵切換焦點(diǎn),我把思路梳理如下:

  1. 監(jiān)聽回車鍵按下事件。
  2. 獲取當(dāng)前聚焦元素。
  3. 獲取下一個(gè)要被聚焦的元素。
  4. 切換焦點(diǎn)。

思路有了,實(shí)現(xiàn)起來也非常簡(jiǎn)單。

1.監(jiān)聽回車鍵按下事件

在文檔中添加 script 標(biāo)簽,寫入如下代碼。

function enterCallback(e) {
 if (e.keyCode === 13) {
 // 按下回車后的邏輯
 }
}
window.addEventListener("keydown", enterCallback);

要注意, enterCallback 單獨(dú)拿出來,用于注銷監(jiān)聽事件。

監(jiān)聽按鍵事件最常用的方法就是使用事件委托,將事件綁定到 window 對(duì)象上。相比較給每一個(gè)元素都綁定一個(gè)事件的方式,這樣做的最大好處就是節(jié)省內(nèi)存空間,性能更好。

判斷按下哪個(gè)鍵的方式有很多,比如判斷 e.keye.code 或者 e.keyCode 等方式。但絕大多數(shù)的情況下都建議使用 e.keyCode 。下面是一張來自網(wǎng)絡(luò)的 keyCode 表。

2.獲取當(dāng)前聚焦元素

很容易就可以做到這一步。

常見的有兩種方式。第一種是 e.target ,第二種是 document.activeElement 。這種情況下,個(gè)人更推薦使用第二種。

function enterCallback(e) {
 if (e.keyCode === 13) {
 let activeEl = document.activeElement;
 }
}

3.獲取下一個(gè)要被聚焦的元素

這一步也比較容易。使用 el.nextElementSibling API 即可獲取。

function enterCallback(e) {
 if (e.keyCode === 13) {
 let activeEl = document.activeElement;
 let nextEl = activeEl.nextElementSibling;
 }
}

4.切換焦點(diǎn)

切換焦點(diǎn)調(diào)用 focus 即可實(shí)現(xiàn)。

function enterCallback(e) {
 if (e.keyCode === 13) {
 let activeEl = document.activeElement;
 let nextEl = activeEl.nextElementSibling;
 nextEl && nextEl.focus();
 }
}

至此一個(gè)最簡(jiǎn)單的 Demo 已經(jīng)實(shí)現(xiàn)了,接下來看看項(xiàng)目中實(shí)際的情況。

在 element-ui 項(xiàng)目中實(shí)現(xiàn)回車鍵切換焦點(diǎn)

因?yàn)槭鞘褂媒M件開發(fā),加上樣式等因素,dom 節(jié)點(diǎn)并不像上面寫的原生 Demo 那么簡(jiǎn)單,實(shí)際情況是多層嵌套的。下面是實(shí)際生成的代碼結(jié)構(gòu)。

<div
 class="el-form-item el-form-item--small"
 style="margin-bottom: 0vh; width: 25%; display: inline-block;"
>
 <label for="pactcode" class="el-form-item__label" style="width: 130px;"
 >協(xié)議號(hào)</label
 >
 <div class="el-form-item__content" style="margin-left: 130px;">
 <div class="el-input el-input--small">
 <!---->
 <input
 type="text"
 autocomplete="off"
 id="el-input"
 placeholder="未填寫協(xié)議號(hào)"
 class="el-input__inner"
 />
 <!---->
 </div>
 </div>
</div>

可以看到,如果每一個(gè)輸入框都是這種類型的嵌套結(jié)構(gòu),上面的方法是無法直接解決的。因?yàn)?nextElementSibling API 只能找到下一個(gè)兄弟元素,而在這里 input 明顯找不到下一個(gè)兄弟元素。

思路是,通過回溯的手段朝外層尋找,直到找到一個(gè)類名包含 el-form-itemel-form-item--small 的祖級(jí)元素,然后再從這個(gè)祖級(jí)元素的下一個(gè)兄弟元素中尋找類名包含 el-input__inner 的 input 元素。

所以要再寫兩個(gè)函數(shù),分別是尋找組件元素的 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;
}

有了這兩個(gè)函數(shù)以后,實(shí)現(xiàn)回車切換焦點(diǎn)就非常簡(jiǎn)單了。只需要執(zhí)行兩行代碼。

const container = findFormItem(document.activeElement);
findInput(container) && findInput(container).focus();

完整的代碼大概是這樣的。

methods 中聲明三個(gè)方法。

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 中添加回車監(jiān)聽和在 destroy 中移除回車鍵聽。

mounted() {
 this.addEnterListener();
},
destroy() {
 this.removeEnterListener();
},

需要注意的是,項(xiàng)目是多標(biāo)簽頁的形式,表單組件可能會(huì)被渲染多次,所以通過在 window 對(duì)象上添加一個(gè) __completeEnterBind__ 字段來確保回車換行事件正確綁定。

總結(jié)

以上所述是小編給大家介紹的Vue中實(shí)現(xiàn)回車鍵切換焦點(diǎn)的方法,希望對(duì)大家有所幫助,也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Vue項(xiàng)目啟動(dòng)白屏問題的幾種解決辦法

    Vue項(xiàng)目啟動(dòng)白屏問題的幾種解決辦法

    這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目啟動(dòng)白屏問題的幾種解決辦法,Vue項(xiàng)目打包后出現(xiàn)白屏的可能原因有很多,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • vue實(shí)現(xiàn)動(dòng)態(tài)綁定行內(nèi)樣式style的backgroundImage

    vue實(shí)現(xiàn)動(dòng)態(tài)綁定行內(nèi)樣式style的backgroundImage

    這篇文章主要介紹了vue實(shí)現(xiàn)動(dòng)態(tài)綁定行內(nèi)樣式style的backgroundImage方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • vue2和vue3的v-if與v-for優(yōu)先級(jí)對(duì)比學(xué)習(xí)

    vue2和vue3的v-if與v-for優(yōu)先級(jí)對(duì)比學(xué)習(xí)

    這篇文章主要介紹了vue2和vue3的v-if與v-for優(yōu)先級(jí)對(duì)比學(xué)習(xí),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Vue3報(bào)錯(cuò)‘defineProps‘?is?not?defined的解決方法

    Vue3報(bào)錯(cuò)‘defineProps‘?is?not?defined的解決方法

    最近工作中遇到vue3中使用defineProps中報(bào)錯(cuò),飄紅,所以這篇文章主要給大家介紹了關(guān)于Vue3報(bào)錯(cuò)‘defineProps‘?is?not?defined的解決方法,需要的朋友可以參考下
    2023-01-01
  • VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲

    VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲

    這篇文章主要介紹了VUE+Canvas實(shí)現(xiàn)財(cái)神爺接元寶小游戲,需要的朋友可以參考下本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-04-04
  • Vue 實(shí)現(xiàn)前端權(quán)限控制的示例代碼

    Vue 實(shí)現(xiàn)前端權(quán)限控制的示例代碼

    這篇文章主要介紹了Vue 實(shí)現(xiàn)前端權(quán)限控制的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Vue實(shí)現(xiàn)時(shí)間軸功能

    Vue實(shí)現(xiàn)時(shí)間軸功能

    這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)時(shí)間軸功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 手寫vue無限滾動(dòng)指令的詳細(xì)過程

    手寫vue無限滾動(dòng)指令的詳細(xì)過程

    今天在移動(dòng)端項(xiàng)目中遇見一個(gè)需求,需要數(shù)據(jù)無限滾動(dòng),所以下面這篇文章主要給大家介紹了關(guān)于手寫vue無限滾動(dòng)指令的詳細(xì)過程,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • Vue 打包上線后的緩存問題解決

    Vue 打包上線后的緩存問題解決

    在使用vue腳手架搭建前端工程時(shí),經(jīng)常會(huì)遇到打包上線后的緩存問題,許多開發(fā)者會(huì)直接在index.html中加入類似以下代碼來解決緩存問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-11-11
  • Vue2路由動(dòng)畫效果的實(shí)現(xiàn)代碼

    Vue2路由動(dòng)畫效果的實(shí)現(xiàn)代碼

    本篇文章主要介紹了Vue2路由動(dòng)畫效果的實(shí)現(xiàn)代碼,可以根據(jù)不同的路徑去改變動(dòng)畫的效果,有興趣的可以了解一下
    2017-07-07

最新評(píng)論