frame 监听按键事件

  1. 使用hotkeys-js监听按键事件

当按下相关按键时,控制台会输出对应信息

import { useEffect } from 'react';
import hotkeys from 'hotkeys-js';

const App = () => {
  useEffect(() => {
    // 按下删除键
    hotkeys('backspace', () => {
      console.log('backspace');
    });

    // 同时按下command+z
    hotkeys('command+z', () => {
      console.log('command+z');
    });

    // 同时按下shift+command+z
    hotkeys('shift+command+z', () => {
      console.log('shift+command+z');
    });
  }, []);
  return <></>;
};

export default App;
  1. 当页面中嵌套Frame,且鼠标定位在Frame中时,hotkeys-js无法正常监听到按键事件,这是由于按键事件被Frame内部处理了
import { useEffect } from 'react';
import hotkeys from 'hotkeys-js';
import Frame from 'react-frame-component';

const Image = () => {
  useEffect(() => {
    hotkeys('backspace', () => {
      console.log('backspace');
    });

    hotkeys('command+z', () => {
      console.log('command+z');
    });

    hotkeys('shift+command+z', () => {
      console.log('shift+command+z');
    });
  }, []);
  return (
    <Frame width={375} height={667} style={{ border: '1px solid red' }}>
      <>frame</>
    </Frame>
  );
};

export default Image;
  1. 解决方式,让frame监听按键事件,并把事件抛给外部
import { useEffect, useState } from 'react';
import hotkeys from 'hotkeys-js';
import Frame from 'react-frame-component';

const App = () => {
  const [element, setElement] = useState<HTMLIFrameElement | null>(null);

  useEffect(() => {
    hotkeys('backspace', () => {
      console.log('backspace');
    });

    hotkeys('command+z', () => {
      console.log('command+z');
    });

    hotkeys('shift+command+z', () => {
      console.log('shift+command+z');
    });
  }, []);

  useEffect(() => {
    if (!element) {
      return;
    }

    const handler = (e: KeyboardEvent) => {
      window.document.documentElement.dispatchEvent(e);
    };

    if (element && element.contentDocument) {
      setTimeout(() => {
        element.contentDocument!.addEventListener('keydown', handler);
      }, 200);
    }
  }, [element]);

  return (
    <Frame
      width={375}
      height={667}
      style={{ border: '1px solid red' }}
      ref={el => setElement(el)}>
      <>frame</>
    </Frame>
  );
};

export default App;
  1. 出现报错
    请添加图片描述
    可以通过克隆改事件解决
const eClone = new KeyboardEvent(e.type, e);
window.document.documentElement.dispatchEvent(eClone);
  1. 完整代码
import { useEffect, useState } from 'react';
import hotkeys from 'hotkeys-js';
import Frame from 'react-frame-component';

const App = () => {
  const [element, setElement] = useState<HTMLIFrameElement | null>(null);

  useEffect(() => {
    hotkeys('backspace', () => {
      console.log('backspace');
    });

    hotkeys('command+z', () => {
      console.log('command+z');
    });

    hotkeys('shift+command+z', () => {
      console.log('shift+command+z');
    });
  }, []);

  useEffect(() => {
    if (!element) {
      return;
    }

    const handler = (e: KeyboardEvent) => {
      e.preventDefault(); //阻止本身事件
      const eClone = new KeyboardEvent(e.type, e);
      window.document.documentElement.dispatchEvent(eClone);
    };

    if (element && element.contentDocument) {
      setTimeout(() => {
        element.contentDocument!.addEventListener('keydown', handler);
      }, 200);
    }
  }, [element]);

  return (
    <Frame width={375} height={667} style={{ border: '1px solid red' }} ref={el => setElement(el)}>
      <>frame</>
    </Frame>
  );
};

export default App;

你可能感兴趣的:(前端,javascript,前端,react.js)