接到一個需求:點擊頁面連接時按住 Ctrl
按鍵則以新窗口形式打開該連接,原頁面不進行跳轉,這個需求比較棒,它保證了頁面跳轉時的靈活性。html
這個需求實現的重點是在何處添加判斷是否以新窗口打開
的代碼,好比在每一個連接點擊的地方加入邏輯判斷,這是最差的實現,由於這種方法改動點很大,並且沒法自動兼容新連接的添加。而後可能想到的是攔截 $router.push
行爲,或者封裝一個自定義指令,再在合適的地方添加指令,這些都是否是很好的實現方式,咱們應該考慮如何以最小的改動而且向後兼容,那就是在 全局的 beforeEach 路由守衛
中添加邏輯。vue
咱們須要維護一個記載當前按鍵的數據,用來幫助咱們判斷 Ctrl
鍵是否按下。markdown
首先咱們在項目中維護公共函數的地方新建一個 keyboard.js
文件。函數
const keys = {}
export function addKeyboardKey (e) {
// 別用已經廢棄的 keycode 字段
keys[e.key] = true
}
export function removeKeyboardKey (e) {
delete keys[e.key]
}
export function isCtrlPress(e) {
return keys['Control']
}
複製代碼
而後尋找一個合適的地方添加鍵盤的事件監聽,好比在 App.vue
的 created
中。oop
// 下面只展現需求相關代碼
import { removeKeyboardKey, addKeyboardKey } from '@/utils/keyboard'
export default {
created () {
// 添加監聽
window.addEventListener('keydown', addKeyboardKey)
window.addEventListener('keyup', removeKeyboardKey)
// 記住添加事件和卸載事件老是成對存在
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('keydown', addKeyboardKey)
window.removeEventListener('keyup', removeKeyboardKey)
})
}
}
複製代碼
至此咱們已經完成了記錄頁面中的當前按下按鍵。ui
咱們在路由的全局守衛 beforeEach
中添加控制的代碼。this
// 下面只展現需求相關代碼
import { isCtrlPress } from '@/utils/keyboard'
// 這裏省略了router的建立,router是VueRouter的實例
router.beforeEach((to, from, next) => {
// 在每次路由跳轉的時候進行判斷
if (isCtrlPress()) {
// 若是 ctrl 按鍵被按下,則以新窗口打開目標頁面
window.open('#' + to.fullPath)
// 並阻止當前頁面的跳轉
return next(false)
}
// 其餘的代碼,注意保證next至少和至多被調用一次
// ...
}
複製代碼
如今咱們就已經完成了點擊頁面連接時按住 Ctrl
按鍵則以新窗口形式打開該頁面 😀。spa
文章首發在個人我的博客,原文連接,歡迎轉載,轉載請註明出處 😀。code