用 Javascript 實現(xiàn)空格鍵功能

最近在做 Accessibility 相關(guān)的東西時候,又發(fā)現(xiàn)了一個坑,就是跟這個看似完美的tabindex=0的有關(guān)笔诵。

其實究其原因,還是年輕的我不仔細(xì)看文檔導(dǎo)致的姑子,但我覺得文檔沒有特別強調(diào)的但是確實很重要的東西就有可能是未來的坑乎婿,所以還是想分享一下給大家。

要實現(xiàn)的需求大概是這樣的

有一個選擇框是這個樣子的街佑,我們叫它 可以搜索的 Listbox谢翎,可以點擊打開里面的List選擇,也可以點擊輸入你想要的國家英文名稱沐旨,它會模糊進行 Filter給出你想要的結(jié)果森逮。

但我們今天想說的不是它的搜索和選擇功能,而是你看到的這個組件的無障礙可訪問功能(Web Accessibility)中的輸入空格的功能磁携。

可能你還是不是太明白褒侧,再看個圖吧,我在按下了 Tab 鍵之后,這個 Listbox會被聚焦闷供,并且有藍色的邊框烟央,這個就是用這行代碼實現(xiàn)的。

//偽代碼
<div tabindex="0" role="listbox">
  <input tabindex="-1" />
</div>

在我添加了一系列點擊事件之后歪脏,我發(fā)現(xiàn)一旦它被Focus之后疑俭,按下空格和回車鍵的時候,它就會依次打開婿失、關(guān)閉怠硼,心中竊喜,簡直完美移怯,也沒有仔細(xì)看原因.......

然后呢,再測試的時候就有問題了这难,當(dāng)我在輸入框輸入一串字符舟误,接著想輸入一個空格的時候,我的Listbox 直接就給我合上了姻乓,這是怎么回事呢嵌溢,什么都沒干呢,怎么會有這種Bug蹋岩,我輸?shù)拿髅魇强崭裱嚼挡荩业目崭衲娜チ四?..

按 Tab 鍵之后打開 Listbox

果然多看文檔才是王道呀

人家大大的 Important 寫著 加了 tabindex=0的元素也就意味著會是以按鈕形式顯示的元素,必須是響應(yīng) Enter 和 Spacebar 鍵的

這樣一看剪个,為什么我加了點擊和關(guān)閉事件以后秧骑,默認(rèn)回車和空格鍵就生效了,你找個 Accessibility 做的好的頁面扣囊,隨便 Tab 一個 Button乎折,人家按回車和空格都是可以 work 的呀。

自然侵歇,在我沒有自定義任何響應(yīng)空格鍵的方法的情況下骂澄,輸入框里輸入空格,它不關(guān)閉我的 Listbox 才怪呢惕虑。

那么這下我就知道該做什么了坟冲,自定義按空格鍵的事件把默認(rèn)的覆蓋不就好了。

//偽代碼
<div tabindex="0" role="listbox">
   <input onKeyDown={ this.onKeyDown} ref={input => {this.textBox=input;}}
/>
</div>

//偽代碼
onKeyDown = event => {
    if(event.keyCode === 32) {
        event.preventDefault(); //禁用默認(rèn)的打開關(guān)閉事件
        this.input.value = this.input.value.concat(' '); //更新 input 輸入的值為添加了空字符串的 string
        }
}

看著很健康溃蔫,很完美健提,誘人的空格就這樣出來了。


但是我發(fā)現(xiàn)好像忘了按空格了伟叛,讓我再回去加個空格矩桂。

崩了,我還能說什么呢,只傻傻的給后面追加空字符串是真的不行啊侄榴,無論在哪里按空格雹锣,都是在最后面追加。

正確的思路應(yīng)該是這樣的

  • 獲取光標(biāo)所在的位置
  • 在光標(biāo)的位置加空格癞蚕,重新拼接輸入的字符串
  • 更新 input 的值
  • 讓添加空格之后的光標(biāo)位置保持的原位置

但是要怎么獲取光標(biāo)的位置蕊爵,得解決這個問題,搜了很多資料加動了一些小腦筋之后桦山,才發(fā)現(xiàn)兩行代碼就搞定了攒射,這下才是真的完美。

if(event.KeyCode === 32) {
            event.preventDefault(); //同樣禁用默認(rèn)的打開關(guān)閉事件
            const caretIndex = this.input.selectionStart; //獲取光標(biāo)的位置恒水,其實是用了做選中一段文字的起始位置的接口
            const inputedText = `${this.input.value.slice(0, caretIndex)} ${this.input.value.slice(caretIndex)}`; //將空字符串加到光標(biāo)所在的位置
            this.input.value = inputedText; //更新 input 的值
            this.setState({ //這時候默認(rèn)加的空格是不會觸發(fā) input 的 onchange 事件的会放,同樣需要手動 trigger
                inputedText,
            });
            this.input.focus(); //從這里開始是移動光標(biāo)到加了空格的地方,如果沒有這兩行钉凌,那么添加完空格之后咧最,光標(biāo)默認(rèn)還是會回到輸入值的最后
            this.input.selectionEnd = caretIndex + 1;  //還是用了做選中一段文字的相關(guān)結(jié)果,不過是設(shè)置結(jié)束位置的光標(biāo)
          // this.input.setSelectionRange(caretIndex + 1, caretIndex + 1); 同樣也可以用這種思路實現(xiàn)御雕,將要選擇的范圍起點的終點設(shè)在同一個位置
        }

實現(xiàn)一個空格鍵的功能并沒有那么難吧矢沿,總之,還有兩個比較重要的點酸纲。

在用一個自己不那么熟悉的東西的時候捣鲸,不管你開始看的是中文的還是哪里的文檔,最終一定要仔細(xì)看看官方的文檔闽坡,坑很容易就從眼皮底下溜了的

在網(wǎng)上搜答案的時候栽惶,不要一味復(fù)制粘貼,發(fā)現(xiàn)一個不行疾嗅,兩個還是不行媒役,稍微搜一下用法的文檔,自己再多想那么一丟丟宪迟,可能問題一下子就有了答案酣衷。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市次泽,隨后出現(xiàn)的幾起案子穿仪,更是在濱河造成了極大的恐慌,老刑警劉巖意荤,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啊片,死亡現(xiàn)場離奇詭異,居然都是意外死亡玖像,警方通過查閱死者的電腦和手機紫谷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人笤昨,你說我怎么就攤上這事祖驱。” “怎么了瞒窒?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵捺僻,是天一觀的道長。 經(jīng)常有香客問我崇裁,道長匕坯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任拔稳,我火速辦了婚禮葛峻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巴比。我一直安慰自己术奖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布匿辩。 她就那樣靜靜地躺著,像睡著了一般榛丢。 火紅的嫁衣襯著肌膚如雪铲球。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天晰赞,我揣著相機與錄音稼病,去河邊找鬼。 笑死掖鱼,一個胖子當(dāng)著我的面吹牛然走,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戏挡,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芍瑞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了褐墅?” 一聲冷哼從身側(cè)響起拆檬,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎妥凳,沒想到半個月后竟贯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡逝钥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年屑那,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡持际,死狀恐怖沃琅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情选酗,我是刑警寧澤阵难,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站芒填,受9級特大地震影響呜叫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜殿衰,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一朱庆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闷祥,春花似錦娱颊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悟衩,卻和暖如春剧罩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背座泳。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工惠昔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挑势。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓镇防,卻偏偏與公主長得像,于是被迫代替她去往敵國和親潮饱。 傳聞我的和親對象是個殘疾皇子来氧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,601評論 2 353