Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
近,知乎在桌面端網頁上陸續增加了一些快捷鍵:
在非輸入狀態下按 ?(Shift+/)就可以查看快捷鍵列表
在開發快捷鍵的過程中,有一些值得分享的經驗。
實現快捷鍵不困難,因為監聽鍵盤事件很簡單。大部分時候,我們只需要在希望響應事件的最外層元素上注冊事件就行,而響應事件的回調(比如關閉模態框)也都可以在這個最外層組件內實現。
知乎首頁的組件結構
但是這次的情況要更加復雜。以在首頁按 V 贊同答案為例:列表內的時間線條目(FeedItem)包括了回答(AnswerItem)在內各種類型的內容,而在回答里的贊同按鈕(VoteButton)才是適合響應快捷鍵事件的地方。在最外側的 FeedItem 上容易注冊事件卻無法響應事件,在最內側的 VoteButton 中可以響應事件卻不能簡單地注冊事件。
如何在 React 的組件關系中優雅地實現子組件(贊同、收藏按鈕等)注冊快捷鍵和回調函數、同時直到父組件(整個回答甚至 Feed 條目)的范圍內都可以響應快捷鍵是比較有趣的。
一種簡單的想法是:放棄在子組件中注冊快捷鍵,全部在父組件中注冊快捷鍵,在回調的時候調用子組件的實例方法。這會造成以下這些問題:
現在知乎使用的方案是:基于 React context 來為所有子組件共享一個「快捷鍵實例」,在這個「作用域」下的所有子組件聲明快捷鍵時,都會注冊到這個實例上面。
參考下方的偽代碼:
function FeedItem() {
const feedItemElement = useRef(null)
return (
<ShortcutContext value={feedItemElement}>
<div className="FeedItem" ref={feedItemElement}>
<AnswerItem />
</div>
</ShortcutContext>
)
}
在 FeedItem 中,以自身的 HTML element 來初始化一個新的快捷鍵實例并設置在 context 中,實際的 keydown 等鍵盤事件是注冊在這個 element 上。所以子組件都可以通過 context 在這個實例上注冊新的快捷鍵。
function VoteButton() {
const handleVote = () => console.log('voting')
// 在 useShortcut 中查找當前 context 中存在的快捷鍵實例,并注冊在實例上
useShortcut('v', handleVote)
return <button onClick={handleVote}>贊同</button>
}
在 VoteButton 中,就可以像響應點擊事件一樣注冊并響應快捷鍵事件,看起來和寫起來都非常清爽。
使用 J、K 進行 Vim 風格的列表導航是許多網站常見的快捷鍵設計[2]。下面是一些如果從零開始實現時,可能會遇到的細節問題:
當使用快捷鍵進行瀏覽時,「知道光標在哪里」很重要。屏幕閱讀器可以閱讀當前 focus 元素的內容。如果不通過聲音的話、就只能通過視覺樣式來知道當前正在 focus 的元素是什么。
Chrome 為 Input 標簽默認添加的 focus outline
瀏覽器默認會為可 focus 的元素通過 :focus 偽類增加一個 outline 樣式,因為這個樣式不是很好看,再加上可 focus 的元素往往也會單獨設計一些響應點擊的樣式,所以一般產品或設計會要求工程師取消掉該樣式。但是如果簡單取消所有 focus 樣式后,用鼠標當然知道「我在點哪里」,但在使用鍵盤訪問的場合就根本不知道「我在哪里」了。
最優雅的方案是使用 CSSWG 的 :focus-visible 偽類來添加 focus 樣式(同時禁用原先的 :focus 樣式),在 WICG 對該樣式的 polyfill 中有詳細的介紹。簡單來說,就是「只有用鍵盤觸發的 focus 才應該添加 focus 樣式」。
知乎按鈕的 focus 樣式
知乎通過和該 polyfill 類似的思想實現了這一設計:在使用鍵盤操作后,會為 <html> 元素添加 data-focus-visible 屬性。只有在包含該屬性的情況下,各個元素才會添加 focus 樣式。而且知乎還修改了默認的樣式、更為美觀。你可以使用 Tab 鍵 tab 到贊同按鈕上查看這個效果。
在開發這一部分功能的時候,還有一個特殊的設計:使用 ?+C 等快捷鍵進行復制粘貼操作(準確地說,是按鍵中包括 Control 或 Shift 等 Modifier Key)時,不認為是一般的鍵盤操作,也不展現 focus outline,否則 outline 會過于頻繁地時有時無。有意思的是,Twitter 其實也已經做了類似的處理,讓人感到大洋兩岸的工程師都在為用戶體驗而努力…
很多關于快捷鍵的討論都會有視障用戶的參與,因為使用屏幕閱讀器瀏覽網頁、必須使用包括 Tab 鍵在內的各種鍵盤快捷鍵進行光標定位與操作,他們是「最會用鍵盤刷知乎」的人。但是,對視障用戶的支持遠不止添加快捷鍵這么簡單。
@devil纏
在一個答案的評論區[6]提到:
如果只是單個按鍵,(快捷鍵)基本上沒有任何用處。以 V 為例:當用 Tab 到達「贊同」按鈕時,直接(按)空格就可以點贊同。(另外)如果在查看內容區點擊 V,焦點不會跑到「贊同」按鈕上。
合理的快捷鍵有可能用處不大,而不合理的快捷鍵不但不能幫助視障用戶,還會幫倒忙。
@殷曉波
和
@devil纏
都提到「使用 V 贊同之后,希望可以 focus 到贊同按鈕」,如果不真正使用屏幕閱讀器瀏覽網頁,是無法想象這句話的原因的:
快捷鍵贊同后,需要轉移焦點
簡單來說,屏幕閱讀器只有在焦點改變時才會閱讀焦點內的文字,它監控不到「贊同按鈕變深藍」這樣普通人可以輕松理解的設計反饋。如果使用快捷鍵贊同后不改變焦點,連按下鍵盤發生了什么都不知道,也就不會知道「已經贊同了答案」。此時 tab 到贊同按鈕上閱讀到「已贊同」的文字才知道發生了什么就很奇怪。
瀏覽器的點擊行為會自動 focus 在可交互的元素上(例如 <button> 或 <a>),而此時按 Enter 或 Space 等快捷鍵可以「模擬一次點擊」,這套現成的體系很容易被忽略。在實際體驗中,tab 到「閱讀全文」按鈕再按 Space 來展開全文并不比用快捷鍵 O 來展開全文麻煩很多。
除此之外,很多讀屏軟件或者視障用戶也會定義、開發個性化的快捷鍵[6]。這么來看,使用 <button> 等語義化標簽使元素可交互元素也可以被 focus、盡可能使用 <a> 而不是在監聽 onClick 事件時使用 location.href 進行頁面跳轉、配置好 aria 屬性等…對 Accessibility 更有意義。
總的來說,實現快捷鍵和實現其他功能一樣也要注意視障用戶的使用、交互體驗,比如:
快捷鍵只是 Accessibility 的一部分,而可訪問性又是一個更加系統和復雜的工程。知乎做了一些努力[7],但還遠遠不夠。也歡迎對這個領域有更多了解的朋友提出建議。
是的。如果你使用 Vimperator 或者 Vimium 等瀏覽器擴展定制了快捷鍵而不想和知乎的沖突,可以在桌面端網頁的個人偏好設置(https://www.zhihu.com/settings/preference)中關閉快捷鍵[8]。
這是編輯器的新功能,會在開放后再行介紹。
^這些快捷鍵在遷移到新版 Web 頁面時沒有同步遷移,在很長一段時間內都沒有實現。
^包括 Twitter、Facebook、Gmail 與新浪微博等,知乎從這些網站的實現細節中受益良多。
^一個叫 tabbable 的庫中有關于這兩者區別的介紹,這個庫在實現 focus trap 等效果時很有用。 https://github.com/davidtheclark/tabbable
^如何高效地查找離視窗最近、滾動距離最小的元素,這個算法比較有意思,這里不贅述了。
^知乎和 Facebook 與新浪微博一樣,會選中視野內可見的新元素,而 Twitter 會放棄滾動。
^ab根據 @devil纏 在這個答案評論區中的說法,他使用的讀屏環境還會定義包括 K 下跳 10 個鏈接、Shift+K 上跳 10 個鏈接等快捷鍵 https://www.zhihu.com/question/19842222/answer/17152043
^@長天之云 的答案介紹了一些知乎對 a11y 的支持 https://www.zhihu.com/question/20487917/answer/15265930
^只在當前使用的瀏覽器中生效。
作者:孫北吉
出處:https://zhuanlan.zhihu.com/p/59928288
在的瀏覽器普遍都支持Javascript,客戶的瀏覽器都安裝了好幾種。這里我們對javascipt做個初步的介紹。
javascript是一種基于對象和事件并具有安全性能的解釋型腳本語言。不但用于編寫客戶端的腳本程序,由客戶端瀏覽器解釋執行。而且還可以編寫在服務器端執行的腳本程序,由服務器端處理用戶提交的信息并動態地向瀏覽器返回處理結果。
字符串型:使用單引號或者雙引號括起來的一個或者多個字符串
數值型:包括整數或者浮點數(包含小數點的數或者科學計數法的數)
布爾型:true或者false
對象型:用于指定javascript程序中用到的對象
空值:給一個變量賦值null值來清除變量的內容
undefined:表示該變量尚未被賦值
1、變量命名的規則
必須以字母或者下劃線開頭,中間可以是數字、字母或者下劃線。
變量名不能包含空格或加號、減號等符號。
變量名嚴格區分大小寫的。大小寫不一樣代表不同的變量。
變量名不能使用關鍵字。
關鍵字和java的關鍵字類似。這里不列舉。
2、聲明和賦值
var variable; //聲明一個變量
var variable=10; //聲明并賦值11
var sum,avg; //聲明多個變量
var sum=0,avg=10; //聲明多個變量并賦值
Javascript的函數和語句和php有相通的地方。這里就不介紹了。
可以閱讀其他相關教程:https://www.w3school.com.cn/js/index.asp
事件是某些動作發生的時候產生的信號,這些事件隨時可以發生。引起事件的發生的動作成為觸發事件。比如鼠標點擊了某個按鈕,用戶在文本框輸入文字都會有對應的觸發事件。
下面是常見的事件:
onchange | HTML 元素已被改變 |
onclick | 用戶點擊了 HTML 元素 |
onmouseover | 用戶把鼠標移動到 HTML 元素上 |
onmouseout | 用戶把鼠標移開 HTML 元素 |
onkeydown | 用戶按下鍵盤按鍵 |
onload | 瀏覽器已經完成頁面加載 |
其他事件可以查看手冊:
https://www.w3school.com.cn/js/js_events.asp
https://www.w3school.com.cn/jsref/jsref_events.asp
https://www.w3school.com.cn/jsref/dom_obj_event.asp
1、在html中嵌入javascript腳本
在html中使用<script>標記就可以嵌入到html中
<script language="javascript">
....
</script>
language標記的是設置腳本語言的名稱和版本,也可以不設置該屬性,瀏覽器默認使用javascript腳本預約進行處理。
2、在網頁中引用Js文件
不管是在php,還是其他語言上甚至是普通的html頁面上,都可以使用外置的腳本文件來調用javascipt腳本
<script src="url" language="javascript"></script>
src的url是js文件的路徑,language的作用和上面的一樣。使用腳本文件不僅可以在html中結合使用,還可以與php動態網頁結合使用。使用外部js文件的優點如下:
將javascript代碼從網頁中獨立出來,方便代碼閱讀
一個外部js文件可以同時被多個頁面調用。需要修改代碼,只需要修改js文件的代碼,方便代碼維護。
通過script不僅可以調用自己服務器的上面的js文件,也可以通過路徑調用其他服務器上的js文件。
注意:在js文件中,只能包含javascript腳本代碼,不能包含<script>標記和html代碼,不然會產生錯誤。
在引用js文件的<script>和</script>標記的中間不能有其他的javascript代碼,即使存在了瀏覽器也是會忽略這寫代碼,而只執行js文件中的javascript代碼
3、頁面中調用自定義函數
這個就是前面說道的事件,根據事件調用自定義函數。
<button type="button" onclick="check();"> 提交 </button>
提交按鈕綁定了一個點擊事件,調用check()函數。
1、開啟瀏覽器對Javascript的支持
有些瀏覽器是出于安全考慮關閉了對javascript的支持,所以可以直接通過瀏覽器啟用對javascript的支持。
2、使用注釋符號驗證瀏覽器的支持
如果用戶不確定自己的瀏覽器是否支持javascript腳本,可以使用html的注釋符號來進行驗證。Html注釋符號“<!--”開始,以“-->”結束。如果此注釋符號里的javascript腳本在不支持javascript的瀏覽器,會把javascript腳本作為注釋而不會顯示在客戶瀏覽器上。
<script type="text/javascript">
<!--
//即使不支持Javascript腳本,用戶也看不到這里面的代碼
var a={};
a[“stu”] = null;
-->
</script>
3、使用<noscript>標記驗證瀏覽器的支持
除了上面的方式,還可以使用<noscript>標記來進行驗證。
如果瀏覽器支持Javascript腳本,那么瀏覽器會忽略<noscript>...</noscript>標記中間的任何內容,反之不支持會把這標記中間的內容顯示出來。用來提醒瀏覽者當前使用瀏覽器是否支持Javascript腳本。
文章有
ctrl+s一鍵提交的功能時候,真的是會方便很多,對于我們這些高度使用pc,并且熟悉PC快捷鍵的使用者來說,如何實現html響應ctrl+s快捷鍵,下面我分享一個簡單的代碼給大家。
$(window).keydown( function (event) {
if(event.ctrlKey && window.event.keyCode==83 ){
$("#submit").click()
return false
}
}) ;
當使用ctrl+s組合快捷鍵的時候,我們模擬了submit的點擊事件進行提交文章。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。