「为什么」不自定义hook实现快捷键功能?

365 阅读1分钟

写在前面

适用快捷键esc/enter正在编辑的代码,这个功能是怎么实现的? 想必大家心里很清楚了:监听键盘输入事件就可以了,确实是这样。

那么我们今天来做点不一样的!我们自定义Hook来实现一下这个快捷键监听功能,适用所有键盘操作。

开始代码

自定义hook实现按键监听

在使用普通代码实现快捷键的时候,往往需要不停地addEventListener,然后不停地removeEventListener,代码看起来臃肿不堪,下面来看看hook这种优雅的实现吧?

import { useState, useEffect } from 'react';

const useKeyPressed = (targetKeyCode) => {
  const [keyPressed, setKeyPressed] = useState(false);
  useEffect(() => {
    // 监听目标键按下
    const keyDownHandler = ({ keyCode }) => {
      if (keyCode === targetKeyCode) {
        setKeyPressed(true);
      }
    };
    // 监听目标键抬起
    const keyUpHandler = ({ keyCode }) => {
      if (keyCode === targetKeyCode) {
        setKeyPressed(false);
      }
    };
    document.addEventListener('keyup', keyUpHandler);
    document.addEventListener('keydown', keyDownHandler);
    return () => {
      // 去掉监听
      document.removeEventListener('keyup', keyUpHandler);
      document.removeEventListener('keydown', keyDownHandler);
    };
  }, []);
  return keyPressed;
};

export default useKeyPressed;

在useEffect中使用hook

上面自定义了一个hook,实现了监听目标键按下和抬起,并返回了true/false。下面我们来看看怎么使用吧!

import React, { useState, useEffect } from 'react';
import useKeyPressed from '../hooks/useKeyPressed';
import styles from './InputSearch.less';

const InputSearch = ({ title, onSearch }) => {
  const [value, setValue] = useState('');
  const enterPressed = useKeyPressed(13);// enter键
  const escPressed = useKeyPressed(27); //esc键
  
  const closeSearch = () => {
    setValue('');
  };
  
  // 监听鼠标按下副作用
  useEffect(() => {
    if (enterPressed) {
      onSearch(value);
    }
    if (escPressed) {
      closeSearch();
    }
  });

  return (
    <div className={styles.InputSearch}>
          <input
            placeholder="搜索"
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
            style={{
              width: 'calc(100% - 30px)',
              height: 24,
              padding: '0 4px',
              background: '#5e5e5e',
              borderColor: '#9e9e9e',
              color: '#fff',
              caretColor: '#fff',
            }}
          />
    </div>
  );
};

export default InputSearch;

尾声

核心逻辑也很简单,就不解释了。

自定义hook是不是很简单,很优雅?一处封装,多次使用。