useImperativeHandle暴露ref方法使用 - davy-gan/web GitHub Wiki

import React, { useRef, useEffect, useImperativeHandle } from 'react';
import { Icon } from 'antd';
import * as monaco from 'monaco-editor';
import { useFullscreen } from '@/util/hooks';
import styles from './Sql.less';

export default React.forwardRef(({ value = '', onChange, theme }, ref) => {
  const myRef = useRef({});
  useEffect(() => {
    const editor = monaco.editor.create(myRef.current, {
      value,
      language: 'sql',
      minimap: {
        enabled: false,
      },
      automaticLayout: true,
      theme,
      wordWrap: 'on',
    });
    const onDidChangeModelContent = editor.onDidChangeModelContent(e => {
      if (onChange && typeof onChange === 'function') {
        const val = editor.getModel().getValue();
        onChange(val);
      }
    });
    myRef.current.editor = editor;
    return () => {
      onDidChangeModelContent.dispose();
    };
  }, []);

  useEffect(() => {
    const model = myRef.current.editor.getModel();
    const newValue = model.getValue();
    if (newValue !== value) {
      model.setValue(value);
    }
  }, [value]);

  useImperativeHandle(ref, () => ({
    getData: () => {
      const model = myRef.current.editor.getModel();
      return model.getValue();
    },
  }));

  const { fullscreen, toggleFullscreen } = useFullscreen(myRef);

  return (
    <div className={styles.container} ref={myRef}>
      <Icon
        type={fullscreen ? 'fullscreen-exit' : 'fullscreen'}
        className={theme === 'vs-dark' ? styles.fullscreen : styles.fullscreenLight}
        onClick={toggleFullscreen}
      />
    </div>
  );
});

// 全屏
export function toggleFullscreen(elem, fullscreen) {
  if (!elem) return;
  if (fullscreen) {
    if (elem.requestFullscreen) {
      elem.requestFullscreen();
    } else if (elem.msRequestFullscreen) {
      elem.msRequestFullscreen();
    } else if (elem.mozRequestFullScreen) {
      elem.mozRequestFullScreen();
    } else if (elem.webkitRequestFullscreen) {
      elem.webkitRequestFullscreen();
    }
  } else if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
}
export function useFullscreen(ref) {
  const [fullscreen, setFullscreen] = useState(false);
  useEffect(() => {
    const callback = () => {
      let newFullscreen = false;
      if (document.fullscreenElement) {
        newFullscreen = true;
      }
      setFullscreen(newFullscreen);
    };
    ref.current.addEventListener('fullscreenchange', callback);
    return () => {
      ref.current.removeEventListener('fullscreenchange', callback);
    };
  }, []);
  return {
    fullscreen,
    toggleFullscreen: () => {
      const newFullscreen = !fullscreen;
      toggleFullscreen(ref.current, newFullscreen);
    },
  };
}

.container {
  width: 100%;
  height: 100%;
  position: relative;
}

.fullscreen {
  position: absolute;
  right: 18px;
  bottom: 6px;
  color: #fff;
  z-index: 10;
  cursor: pointer;
  font-size: 14px;
}

.fullscreenLight {
  position: absolute;
  right: 18px;
  bottom: 6px;
  color: #000;
  z-index: 10;
  cursor: pointer;
  font-size: 14px;
}
⚠️ **GitHub.com Fallback** ⚠️