You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React Grid Layout场景下,初始化后动态更新TinyMCE编辑器高度

动态调整TinyMCE高度适配React Grid Layout缩放

针对你遇到的两个核心问题,我结合React生命周期特性和TinyMCE的API,给你具体的解决方案:

1. 选择哪个生命周期监听父元素高度变化?

核心原则是在编辑器完全初始化后,精准监听父容器(你的#wrapper元素)的尺寸变化,不同组件类型的选择如下:

  • 类组件:在componentDidMount中初始化监听逻辑,同时在componentDidUpdate中处理React Grid Layout重新排列后的布局变化;最后一定要在componentWillUnmount中清理监听,避免内存泄漏。
  • 函数组件:用useEffect钩子实现,依赖数组可以加入Grid Layout的布局状态(比如layout属性),确保布局变化时重新触发监听,同时返回清理函数完成资源释放。

这里强烈推荐用ResizeObserver API来监听父容器高度,它比全局resize事件更精准,只会在目标元素尺寸变化时触发,不会因为窗口其他区域的变动干扰。

2. 在哪里更新编辑器的高度配置?

不要在init方法里写死高度——init仅负责初始化时的基础配置,动态调整需要在编辑器实例创建完成后,调用TinyMCE的实例方法来更新:

  • 第一步:在TinyMCE的setup回调中,把编辑器实例保存到组件的ref或状态中;
  • 第二步:当父容器高度变化时,调用editor.setSize(null, newHeight)null表示保持宽度自适应,只修改高度),这种方式无需重新初始化编辑器,效率更高。

函数组件代码示例

import { useEffect, useRef } from 'react';
import tinymce from 'tinymce';

const TinyMCEEditor = () => {
  const wrapperRef = useRef(null);
  const editorRef = useRef(null);

  useEffect(() => {
    // 初始化TinyMCE
    tinymce.init({
      selector: '#tinymceSelector',
      setup: (editor) => {
        editorRef.current = editor; // 保存编辑器实例
      },
      // 其他初始化配置(比如工具栏、插件等)
    });

    // 监听父容器高度变化
    const resizeObserver = new ResizeObserver((entries) => {
      const { height } = entries[0].contentRect;
      if (editorRef.current) {
        // 预留20px内边距,避免内容贴边
        const editorHeight = height - 20;
        editorRef.current.setSize(null, editorHeight);
      }
    });

    if (wrapperRef.current) {
      resizeObserver.observe(wrapperRef.current);
    }

    // 组件卸载时清理资源
    return () => {
      tinymce.remove('#tinymceSelector');
      if (wrapperRef.current) {
        resizeObserver.unobserve(wrapperRef.current);
      }
    };
  }, []);

  return (
    <div id="wrapper" ref={wrapperRef}>
      <textarea id="tinymceSelector" />
    </div>
  );
};

export default TinyMCEEditor;

类组件代码参考

import React, { Component } from 'react';
import tinymce from 'tinymce';

class TinyMCEEditor extends Component {
  constructor(props) {
    super(props);
    this.wrapperRef = React.createRef();
    this.editorRef = null;
    this.resizeObserver = null;
  }

  componentDidMount() {
    // 初始化编辑器
    tinymce.init({
      selector: '#tinymceSelector',
      setup: (editor) => {
        this.editorRef = editor;
      },
      // 其他初始化配置
    });

    // 监听父容器尺寸变化
    this.resizeObserver = new ResizeObserver((entries) => {
      const height = entries[0].contentRect.height;
      if (this.editorRef) {
        this.editorRef.setSize(null, height - 20);
      }
    });

    if (this.wrapperRef.current) {
      this.resizeObserver.observe(this.wrapperRef.current);
    }
  }

  componentDidUpdate(prevProps) {
    // 当Grid Layout布局变化时,强制同步编辑器高度
    if (prevProps.layout !== this.props.layout && this.editorRef) {
      const height = this.wrapperRef.current.offsetHeight;
      this.editorRef.setSize(null, height - 20);
    }
  }

  componentWillUnmount() {
    tinymce.remove('#tinymceSelector');
    if (this.wrapperRef.current) {
      this.resizeObserver.unobserve(this.wrapperRef.current);
    }
  }

  render() {
    return (
      <div id="wrapper" ref={this.wrapperRef}>
        <textarea id="tinymceSelector" />
      </div>
    );
  }
}

export default TinyMCEEditor;

额外注意事项

  • 确保父容器#wrapper的高度由React Grid Layout控制(比如设置height: 100%或Grid的h属性),这样ResizeObserver才能正确捕获高度变化;
  • 如果编辑器内容较多有滚动需求,调整高度后可以调用editor.execCommand('mceAutoResize')让编辑器自动适配内容,但强制适配父容器高度时,setSize更可靠;
  • 为避免频繁触发高度更新,可给ResizeObserver的回调加防抖处理(比如用lodash.debounce),防止性能损耗。

内容的提问来源于stack exchange,提问作者Yolixtly ANDERSON

火山引擎 最新活动