js快捷鍵設置


/* eslint-disable no-underscore-dangle */
import { each } from 'lodash';
/* 快捷鍵說明:
 * 快捷生效模塊命名規范:
 *  1.路由模塊-執行this.$hotKey.set('ModuleName', {'F9': ()=>{...callback() }}). ModuleName:'Pos.order'
 *  2.彈窗模塊-執行Dialog name=ModuleName,並傳入:hotkeys='callbackObj'. ModuleName:'PosDialog.settlement'
 *  3.說明-初始設計為鍵盤的'down'事件,后增加了'up'事件(本不應該使用),所有快捷鍵均變成了兩次觸發(down和up)方法會被調用兩次, 目前暫不做處理.
 */

/* 按鍵字典
 * 主鍵盤: 大寫和小寫字母, 數字鍵, 功能鍵
 * 小鍵盤: 數字鍵,功能鍵
 * F功能鍵
 * Ctrl-添加'.ctrl', Shift-添加'.alt'
 */
const KEYCODE = {
  // 65: "a", 66: "b", 67: "c", 68: "d", 69: "e", 70: "f", 71: "g",
  // 72: "h", 73: "i", 74: "j", 75: "k", 76: "l", 77: "m", 78: "n",
  // 79: "o", 80: "p", 81: "q", 82: "r", 83: "s", 84: "t", 85: "u",
  // 86: "v", 87: "w", 88: "x", 89: "y", 90: "z",
  65: 'A',
  66: 'B',
  67: 'C',
  68: 'D',
  69: 'E',
  70: 'F',
  71: 'G',
  72: 'H',
  73: 'I',
  74: 'J',
  75: 'K',
  76: 'L',
  77: 'M',
  78: 'N',
  79: 'O',
  80: 'P',
  81: 'Q',
  82: 'R',
  83: 'S',
  84: 'T',
  85: 'U',
  86: 'V',
  87: 'W',
  88: 'X',
  89: 'Y',
  90: 'Z',
  // 主鍵盤數字鍵
  48: '0',
  49: '1',
  50: '2',
  51: '3',
  52: '4',
  53: '5',
  54: '6',
  55: '7',
  56: '8',
  57: '9',
  // 小鍵盤數字鍵
  96: '0',
  97: '1',
  98: '2',
  99: '3',
  100: '4',
  101: '5',
  102: '6',
  103: '7',
  104: '8',
  105: '9',
  // 功能鍵
  16: 'Shift',
  17: 'Ctrl',
  18: 'Alt',
  // 主鍵盤其他
  8: 'BackSpace',
  9: 'Tab',
  13: 'Enter',
  27: 'Esc',
  32: 'Space',
  33: 'PgUp',
  34: 'PgDn',
  35: 'End',
  36: 'Home',
  45: 'Insert',
  187: '+',
  189: '-',
  188: ',',
  190: '.',
  191: '/',
  219: '{',
  220: '|',
  221: '}',
  // 小鍵盤其他
  108: 'Enter',
  106: '*',
  107: '+',
  109: '-',
  110: '.',
  111: '/',
  // F功能鍵
  112: 'F1',
  113: 'F2',
  114: 'F3',
  115: 'F4',
  116: 'F5',
  117: 'F6',
  118: 'F7',
  119: 'F8',
  120: 'F9',
  121: 'F10',
  122: 'F11',
  123: 'F12',
  38: '↑',
  40: '↓',
  37: '←',
  39: '→',
};

/* 快捷鍵構建類 */
export default class HotKey {
  constructor() {
    // 快捷鍵 存儲'執行回調'的對象
    this.hotkeys = {};
    // 快捷鍵 模塊名稱合集
    this.modules = [];
    // this.currentModule = null
    this.uphotkeys = {};
  }

  static isStop = false

  stop() {
    this.constructor.isStop = true;
  }

  start() {
    this.constructor.isStop = false;
  }

  // 初始化
  init() {
    document.onkeydown = (event) => {
      // 獲取事件相關屬性, 阻止瀏覽器 BackSpace鍵,返回url
      let _vReadOnly;
      let _vDisabled;
      const _obj = event.target || event.srcElement;
      const _t = _obj.type || _obj.getAttribute('type');
      _vReadOnly = _obj.readOnly;
      _vDisabled = _obj.disabled;
      // 處理undefined值情況
      _vReadOnly = (_vReadOnly == undefined) ? false : _vReadOnly;
      _vDisabled = (_vDisabled == undefined) ? true : _vDisabled;
      // 事件源類型為密碼或單行、多行文本的,並且readOnly屬性為true或disabled屬性為true的,則退格鍵失效
      const _flag1 = (_t === 'password' || _t === 'text' || _t === 'textarea' || _t === 'number')
        && (_vReadOnly === true || _vDisabled === true);
      // 當敲Backspace鍵時,事件源類型非密碼或單行、多行文本的,則退格鍵失效
      const _flag2 = _t !== 'password' && _t !== 'text' && _t !== 'textarea' && _t !== 'number';

      // 屏蔽input和textarea的Enter鍵默認事件, 同時屏蔽button按鈕的Enter
      if (event.keyCode === 13 || (event.keyCode === 13 && $(event.target).is('button'))) {
        // 但是 恢復 餓了么的彈框組件的確認按鈕,所需要的回車鍵功能恢復,從這加一個判斷條件如果是餓么的組件就不屏蔽
        if (!$(event.target).hasClass('el-button')) {
          event.preventDefault();
        }
      }
      // 屏蔽 F1~F11案件的瀏覽器默認事件
      // 鍵盤按下 Ctrl + F1~F6 時觸發
      // BackSpace鍵入非input或textarea(或狀態為readOnly,disabled), 阻止url返回
      if (
        event.keyCode >= 112 && event.keyCode <= 122
        || (event.keyCode >= 112 && event.keyCode <= 117 && event.ctrlKey)
        || (event.keyCode == 8 && (_flag1 || _flag2))
      ) {
        event.preventDefault();
      }
      // 執行事件觸發
      this.trigger(event);
    };
    document.onkeyup = (event) => {
      this.trigger(event, 'up');
    };
  }

  // 設置模塊名及回調(執行方法)
  set(moduleName, options, type = 'down') {
    const index = this.modules.indexOf(moduleName);
    if (index != -1) {
      this.modules.splice(index, 1);
    }
    this.modules.push(moduleName);
    if (type === 'down') {
      if (options) {
        each(options, (handler, name) => {
          this.hotkeys[`${moduleName}.${name}`] = handler;
        });
      }
    } else if (type === 'up') {
      if (options) {
        each(options, (handler, name) => {
          this.uphotkeys[`${moduleName}.${name}`] = handler;
        });
      }
    }
  }

  findMethod(name, callback, moduleName, type = 'down') {
    if (this.modules.length) {
      const curModule = this.modules[this.modules.length - 1]; // 最后一個設置熱鍵的界面模塊名
      const method = `${curModule}.${name}`;
      let hotkeys = {};
      if (type === 'down') {
        hotkeys = this.hotkeys;
      } else if (type === 'up') {
        hotkeys = this.uphotkeys;
      }
      if (hotkeys[method]) {
        callback(hotkeys[method]);
      } else if (curModule.length) {
        const modules = curModule.split('.');
        modules.pop();
        const prevMethod = `${modules.join('.')}.${name}`;
        if (hotkeys[prevMethod]) {
          callback(hotkeys[prevMethod]);
        }
      }
    }
  }

  // 事件觸發方法
  trigger(event, type = 'down') {
    if (this.constructor.isStop || $('.el-message-box__wrapper:visible').length) {
      return;
    }
    this.findMethod(
      KEYCODE[event.keyCode] + (event.ctrlKey ? '.ctrl' : '') + (event.altKey ? '.alt' : ''),
      (handler) => {
        handler(event);
      },
      null,
      type,
    );
  }

  // 移除關閉模塊(基於模塊名)
  removeCurrentModule(name) {
    if (this.modules[this.modules.length - 1] == name) {
      this.modules.pop();
    }
    if (name.indexOf('AddPayHotkey') != -1) {
      this.modules.forEach((item, index, arr) => {
        item == name && arr.splice(index, arr.length - 1);
      });
    }
  }
}

  

import HotKey from '@/common/js/HotKey';

const VueHotKey = {};
VueHotKey.install = (Vue) => {
  const VueSelf = Vue;
  VueSelf.prototype.$hotKey = new HotKey();
};
export default VueHotKey;

  

import VueHotkey from './vue-hotkey';
Vue.use(VueHotkey);

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM