diff --git a/dist/hotkeys.common.js b/dist/hotkeys.common.js index b2a692fa..652a4ca2 100644 --- a/dist/hotkeys.common.js +++ b/dist/hotkeys.common.js @@ -2,7 +2,7 @@ * hotkeys-js v3.13.3 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies. * - * Copyright (c) 2023 kenny wong + * Copyright (c) 2024 kenny wong * https://github.com/jaywcjlove/hotkeys-js.git * * @website: https://jaywcjlove.github.io/hotkeys-js @@ -19,9 +19,14 @@ function addEvent(object, event, method, useCapture) { if (object.addEventListener) { object.addEventListener(event, method, useCapture); } else if (object.attachEvent) { - object.attachEvent("on".concat(event), () => { - method(window.event); - }); + object.attachEvent("on".concat(event), method); + } +} +function removeEvent(object, event, method, useCapture) { + if (object.removeEventListener) { + object.removeEventListener(event, method, useCapture); + } else if (object.deachEvent) { + object.deachEvent("on".concat(event), method); } } @@ -156,9 +161,9 @@ for (let k = 1; k < 20; k++) { } let _downKeys = []; // 记录摁下的绑定键 -let winListendFocus = false; // window是否已经监听了focus事件 +let winListendFocus = null; // window是否已经监听了focus事件 let _scope = 'all'; // 默认热键范围 -const elementHasBindEvent = []; // 已绑定事件的节点记录 +const elementEventMap = new Map(); // 已绑定事件的节点记录 // 返回键码 const code = x => _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); @@ -235,7 +240,17 @@ function deleteScope(scope, newScope) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; for (i = 0; i < handlers.length;) { - if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; + if (handlers[i].scope === scope) { + const deleteItems = handlers.splice(i, 1); + deleteItems.forEach(_ref2 => { + let { + element + } = _ref2; + return removeKeyEvent(element); + }); + } else { + i++; + } } } } @@ -271,6 +286,7 @@ function unbind(keysInfo) { // unbind(), unbind all keys if (typeof keysInfo === 'undefined') { Object.keys(_handlers).forEach(key => delete _handlers[key]); + removeKeyEvent(null); } else if (Array.isArray(keysInfo)) { // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}]) keysInfo.forEach(info => { @@ -300,13 +316,13 @@ function unbind(keysInfo) { } // 解除绑定某个范围的快捷键 -const eachUnbind = _ref2 => { +const eachUnbind = _ref3 => { let { key, scope, method, splitKey = '+' - } = _ref2; + } = _ref3; const multipleKeys = getKeys(key); multipleKeys.forEach(originKey => { const unbindKeys = originKey.split(splitKey); @@ -317,11 +333,15 @@ const eachUnbind = _ref2 => { // 判断是否传入范围,没有就获取范围 if (!scope) scope = getScope(); const mods = len > 1 ? getMods(_modifier, unbindKeys) : []; + const unbindElements = []; _handlers[keyCode] = _handlers[keyCode].filter(record => { // 通过函数判断,是否解除绑定,函数相等直接返回 const isMatchingMethod = method ? record.method === method : true; - return !(isMatchingMethod && record.scope === scope && compareArray(record.mods, mods)); + const isUnbind = isMatchingMethod && record.scope === scope && compareArray(record.mods, mods); + if (isUnbind) unbindElements.push(record.element); + return !isUnbind; }); + unbindElements.forEach(element => removeKeyEvent(element)); }); }; @@ -445,10 +465,12 @@ function dispatch(event, element) { } // key 不在 _handlers 中返回 if (!(key in _handlers)) return; - for (let i = 0; i < _handlers[key].length; i++) { - if (event.type === 'keydown' && _handlers[key][i].keydown || event.type === 'keyup' && _handlers[key][i].keyup) { - if (_handlers[key][i].key) { - const record = _handlers[key][i]; + const handlerKey = _handlers[key]; + const keyLen = handlerKey.length; + for (let i = 0; i < keyLen; i++) { + if (event.type === 'keydown' && handlerKey[i].keydown || event.type === 'keyup' && handlerKey[i].keyup) { + if (handlerKey[i].key) { + const record = handlerKey[i]; const { splitKey } = record; @@ -465,11 +487,6 @@ function dispatch(event, element) { } } } - -// 判断 element 是否已经绑定事件 -function isElementBind(element) { - return elementHasBindEvent.indexOf(element) > -1; -} function hotkeys(key, option, method) { _downKeys = []; const keys = getKeys(key); // 需要处理的快捷键列表 @@ -528,21 +545,35 @@ function hotkeys(key, option, method) { }); } // 在全局document上设置快捷键 - if (typeof element !== 'undefined' && !isElementBind(element) && window) { - elementHasBindEvent.push(element); - addEvent(element, 'keydown', e => { - dispatch(e, element); - }, capture); + if (typeof element !== 'undefined' && window) { + if (!elementEventMap.has(element)) { + const keydownListener = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + return dispatch(event, element); + }; + const keyupListenr = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + dispatch(event, element); + clearModifier(event); + }; + elementEventMap.set(element, { + keydownListener, + keyupListenr, + capture + }); + addEvent(element, 'keydown', keydownListener, capture); + addEvent(element, 'keyup', keyupListenr, capture); + } if (!winListendFocus) { - winListendFocus = true; - addEvent(window, 'focus', () => { + const listener = () => { _downKeys = []; - }, capture); + }; + winListendFocus = { + listener, + capture + }; + addEvent(window, 'focus', listener, capture); } - addEvent(element, 'keyup', e => { - dispatch(e, element); - clearModifier(e); - }, capture); } } function trigger(shortcut) { @@ -556,6 +587,58 @@ function trigger(shortcut) { }); }); } + +// 销毁事件,unbind之后判断element上是否还有键盘快捷键,如果没有移除监听 +function removeKeyEvent(element) { + const values = Object.values(_handlers).flat(); + const findindex = values.findIndex(_ref4 => { + let { + element: el + } = _ref4; + return el === element; + }); + if (findindex < 0) { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(element) || {}; + if (keydownListener && keyupListenr) { + removeEvent(element, 'keyup', keyupListenr, capture); + removeEvent(element, 'keydown', keydownListener, capture); + elementEventMap.delete(element); + } + } + if (values.length <= 0 || elementEventMap.size <= 0) { + // 移除所有的元素上的监听 + const eventKeys = Object.keys(elementEventMap); + eventKeys.forEach(el => { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(el) || {}; + if (keydownListener && keyupListenr) { + removeEvent(el, 'keyup', keyupListenr, capture); + removeEvent(el, 'keydown', keydownListener, capture); + elementEventMap.delete(el); + } + }); + // 清空 elementEventMap + elementEventMap.clear(); + // 清空 _handlers + Object.keys(_handlers).forEach(key => delete _handlers[key]); + // 移除window上的focus监听 + if (winListendFocus) { + const { + listener, + capture + } = winListendFocus; + removeEvent(window, 'focus', listener, capture); + winListendFocus = null; + } + } +} const _api = { getPressedKeyString, setScope, diff --git a/dist/hotkeys.common.min.js b/dist/hotkeys.common.min.js index 1458cbd8..3f94f965 100644 --- a/dist/hotkeys.common.min.js +++ b/dist/hotkeys.common.min.js @@ -1,2 +1,2 @@ -/*! hotkeys-js v3.13.3 | MIT © 2023 kenny wong https://jaywcjlove.github.io/hotkeys-js */ -"use strict";const isff="undefined"!=typeof navigator&&0{o(window.event)})}function getMods(t,e){var o=e.slice(0,e.length-1);for(let e=0;e_keyMap[e.toLowerCase()]||_modifier[e.toLowerCase()]||e.toUpperCase().charCodeAt(0),getKey=t=>Object.keys(_keyMap).find(e=>_keyMap[e]===t),getModifier=t=>Object.keys(_modifier).find(e=>_modifier[e]===t);function setScope(e){_scope=e||"all"}function getScope(){return _scope||"all"}function getPressedKeyCodes(){return _downKeys.slice(0)}function getPressedKeyString(){return _downKeys.map(e=>getKey(e)||getModifier(e)||String.fromCharCode(e))}function getAllKeyCodes(){const s=[];return Object.keys(_handlers).forEach(e=>{_handlers[e].forEach(e=>{var{key:e,scope:t,mods:o,shortcut:n}=e;s.push({scope:t,shortcut:n,mods:o,keys:e.split("+").map(e=>code(e))})})}),s}function filter(e){var e=e.target||e.srcElement,t=e["tagName"];let o=!e.isContentEditable&&("INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t||e.readOnly)?!0:!1;return o}function isPressed(e){return"string"==typeof e&&(e=code(e)),!!~_downKeys.indexOf(e)}function deleteScope(e,t){var o;let n;e=e||getScope();for(const s in _handlers)if(Object.prototype.hasOwnProperty.call(_handlers,s))for(o=_handlers[s],n=0;ndelete _handlers[e]);else if(Array.isArray(o))o.forEach(e=>{e.key&&eachUnbind(e)});else if("object"==typeof o)o.key&&eachUnbind(o);else if("string"==typeof o){for(var n=arguments.length,s=Array(1{let{key:t,scope:s,method:d,splitKey:i="+"}=e;getKeys(t).forEach(e=>{var e=e.split(i),t=e.length,o=e[t-1],o="*"===o?"*":code(o);if(_handlers[o]){s=s||getScope();const n=1{return!((!d||e.method===d)&&e.scope===s&&compareArray(e.mods,n))})}})};function eventHandler(t,o,n,e){if(o.element===e){let e;if(o.scope===n||"all"===o.scope){e=0{var t=modifierMap[e];o[e]&&!~_downKeys.indexOf(t)?_downKeys.push(t):!o[e]&&~_downKeys.indexOf(t)?_downKeys.splice(_downKeys.indexOf(t),1):"metaKey"!==e||!o[e]||3!==_downKeys.length||o.ctrlKey||o.shiftKey||o.altKey||(_downKeys=_downKeys.slice(_downKeys.indexOf(t)))}),s in _mods){_mods[s]=!0;for(const e in _modifier)_modifier[e]===s&&(hotkeys[e]=!0);if(!n)return}for(const c in _mods)Object.prototype.hasOwnProperty.call(_mods,c)&&(_mods[c]=o[modifierMap[c]]);o.getModifierState&&(!o.altKey||o.ctrlKey)&&o.getModifierState("AltGraph")&&(~_downKeys.indexOf(17)||_downKeys.push(17),~_downKeys.indexOf(18)||_downKeys.push(18),_mods[17]=!0,_mods[18]=!0);var d=getScope();if(n)for(let e=0;e{dispatch(e,i)},y),winListendFocus||(winListendFocus=!0,addEvent(window,"focus",()=>{_downKeys=[]},y)),addEvent(i,"keyup",e=>{dispatch(e,i),clearModifier(e)},y))}function trigger(t){let o=1{_handlers[e].filter(e=>e.scope===o&&e.shortcut===t).forEach(e=>{e&&e.method&&e.method()})})}const _api={getPressedKeyString:getPressedKeyString,setScope:setScope,getScope:getScope,deleteScope:deleteScope,getPressedKeyCodes:getPressedKeyCodes,getAllKeyCodes:getAllKeyCodes,isPressed:isPressed,filter:filter,trigger:trigger,unbind:unbind,keyMap:_keyMap,modifier:_modifier,modifierMap:modifierMap};for(const f0 in _api)Object.prototype.hasOwnProperty.call(_api,f0)&&(hotkeys[f0]=_api[f0]);if("undefined"!=typeof window){const g0=window.hotkeys;hotkeys.noConflict=e=>(e&&window.hotkeys===hotkeys&&(window.hotkeys=g0),hotkeys),window.hotkeys=hotkeys}module.exports=hotkeys; \ No newline at end of file +/*! hotkeys-js v3.13.3 | MIT © 2024 kenny wong https://jaywcjlove.github.io/hotkeys-js */ +"use strict";const isff="undefined"!=typeof navigator&&0_keyMap[e.toLowerCase()]||_modifier[e.toLowerCase()]||e.toUpperCase().charCodeAt(0),getKey=t=>Object.keys(_keyMap).find(e=>_keyMap[e]===t),getModifier=t=>Object.keys(_modifier).find(e=>_modifier[e]===t);function setScope(e){_scope=e||"all"}function getScope(){return _scope||"all"}function getPressedKeyCodes(){return _downKeys.slice(0)}function getPressedKeyString(){return _downKeys.map(e=>getKey(e)||getModifier(e)||String.fromCharCode(e))}function getAllKeyCodes(){const s=[];return Object.keys(_handlers).forEach(e=>{_handlers[e].forEach(e=>{var{key:e,scope:t,mods:n,shortcut:o}=e;s.push({scope:t,shortcut:o,mods:n,keys:e.split("+").map(e=>code(e))})})}),s}function filter(e){var e=e.target||e.srcElement,t=e["tagName"];let n=!e.isContentEditable&&("INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t||e.readOnly)?!0:!1;return n}function isPressed(e){return"string"==typeof e&&(e=code(e)),!!~_downKeys.indexOf(e)}function deleteScope(e,t){var n;let o;e=e||getScope();for(const s in _handlers)if(Object.prototype.hasOwnProperty.call(_handlers,s))for(n=_handlers[s],o=0;o{e=e.element;return removeKeyEvent(e)}):o++;getScope()===e&&setScope(t||"all")}function clearModifier(e){let t=e.keyCode||e.which||e.charCode;var n=_downKeys.indexOf(t);if(n<0||_downKeys.splice(n,1),e.key&&"meta"==e.key.toLowerCase()&&_downKeys.splice(0,_downKeys.length),(t=93!==t&&224!==t?t:91)in _mods){_mods[t]=!1;for(const o in _modifier)_modifier[o]===t&&(hotkeys[o]=!1)}}function unbind(n){if(void 0===n)Object.keys(_handlers).forEach(e=>delete _handlers[e]),removeKeyEvent(null);else if(Array.isArray(n))n.forEach(e=>{e.key&&eachUnbind(e)});else if("object"==typeof n)n.key&&eachUnbind(n);else if("string"==typeof n){for(var o=arguments.length,s=Array(1{let{key:t,scope:r,method:d,splitKey:i="+"}=e;getKeys(t).forEach(e=>{var e=e.split(i),t=e.length,n=e[t-1],n="*"===n?"*":code(n);if(_handlers[n]){r=r||getScope();const o=1{var t=(!d||e.method===d)&&e.scope===r&&compareArray(e.mods,o);return t&&s.push(e.element),!t}),s.forEach(e=>removeKeyEvent(e))}})};function eventHandler(t,n,o,e){if(n.element===e){let e;if(n.scope===o||"all"===n.scope){e=0{var t=modifierMap[e];n[e]&&!~_downKeys.indexOf(t)?_downKeys.push(t):!n[e]&&~_downKeys.indexOf(t)?_downKeys.splice(_downKeys.indexOf(t),1):"metaKey"!==e||!n[e]||3!==_downKeys.length||n.ctrlKey||n.shiftKey||n.altKey||(_downKeys=_downKeys.slice(_downKeys.indexOf(t)))}),e in _mods){_mods[e]=!0;for(const y in _modifier)_modifier[y]===e&&(hotkeys[y]=!0);if(!o)return}for(const p in _mods)Object.prototype.hasOwnProperty.call(_mods,p)&&(_mods[p]=n[modifierMap[p]]);n.getModifierState&&(!n.altKey||n.ctrlKey)&&n.getModifierState("AltGraph")&&(~_downKeys.indexOf(17)||_downKeys.push(17),~_downKeys.indexOf(18)||_downKeys.push(18),_mods[17]=!0,_mods[18]=!0);var s=getScope();if(o)for(let e=0;e{_downKeys=[]},winListendFocus={listener:t,capture:p},addEvent(window,"focus",t,p)))}function trigger(t){let n=1{_handlers[e].filter(e=>e.scope===n&&e.shortcut===t).forEach(e=>{e&&e.method&&e.method()})})}function removeKeyEvent(t){var e,n,o,s=Object.values(_handlers).flat();s.findIndex(e=>{e=e.element;return e===t})<0&&({keydownListener:o,keyupListenr:n,capture:e}=elementEventMap.get(t)||{},o)&&n&&(removeEvent(t,"keyup",n,e),removeEvent(t,"keydown",o,e),elementEventMap.delete(t)),0{var{keydownListener:t,keyupListenr:n,capture:o}=elementEventMap.get(e)||{};t&&n&&(removeEvent(e,"keyup",n,o),removeEvent(e,"keydown",t,o),elementEventMap.delete(e))}),elementEventMap.clear(),Object.keys(_handlers).forEach(e=>delete _handlers[e]),winListendFocus&&({listener:n,capture:o}=winListendFocus,removeEvent(window,"focus",n,o),winListendFocus=null))}const _api={getPressedKeyString:getPressedKeyString,setScope:setScope,getScope:getScope,deleteScope:deleteScope,getPressedKeyCodes:getPressedKeyCodes,getAllKeyCodes:getAllKeyCodes,isPressed:isPressed,filter:filter,trigger:trigger,unbind:unbind,keyMap:_keyMap,modifier:_modifier,modifierMap:modifierMap};for(const J0 in _api)Object.prototype.hasOwnProperty.call(_api,J0)&&(hotkeys[J0]=_api[J0]);if("undefined"!=typeof window){const K0=window.hotkeys;hotkeys.noConflict=e=>(e&&window.hotkeys===hotkeys&&(window.hotkeys=K0),hotkeys),window.hotkeys=hotkeys}module.exports=hotkeys; \ No newline at end of file diff --git a/dist/hotkeys.esm.js b/dist/hotkeys.esm.js index 1369dc31..e7051ecd 100644 --- a/dist/hotkeys.esm.js +++ b/dist/hotkeys.esm.js @@ -2,7 +2,7 @@ * hotkeys-js v3.13.3 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies. * - * Copyright (c) 2023 kenny wong + * Copyright (c) 2024 kenny wong * https://github.com/jaywcjlove/hotkeys-js.git * * @website: https://jaywcjlove.github.io/hotkeys-js @@ -17,9 +17,14 @@ function addEvent(object, event, method, useCapture) { if (object.addEventListener) { object.addEventListener(event, method, useCapture); } else if (object.attachEvent) { - object.attachEvent("on".concat(event), () => { - method(window.event); - }); + object.attachEvent("on".concat(event), method); + } +} +function removeEvent(object, event, method, useCapture) { + if (object.removeEventListener) { + object.removeEventListener(event, method, useCapture); + } else if (object.deachEvent) { + object.deachEvent("on".concat(event), method); } } @@ -154,9 +159,9 @@ for (let k = 1; k < 20; k++) { } let _downKeys = []; // 记录摁下的绑定键 -let winListendFocus = false; // window是否已经监听了focus事件 +let winListendFocus = null; // window是否已经监听了focus事件 let _scope = 'all'; // 默认热键范围 -const elementHasBindEvent = []; // 已绑定事件的节点记录 +const elementEventMap = new Map(); // 已绑定事件的节点记录 // 返回键码 const code = x => _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); @@ -233,7 +238,17 @@ function deleteScope(scope, newScope) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; for (i = 0; i < handlers.length;) { - if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; + if (handlers[i].scope === scope) { + const deleteItems = handlers.splice(i, 1); + deleteItems.forEach(_ref2 => { + let { + element + } = _ref2; + return removeKeyEvent(element); + }); + } else { + i++; + } } } } @@ -269,6 +284,7 @@ function unbind(keysInfo) { // unbind(), unbind all keys if (typeof keysInfo === 'undefined') { Object.keys(_handlers).forEach(key => delete _handlers[key]); + removeKeyEvent(null); } else if (Array.isArray(keysInfo)) { // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}]) keysInfo.forEach(info => { @@ -298,13 +314,13 @@ function unbind(keysInfo) { } // 解除绑定某个范围的快捷键 -const eachUnbind = _ref2 => { +const eachUnbind = _ref3 => { let { key, scope, method, splitKey = '+' - } = _ref2; + } = _ref3; const multipleKeys = getKeys(key); multipleKeys.forEach(originKey => { const unbindKeys = originKey.split(splitKey); @@ -315,11 +331,15 @@ const eachUnbind = _ref2 => { // 判断是否传入范围,没有就获取范围 if (!scope) scope = getScope(); const mods = len > 1 ? getMods(_modifier, unbindKeys) : []; + const unbindElements = []; _handlers[keyCode] = _handlers[keyCode].filter(record => { // 通过函数判断,是否解除绑定,函数相等直接返回 const isMatchingMethod = method ? record.method === method : true; - return !(isMatchingMethod && record.scope === scope && compareArray(record.mods, mods)); + const isUnbind = isMatchingMethod && record.scope === scope && compareArray(record.mods, mods); + if (isUnbind) unbindElements.push(record.element); + return !isUnbind; }); + unbindElements.forEach(element => removeKeyEvent(element)); }); }; @@ -443,10 +463,12 @@ function dispatch(event, element) { } // key 不在 _handlers 中返回 if (!(key in _handlers)) return; - for (let i = 0; i < _handlers[key].length; i++) { - if (event.type === 'keydown' && _handlers[key][i].keydown || event.type === 'keyup' && _handlers[key][i].keyup) { - if (_handlers[key][i].key) { - const record = _handlers[key][i]; + const handlerKey = _handlers[key]; + const keyLen = handlerKey.length; + for (let i = 0; i < keyLen; i++) { + if (event.type === 'keydown' && handlerKey[i].keydown || event.type === 'keyup' && handlerKey[i].keyup) { + if (handlerKey[i].key) { + const record = handlerKey[i]; const { splitKey } = record; @@ -463,11 +485,6 @@ function dispatch(event, element) { } } } - -// 判断 element 是否已经绑定事件 -function isElementBind(element) { - return elementHasBindEvent.indexOf(element) > -1; -} function hotkeys(key, option, method) { _downKeys = []; const keys = getKeys(key); // 需要处理的快捷键列表 @@ -526,21 +543,35 @@ function hotkeys(key, option, method) { }); } // 在全局document上设置快捷键 - if (typeof element !== 'undefined' && !isElementBind(element) && window) { - elementHasBindEvent.push(element); - addEvent(element, 'keydown', e => { - dispatch(e, element); - }, capture); + if (typeof element !== 'undefined' && window) { + if (!elementEventMap.has(element)) { + const keydownListener = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + return dispatch(event, element); + }; + const keyupListenr = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + dispatch(event, element); + clearModifier(event); + }; + elementEventMap.set(element, { + keydownListener, + keyupListenr, + capture + }); + addEvent(element, 'keydown', keydownListener, capture); + addEvent(element, 'keyup', keyupListenr, capture); + } if (!winListendFocus) { - winListendFocus = true; - addEvent(window, 'focus', () => { + const listener = () => { _downKeys = []; - }, capture); + }; + winListendFocus = { + listener, + capture + }; + addEvent(window, 'focus', listener, capture); } - addEvent(element, 'keyup', e => { - dispatch(e, element); - clearModifier(e); - }, capture); } } function trigger(shortcut) { @@ -554,6 +585,58 @@ function trigger(shortcut) { }); }); } + +// 销毁事件,unbind之后判断element上是否还有键盘快捷键,如果没有移除监听 +function removeKeyEvent(element) { + const values = Object.values(_handlers).flat(); + const findindex = values.findIndex(_ref4 => { + let { + element: el + } = _ref4; + return el === element; + }); + if (findindex < 0) { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(element) || {}; + if (keydownListener && keyupListenr) { + removeEvent(element, 'keyup', keyupListenr, capture); + removeEvent(element, 'keydown', keydownListener, capture); + elementEventMap.delete(element); + } + } + if (values.length <= 0 || elementEventMap.size <= 0) { + // 移除所有的元素上的监听 + const eventKeys = Object.keys(elementEventMap); + eventKeys.forEach(el => { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(el) || {}; + if (keydownListener && keyupListenr) { + removeEvent(el, 'keyup', keyupListenr, capture); + removeEvent(el, 'keydown', keydownListener, capture); + elementEventMap.delete(el); + } + }); + // 清空 elementEventMap + elementEventMap.clear(); + // 清空 _handlers + Object.keys(_handlers).forEach(key => delete _handlers[key]); + // 移除window上的focus监听 + if (winListendFocus) { + const { + listener, + capture + } = winListendFocus; + removeEvent(window, 'focus', listener, capture); + winListendFocus = null; + } + } +} const _api = { getPressedKeyString, setScope, diff --git a/dist/hotkeys.js b/dist/hotkeys.js index c80be2cd..1ad197e2 100644 --- a/dist/hotkeys.js +++ b/dist/hotkeys.js @@ -2,7 +2,7 @@ * hotkeys-js v3.13.3 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies. * - * Copyright (c) 2023 kenny wong + * Copyright (c) 2024 kenny wong * https://github.com/jaywcjlove/hotkeys-js.git * * @website: https://jaywcjlove.github.io/hotkeys-js @@ -23,9 +23,14 @@ if (object.addEventListener) { object.addEventListener(event, method, useCapture); } else if (object.attachEvent) { - object.attachEvent("on".concat(event), () => { - method(window.event); - }); + object.attachEvent("on".concat(event), method); + } + } + function removeEvent(object, event, method, useCapture) { + if (object.removeEventListener) { + object.removeEventListener(event, method, useCapture); + } else if (object.deachEvent) { + object.deachEvent("on".concat(event), method); } } @@ -160,9 +165,9 @@ } let _downKeys = []; // 记录摁下的绑定键 - let winListendFocus = false; // window是否已经监听了focus事件 + let winListendFocus = null; // window是否已经监听了focus事件 let _scope = 'all'; // 默认热键范围 - const elementHasBindEvent = []; // 已绑定事件的节点记录 + const elementEventMap = new Map(); // 已绑定事件的节点记录 // 返回键码 const code = x => _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0); @@ -239,7 +244,17 @@ if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; for (i = 0; i < handlers.length;) { - if (handlers[i].scope === scope) handlers.splice(i, 1);else i++; + if (handlers[i].scope === scope) { + const deleteItems = handlers.splice(i, 1); + deleteItems.forEach(_ref2 => { + let { + element + } = _ref2; + return removeKeyEvent(element); + }); + } else { + i++; + } } } } @@ -275,6 +290,7 @@ // unbind(), unbind all keys if (typeof keysInfo === 'undefined') { Object.keys(_handlers).forEach(key => delete _handlers[key]); + removeKeyEvent(null); } else if (Array.isArray(keysInfo)) { // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}]) keysInfo.forEach(info => { @@ -304,13 +320,13 @@ } // 解除绑定某个范围的快捷键 - const eachUnbind = _ref2 => { + const eachUnbind = _ref3 => { let { key, scope, method, splitKey = '+' - } = _ref2; + } = _ref3; const multipleKeys = getKeys(key); multipleKeys.forEach(originKey => { const unbindKeys = originKey.split(splitKey); @@ -321,11 +337,15 @@ // 判断是否传入范围,没有就获取范围 if (!scope) scope = getScope(); const mods = len > 1 ? getMods(_modifier, unbindKeys) : []; + const unbindElements = []; _handlers[keyCode] = _handlers[keyCode].filter(record => { // 通过函数判断,是否解除绑定,函数相等直接返回 const isMatchingMethod = method ? record.method === method : true; - return !(isMatchingMethod && record.scope === scope && compareArray(record.mods, mods)); + const isUnbind = isMatchingMethod && record.scope === scope && compareArray(record.mods, mods); + if (isUnbind) unbindElements.push(record.element); + return !isUnbind; }); + unbindElements.forEach(element => removeKeyEvent(element)); }); }; @@ -449,10 +469,12 @@ } // key 不在 _handlers 中返回 if (!(key in _handlers)) return; - for (let i = 0; i < _handlers[key].length; i++) { - if (event.type === 'keydown' && _handlers[key][i].keydown || event.type === 'keyup' && _handlers[key][i].keyup) { - if (_handlers[key][i].key) { - const record = _handlers[key][i]; + const handlerKey = _handlers[key]; + const keyLen = handlerKey.length; + for (let i = 0; i < keyLen; i++) { + if (event.type === 'keydown' && handlerKey[i].keydown || event.type === 'keyup' && handlerKey[i].keyup) { + if (handlerKey[i].key) { + const record = handlerKey[i]; const { splitKey } = record; @@ -469,11 +491,6 @@ } } } - - // 判断 element 是否已经绑定事件 - function isElementBind(element) { - return elementHasBindEvent.indexOf(element) > -1; - } function hotkeys(key, option, method) { _downKeys = []; const keys = getKeys(key); // 需要处理的快捷键列表 @@ -532,21 +549,35 @@ }); } // 在全局document上设置快捷键 - if (typeof element !== 'undefined' && !isElementBind(element) && window) { - elementHasBindEvent.push(element); - addEvent(element, 'keydown', e => { - dispatch(e, element); - }, capture); + if (typeof element !== 'undefined' && window) { + if (!elementEventMap.has(element)) { + const keydownListener = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + return dispatch(event, element); + }; + const keyupListenr = function () { + let event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.event; + dispatch(event, element); + clearModifier(event); + }; + elementEventMap.set(element, { + keydownListener, + keyupListenr, + capture + }); + addEvent(element, 'keydown', keydownListener, capture); + addEvent(element, 'keyup', keyupListenr, capture); + } if (!winListendFocus) { - winListendFocus = true; - addEvent(window, 'focus', () => { + const listener = () => { _downKeys = []; - }, capture); + }; + winListendFocus = { + listener, + capture + }; + addEvent(window, 'focus', listener, capture); } - addEvent(element, 'keyup', e => { - dispatch(e, element); - clearModifier(e); - }, capture); } } function trigger(shortcut) { @@ -560,6 +591,58 @@ }); }); } + + // 销毁事件,unbind之后判断element上是否还有键盘快捷键,如果没有移除监听 + function removeKeyEvent(element) { + const values = Object.values(_handlers).flat(); + const findindex = values.findIndex(_ref4 => { + let { + element: el + } = _ref4; + return el === element; + }); + if (findindex < 0) { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(element) || {}; + if (keydownListener && keyupListenr) { + removeEvent(element, 'keyup', keyupListenr, capture); + removeEvent(element, 'keydown', keydownListener, capture); + elementEventMap.delete(element); + } + } + if (values.length <= 0 || elementEventMap.size <= 0) { + // 移除所有的元素上的监听 + const eventKeys = Object.keys(elementEventMap); + eventKeys.forEach(el => { + const { + keydownListener, + keyupListenr, + capture + } = elementEventMap.get(el) || {}; + if (keydownListener && keyupListenr) { + removeEvent(el, 'keyup', keyupListenr, capture); + removeEvent(el, 'keydown', keydownListener, capture); + elementEventMap.delete(el); + } + }); + // 清空 elementEventMap + elementEventMap.clear(); + // 清空 _handlers + Object.keys(_handlers).forEach(key => delete _handlers[key]); + // 移除window上的focus监听 + if (winListendFocus) { + const { + listener, + capture + } = winListendFocus; + removeEvent(window, 'focus', listener, capture); + winListendFocus = null; + } + } + } const _api = { getPressedKeyString, setScope, diff --git a/dist/hotkeys.min.js b/dist/hotkeys.min.js index 64771369..e38fb29b 100644 --- a/dist/hotkeys.min.js +++ b/dist/hotkeys.min.js @@ -1,2 +1,2 @@ -/*! hotkeys-js v3.13.3 | MIT © 2023 kenny wong https://jaywcjlove.github.io/hotkeys-js */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).hotkeys=t()}(this,function(){"use strict";var e="undefined"!=typeof navigator&&0{n(window.event)})}function u(t,e){var n=e.slice(0,e.length-1);for(let e=0;eo[e.toLowerCase()]||m[e.toLowerCase()]||e.toUpperCase().charCodeAt(0);function i(e){t=e||"all"}function d(){return t||"all"}function b(n){if(void 0===n)Object.keys(k).forEach(e=>delete k[e]);else if(Array.isArray(n))n.forEach(e=>{e.key&&s(e)});else if("object"==typeof n)n.key&&s(n);else if("string"==typeof n){for(var o=arguments.length,r=Array(1{let{key:t,scope:r,method:i,splitKey:s="+"}=e;h(t).forEach(e=>{var e=e.split(s),t=e.length,n=e[t-1],n="*"===n?"*":K(n);if(k[n]){r=r||d();const o=1{return!((!i||e.method===i)&&e.scope===r&&function(e,t){var n=e.length{var t=p[e];n[e]&&!~w.indexOf(t)?w.push(t):!n[e]&&~w.indexOf(t)?w.splice(w.indexOf(t),1):"metaKey"!==e||!n[e]||3!==w.length||n.ctrlKey||n.shiftKey||n.altKey||(w=w.slice(w.indexOf(t)))}),r in g){g[r]=!0;for(const e in m)m[e]===r&&(E[e]=!0);if(!o)return}for(const a in g)Object.prototype.hasOwnProperty.call(g,a)&&(g[a]=n[p[a]]);n.getModifierState&&(!n.altKey||n.ctrlKey)&&n.getModifierState("AltGraph")&&(~w.indexOf(17)||w.push(17),~w.indexOf(18)||w.push(18),g[17]=!0,g[18]=!0);var i=d();if(o)for(let e=0;e{C(e,s)},p),v||(v=!0,y(window,"focus",()=>{w=[]},p)),y(s,"keyup",t=>{C(t,s);{let e=t.keyCode||t.which||t.charCode;var n=w.indexOf(e);if(n<0||w.splice(n,1),t.key&&"meta"==t.key.toLowerCase()&&w.splice(0,w.length),(e=93!==e&&224!==e?e:91)in g){g[e]=!1;for(const o in m)m[o]===e&&(E[o]=!1)}}},p))}var n={getPressedKeyString:function(){return w.map(e=>{return n=e,Object.keys(o).find(e=>o[e]===n)||(t=e,Object.keys(m).find(e=>m[e]===t))||String.fromCharCode(e);var t,n})},setScope:i,getScope:d,deleteScope:function(e,t){var n;let o;e=e||d();for(const r in k)if(Object.prototype.hasOwnProperty.call(k,r))for(n=k[r],o=0;o{k[e].forEach(e=>{var{key:e,scope:t,mods:n,shortcut:o}=e;r.push({scope:t,shortcut:o,mods:n,keys:e.split("+").map(e=>K(e))})})}),r},isPressed:function(e){return"string"==typeof e&&(e=K(e)),!!~w.indexOf(e)},filter:function(e){var t=(e=e.target||e.srcElement)["tagName"];let n=!e.isContentEditable&&("INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t||e.readOnly)?!0:!1;return n},trigger:function(t){let n=1{k[e].filter(e=>e.scope===n&&e.shortcut===t).forEach(e=>{e&&e.method&&e.method()})})},unbind:b,keyMap:o,modifier:m,modifierMap:p};for(const r in n)Object.prototype.hasOwnProperty.call(n,r)&&(E[r]=n[r]);if("undefined"!=typeof window){const l=window.hotkeys;E.noConflict=e=>(e&&window.hotkeys===E&&(window.hotkeys=l),E),window.hotkeys=E}return E}); \ No newline at end of file +/*! hotkeys-js v3.13.3 | MIT © 2024 kenny wong https://jaywcjlove.github.io/hotkeys-js */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).hotkeys=t()}(this,function(){"use strict";var e="undefined"!=typeof navigator&&0o[e.toLowerCase()]||k[e.toLowerCase()]||e.toUpperCase().charCodeAt(0);function l(e){t=e||"all"}function E(){return t||"all"}function j(n){if(void 0===n)Object.keys(v).forEach(e=>delete v[e]),c(null);else if(Array.isArray(n))n.forEach(e=>{e.key&&s(e)});else if("object"==typeof n)n.key&&s(n);else if("string"==typeof n){for(var o=arguments.length,r=Array(1{let{key:t,scope:i,method:l,splitKey:s="+"}=e;m(t).forEach(e=>{var e=e.split(s),t=e.length,n=e[t-1],n="*"===n?"*":K(n);if(v[n]){i=i||E();const o=1{var t=(!l||e.method===l)&&e.scope===i&&function(e,t){var n=e.lengthc(e))}})};function x(t,n,o,e){if(n.element===e){let e;if(n.scope===o||"all"===n.scope){e=0{var t=u[e];n[e]&&!~w.indexOf(t)?w.push(t):!n[e]&&~w.indexOf(t)?w.splice(w.indexOf(t),1):"metaKey"!==e||!n[e]||3!==w.length||n.ctrlKey||n.shiftKey||n.altKey||(w=w.slice(w.indexOf(t)))}),e in g){g[e]=!0;for(const d in k)k[d]===e&&(L[d]=!0);if(!o)return}for(const p in g)Object.prototype.hasOwnProperty.call(g,p)&&(g[p]=n[u[p]]);n.getModifierState&&(!n.altKey||n.ctrlKey)&&n.getModifierState("AltGraph")&&(~w.indexOf(17)||w.push(17),~w.indexOf(18)||w.push(18),g[17]=!0,g[18]=!0);var r=E();if(o)for(let e=0;e{w=[]},O={listener:t,capture:p},y(window,"focus",t,p)))}function c(t){var e,n,o,r=Object.values(v).flat();r.findIndex(e=>{e=e.element;return e===t})<0&&({keydownListener:o,keyupListenr:n,capture:e}=b.get(t)||{},o)&&n&&(i(t,"keyup",n,e),i(t,"keydown",o,e),b.delete(t)),0{var{keydownListener:t,keyupListenr:n,capture:o}=b.get(e)||{};t&&n&&(i(e,"keyup",n,o),i(e,"keydown",t,o),b.delete(e))}),b.clear(),Object.keys(v).forEach(e=>delete v[e]),O&&({listener:n,capture:o}=O,i(window,"focus",n,o),O=null))}var n={getPressedKeyString:function(){return w.map(e=>{return n=e,Object.keys(o).find(e=>o[e]===n)||(t=e,Object.keys(k).find(e=>k[e]===t))||String.fromCharCode(e);var t,n})},setScope:l,getScope:E,deleteScope:function(e,t){var n;let o;e=e||E();for(const r in v)if(Object.prototype.hasOwnProperty.call(v,r))for(n=v[r],o=0;o{e=e.element;return c(e)}):o++;E()===e&&l(t||"all")},getPressedKeyCodes:function(){return w.slice(0)},getAllKeyCodes:function(){const r=[];return Object.keys(v).forEach(e=>{v[e].forEach(e=>{var{key:e,scope:t,mods:n,shortcut:o}=e;r.push({scope:t,shortcut:o,mods:n,keys:e.split("+").map(e=>K(e))})})}),r},isPressed:function(e){return"string"==typeof e&&(e=K(e)),!!~w.indexOf(e)},filter:function(e){var t=(e=e.target||e.srcElement)["tagName"];let n=!e.isContentEditable&&("INPUT"!==t&&"TEXTAREA"!==t&&"SELECT"!==t||e.readOnly)?!0:!1;return n},trigger:function(t){let n=1{v[e].filter(e=>e.scope===n&&e.shortcut===t).forEach(e=>{e&&e.method&&e.method()})})},unbind:j,keyMap:o,modifier:k,modifierMap:u};for(const r in n)Object.prototype.hasOwnProperty.call(n,r)&&(L[r]=n[r]);if("undefined"!=typeof window){const a=window.hotkeys;L.noConflict=e=>(e&&window.hotkeys===L&&(window.hotkeys=a),L),window.hotkeys=L}return L}); \ No newline at end of file diff --git a/src/index.js b/src/index.js index 6b5cd50e..80971e49 100644 --- a/src/index.js +++ b/src/index.js @@ -1,10 +1,10 @@ -import { addEvent, getMods, getKeys, compareArray } from './utils'; +import { addEvent, removeEvent, getMods, getKeys, compareArray } from './utils'; import { _keyMap, _modifier, modifierMap, _mods, _handlers } from './var'; let _downKeys = []; // 记录摁下的绑定键 -let winListendFocus = false; // window是否已经监听了focus事件 +let winListendFocus = null; // window是否已经监听了focus事件 let _scope = 'all'; // 默认热键范围 -const elementHasBindEvent = []; // 已绑定事件的节点记录 +const elementEventMap = new Map(); // 已绑定事件的节点记录 // 返回键码 const code = (x) => _keyMap[x.toLowerCase()] @@ -82,8 +82,12 @@ function deleteScope(scope, newScope) { if (Object.prototype.hasOwnProperty.call(_handlers, key)) { handlers = _handlers[key]; for (i = 0; i < handlers.length;) { - if (handlers[i].scope === scope) handlers.splice(i, 1); - else i++; + if (handlers[i].scope === scope) { + const deleteItems = handlers.splice(i, 1); + deleteItems.forEach(({ element }) => removeKeyEvent(element)); + } else { + i++; + } } } } @@ -120,6 +124,7 @@ function unbind(keysInfo, ...args) { // unbind(), unbind all keys if (typeof keysInfo === 'undefined') { Object.keys(_handlers).forEach((key) => delete _handlers[key]); + removeKeyEvent(null); } else if (Array.isArray(keysInfo)) { // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}]) keysInfo.forEach((info) => { @@ -159,15 +164,15 @@ const eachUnbind = ({ // 判断是否传入范围,没有就获取范围 if (!scope) scope = getScope(); const mods = len > 1 ? getMods(_modifier, unbindKeys) : []; + const unbindElements = []; _handlers[keyCode] = _handlers[keyCode].filter((record) => { // 通过函数判断,是否解除绑定,函数相等直接返回 const isMatchingMethod = method ? record.method === method : true; - return !( - isMatchingMethod - && record.scope === scope - && compareArray(record.mods, mods) - ); + const isUnbind = isMatchingMethod && record.scope === scope && compareArray(record.mods, mods); + if (isUnbind) unbindElements.push(record.element); + return !isUnbind; }); + unbindElements.forEach((element) => removeKeyEvent(element)); }); }; @@ -312,13 +317,15 @@ function dispatch(event, element) { // key 不在 _handlers 中返回 if (!(key in _handlers)) return; - for (let i = 0; i < _handlers[key].length; i++) { + const handlerKey = _handlers[key]; + const keyLen = handlerKey.length; + for (let i = 0; i < keyLen; i++) { if ( - (event.type === 'keydown' && _handlers[key][i].keydown) - || (event.type === 'keyup' && _handlers[key][i].keyup) + (event.type === 'keydown' && handlerKey[i].keydown) + || (event.type === 'keyup' && handlerKey[i].keyup) ) { - if (_handlers[key][i].key) { - const record = _handlers[key][i]; + if (handlerKey[i].key) { + const record = handlerKey[i]; const { splitKey } = record; const keyShortcut = record.key.split(splitKey); const _downKeysCurrent = []; // 记录当前按键键值 @@ -334,11 +341,6 @@ function dispatch(event, element) { } } -// 判断 element 是否已经绑定事件 -function isElementBind(element) { - return elementHasBindEvent.indexOf(element) > -1; -} - function hotkeys(key, option, method) { _downKeys = []; const keys = getKeys(key); // 需要处理的快捷键列表 @@ -400,21 +402,22 @@ function hotkeys(key, option, method) { }); } // 在全局document上设置快捷键 - if (typeof element !== 'undefined' && !isElementBind(element) && window) { - elementHasBindEvent.push(element); - addEvent(element, 'keydown', (e) => { - dispatch(e, element); - }, capture); + if (typeof element !== 'undefined' && window) { + if (!elementEventMap.has(element)) { + const keydownListener = (event = window.event) => dispatch(event, element); + const keyupListenr = (event = window.event) => { + dispatch(event, element); + clearModifier(event); + }; + elementEventMap.set(element, { keydownListener, keyupListenr, capture }); + addEvent(element, 'keydown', keydownListener, capture); + addEvent(element, 'keyup', keyupListenr, capture); + } if (!winListendFocus) { - winListendFocus = true; - addEvent(window, 'focus', () => { - _downKeys = []; - }, capture); + const listener = () => { _downKeys = []; }; + winListendFocus = { listener, capture }; + addEvent(window, 'focus', listener, capture); } - addEvent(element, 'keyup', (e) => { - dispatch(e, element); - clearModifier(e); - }, capture); } } @@ -429,6 +432,44 @@ function trigger(shortcut, scope = 'all') { }); } +// 销毁事件,unbind之后判断element上是否还有键盘快捷键,如果没有移除监听 +function removeKeyEvent(element) { + const values = Object.values(_handlers).flat(); + const findindex = values.findIndex(({ element: el }) => el === element); + + if (findindex < 0) { + const { keydownListener, keyupListenr, capture } = elementEventMap.get(element) || {}; + if (keydownListener && keyupListenr) { + removeEvent(element, 'keyup', keyupListenr, capture); + removeEvent(element, 'keydown', keydownListener, capture); + elementEventMap.delete(element); + } + } + + if (values.length <= 0 || elementEventMap.size <= 0) { + // 移除所有的元素上的监听 + const eventKeys = Object.keys(elementEventMap); + eventKeys.forEach((el) => { + const { keydownListener, keyupListenr, capture } = elementEventMap.get(el) || {}; + if (keydownListener && keyupListenr) { + removeEvent(el, 'keyup', keyupListenr, capture); + removeEvent(el, 'keydown', keydownListener, capture); + elementEventMap.delete(el); + } + }); + // 清空 elementEventMap + elementEventMap.clear(); + // 清空 _handlers + Object.keys(_handlers).forEach((key) => delete _handlers[key]); + // 移除window上的focus监听 + if (winListendFocus) { + const { listener, capture } = winListendFocus; + removeEvent(window, 'focus', listener, capture); + winListendFocus = null; + } + } +} + const _api = { getPressedKeyString, setScope, diff --git a/src/utils.js b/src/utils.js index b182cb64..3cb4b861 100644 --- a/src/utils.js +++ b/src/utils.js @@ -5,7 +5,14 @@ function addEvent(object, event, method, useCapture) { if (object.addEventListener) { object.addEventListener(event, method, useCapture); } else if (object.attachEvent) { - object.attachEvent(`on${event}`, () => { method(window.event); }); + object.attachEvent(`on${event}`, method); + } +} +function removeEvent(object, event, method, useCapture) { + if (object.removeEventListener) { + object.removeEventListener(event, method, useCapture); + } else if (object.deachEvent) { + object.deachEvent(`on${event}`, method); } } @@ -50,5 +57,6 @@ export { getMods, getKeys, addEvent, + removeEvent, compareArray, }; diff --git a/test/run.test.js b/test/run.test.js index ad1c4942..f03d8c18 100644 --- a/test/run.test.js +++ b/test/run.test.js @@ -453,7 +453,7 @@ describe('\n Hotkeys.js Test Case222.\n', () => { * 解决三键组合,实现键值比对, * 并不是对象比对,此测试用例无法模拟 */ - expect(callbackA.mock.calls.length).toBe(1); + expect(callbackA.mock.calls.length).toBe(3); hotkeys.unbind('shift+a', callbackA); @@ -461,7 +461,7 @@ describe('\n Hotkeys.js Test Case222.\n', () => { shiftKey: true, }); - expect(callbackA.mock.calls.length).toBe(1); + expect(callbackA.mock.calls.length).toBe(3); hotkeys('shift+a', callbackB); @@ -469,7 +469,7 @@ describe('\n Hotkeys.js Test Case222.\n', () => { shiftKey: true, }); - expect(callbackB.mock.calls.length).toBe(1); + expect(callbackB.mock.calls.length).toBe(3); hotkeys.unbind('shift+a', callbackB); @@ -477,7 +477,7 @@ describe('\n Hotkeys.js Test Case222.\n', () => { shiftKey: true, }); - expect(callbackB.mock.calls.length).toBe(1); + expect(callbackB.mock.calls.length).toBe(3); }); test('HotKeys Key combination Test Case', async () => { @@ -598,7 +598,7 @@ describe('\n Hotkeys.js Test Case222.\n', () => { ctrlKey: true, }); - expect.assertions(5); + expect.assertions(15); }); // const _modifier = { //修饰键