[極致用戶體驗] 你的 Link Button 能讓用戶選擇新頁面打開嗎?
點擊上方?前端陽光,關注公眾號
回復加群,加入技術交流群交流群
作者是公眾號「線下聚會游戲」HullQin,開發(fā)了一些聯機桌游網頁(UNO、斗地主、五子棋等),總結了一些前端經驗,分享給大家。
1. 什么是Link Button?
我想表達的是「需要導航能力的可點擊元素」(Link Button是為了方便溝通而創(chuàng)造的名詞)
我用Link表示導航能力,用Button表示可點擊元素。
什么是導航能力?
切換路由(URL)的能力。
標簽因為href屬性,天然具備導航能力。而標簽沒href,只能在onclick事件中,用JS控制打開新頁面。
2. 用戶怎么選擇新頁面打開?
分2種情況,你可以在掘金頁面試一下:
2.1 新標簽頁(tab)打開
Command(Mac)/Ctrl(Windows) + 鼠標左鍵click鼠標中鍵click 鼠標右鍵click,在菜單選擇“在新標簽頁中打開鏈接” (無障礙)通過 Tab,選中鏈接時,按Command(Mac)/Ctrl(Windows) + 回車鍵Enter
2.2 新窗口(window)打開
Shift?+ 鼠標左鍵click鼠標右鍵click,在菜單選擇“在窗口中打開鏈接” (無障礙)通過 Tab,選中鏈接時,按Shift?+ 回車鍵Enter
3. 什么是極致的用戶體驗?
一切導航功能,都應該給用戶完整的『新窗口』打開能力。
只要你的按鈕會導致頁面切換,就應該允許用戶用1.2提到的任意方式,在新頁面打開。
4. 如何優(yōu)雅的實現“Link Button”
4.1 新手方案:+onclick
我剛學前端時,常常喜歡用實現導航功能,只要在onclick里寫window.open(url)或window.document.href = url或window.location.replace(URL)就好了。
缺點很明顯
4.2 中手方案:+onclick+event
工作2個月后,我懂了點用戶體驗,但知識局限于:用戶點擊Command(Mac)/Ctrl(Windows) + 鼠標左鍵click,可以新標簽頁打開。所以我這么寫:
//?buttonElement?是html中某個
buttonElement.onclick?=?function?(event)?{
??if?(event.ctrlKey?||?event.metaKey)?{
????window.open('某個url');
??}?else?{
????window.document.href?=?'某個url';
??}
};
復制代碼
觸發(fā)onclick時,通過event參數判斷下有沒有按下Ctrl或Command:如果有按下,就新標簽頁打開;否則本頁面跳轉。
其實這種方案只比新手方案好一點點,問題沒有得到根本解。
4.3 高手方案:+onclick+event
工作半年后,同事告訴我中鍵click也能新標簽頁打開。我又學了點html無障礙規(guī)范,才明白一個道理:
導航能力,就交給專業(yè)的標簽做,兼容性最好,能力最全面。
除了天然支持新頁面打開,還有些好處:鼠標Hover上去時,瀏覽器會提示新頁面地址,并且也能直接右鍵復制地址,便于分享!
但是!有2個問題需要解決:
4.3.1 樣式問題
和樣式是有差異的。產品形態(tài)上希望用按鈕,我們就不能用超鏈接樣式。
該問題很好解,把你按鈕樣式復制一份,或者把相關class放到標簽上,就基本一樣了,如果還有樣式差異,就再覆蓋一下的默認樣式(大多數瀏覽器會給它設置字體顏色、下劃線這2個默認樣式):
a,?a:link,?a:visited,?a:hover,?a:active?{
??color:?inherit;
??text-decoration:?none;
}
復制代碼
4.3.2 JS邏輯問題
如果導航,需要其它JS邏輯,就無法只用和href實現,并且這種情況還不少。例如:
跳轉時,需要傳路由state。 某些邏輯,只希望本頁面跳轉時執(zhí)行,不允許新頁面打開時執(zhí)行(因為JS只能執(zhí)行本頁面的JS,如果在新頁面打開,本頁面應該保持不變,不能執(zhí)行那段JS,例如React Router中的 )。某個按鈕,直接點擊時是 window.history.back(),但也允許新窗口打開上個頁面地址(這個問題更加復雜,請期待我的下篇文章,會做詳細講解)
現在我想告訴你:這些問題,也是有解的!
這些問題的解決方案
還記得我曾經是個“中手”嗎?我的“中手方案”剛好可以解決這個難題!把中手方案邏輯改改,就可以了:
//?aElement是html中的某個包含href的元素:?某個鏈接
aElement.onclick?=?function?(event)?{
??if?(event.button?!==?0)?return;
??if?(event.ctrlKey?||?event.metaKey?||?event.shiftKey?||?event.altKey)?return;
??event.preventDefault();
??//?如果用戶期望本頁面跳轉(而非新窗口打開),則執(zhí)行以下邏輯
??window.history.pushState({?pageState:?123?},?'',?'new-page.html');
};
復制代碼
解釋下:
event.button
表示按下的是鼠標哪個按鍵:
0:主按鍵,通常指鼠標左鍵或默認值 1:輔助按鍵,通常指鼠標滾輪中鍵 2:次按鍵,通常指鼠標右鍵 3:第四個按鈕,通常指瀏覽器后退按鈕 4:第五個按鈕,通常指瀏覽器的前進按鈕
這里我們只管理左鍵就好,其它按鍵都保持瀏覽器默認行為(所以非0直接return,不執(zhí)行JS邏輯,執(zhí)行原生行為)。
event.xxxKey
event.ctrlKey: MAC上表示Control鍵,Windows上表示Ctrl鍵。event.metaKey: MAC上表示Command鍵,Windows上表示Windows鍵。event.shiftKey: Shift鍵。event.altKey: MAC上表示Option鍵,Windows上表示Alt鍵。
按照規(guī)范,這些鍵按下時,不應該在本頁面繼續(xù)跳轉,而是會發(fā)生這些事:
ctrlKey?+?click: Mac上表示右鍵點擊該元素,Windows上表示新標簽頁打開頁面。metaKey?+?click: Mac上表示新標簽頁打開頁面,Windows上打開Windows開始菜單。shiftKey?+?click: 新窗口打開頁面。altKey?+?click: 下載頁面。
event.preventDefault()
如果用戶只是普通的左鍵點擊了鏈接,沒按任何xxxKey,就應該阻止標簽默認行為,由我們的JS去接管,自由操控跳轉。
但如果用戶按了任何xxxKey,或是點了鼠標其它鍵,都應該讓瀏覽器接管后續(xù)邏輯。
Oh!真是完美的方案!
5. 寫在最后
如果你像我一樣,喜歡代碼純粹一點,不夾雜冗余功能,就可以自己寫Link Button,封裝自己所需的組件 ??
如果你只是為了完成別人的需求,還是直接用組件庫吧 ??
但是,即使你用組件庫,里面有Menu、Button組件,你一定要想清楚,如果需要頁面跳轉,務必找找Link組件,盡量使用Link來表達導航。
關于導航的用戶體驗,非常細節(jié),太重要了!一個網頁的質量,一個前端開發(fā)者的水平,能直接從導航欄細節(jié)中看出。
最后希望大家都能開發(fā)出用戶體驗完美的“Link Button”!
關于本文
作者:公眾號「線下聚會游戲」HullQin
https://juejin.cn/post/7089483164908781604

往期推薦
我組建了技術交流群,里面有很多?大佬,歡迎進來交流、學習、共建。回復?加群?即可。后臺回復「電子書」即可免費獲取?27本?精選的前端電子書!回復內推,可內推各廠內推碼
???“分享、點贊、在看” 支持一波??

