You need to enable JavaScript to run this app. 基于现有React组件实现点击锚点弹出TinyMCE富文本编辑器并回传数据
优惠活动
大模型
产品
解决方案
定价
更多

基于现有React组件实现点击锚点弹出TinyMCE富文本编辑器并回传数据

富文本弹窗集成实现方案

前置组件修正:优化TextEditor.js的可复用能力

你当前编写的TextEditor组件存在命名不规范、无外部交互接口的问题,无法和父组件进行数据联动,需要先改造为可接收外部参数、回传编辑数据的通用组件:

  • 移除组件内部硬编码的初始值,改为通过props接收初始编辑内容
  • 内置的内容变更事件不再仅做控制台打印,改为通过props回调将实时编辑内容抛出
  • 预留弹窗关闭的回调入口,适配弹窗交互逻辑

改造后的完整TextEditor.js代码:

import React from 'react';
import { Editor } from '@tinymce/tinymce-react';

// 修正为通用业务组件,不再使用不符合规范的App命名
const TinyMceEditor = (props) => {
  // 从props解构接收外部传入的参数
  const { initialContent = '', onContentChange, onClose } = props;

  // 编辑器内容变更回调,直接通过props抛给父组件
  const handleEditorChange = (content) => {
    onContentChange?.(content);
  }

  return (
    <div className="editor-wrapper">
      {/* 弹窗头部:嵌入关闭按钮 */}
      <div className="modal-header" style={{display: 'flex', justifyContent: 'flex-end', paddingBottom: '12px'}}>
        <button onClick={onClose} style={{padding: '4px 12px', cursor: 'pointer'}}>关闭</button>
      </div>
      <Editor
        // 用外部传入的初始值替换硬编码内容
        initialValue={initialContent}
        init={{
          height: 500,
          menubar: false,
          // 本地资源路径配置,避免依赖外链CDN
          // skin_url: '/tinymce/skins/ui/oxide',
          // content_css: '/tinymce/skins/content/default/content.css',
          plugins: [
            'advlist autolink lists link image charmap print preview anchor',
            'searchreplace visualblocks code fullscreen',
            'insertdatetime media table paste code help wordcount'
          ],
          toolbar:
            'undo redo | formatselect | bold italic backcolor | \
            alignleft aligncenter alignright alignjustify | \
            bullist numlist outdent indent | removeformat | help'
        }}
        onEditorChange={handleEditorChange}
      />
    </div>
  );
}

export default TinyMceEditor;

DogPaddle组件改造:实现点击唤起弹窗、接收编辑器回传内容

原DogPaddle组件缺少状态管理逻辑,需要补充两个核心状态:

  • isModalVisible:控制弹窗的展示/隐藏
  • editorContent:存储从编辑器回传的实时编辑内容

弹窗使用原生DOM结构实现,不依赖第三方UI库,避免额外依赖,改造后的完整DogPaddle.js代码:

import React, { useState } from 'react'
// 引入改造后的通用编辑器组件
import TinyMceEditor from './TextEditor'

const DogPaddle = (props) => {
  // 新增状态管理
  const [isModalVisible, setIsModalVisible] = useState(false);
  // 存储编辑器回传的内容,满足数据回传至DogPaddle的要求
  const [editorContent, setEditorContent] = useState('');

  // 点击锚点唤起弹窗
  const handleLinkClick = () => {
    setIsModalVisible(true);
  }

  // 关闭弹窗逻辑
  const handleModalClose = () => {
    setIsModalVisible(false);
    // 可根据业务需要,关闭时把最终的editorContent抛给上层组件
    props.onContentSaved?.(editorContent);
  }

  // 接收编辑器回传的实时内容
  const handleEditorContentChange = (content) => {
    setEditorContent(content);
  }

  return(
    <>
      {/* 原有结构的锚点标签,绑定点击事件 */}
      <a onClick={handleLinkClick} href="javascript:void(0)">
        点击打开富文本编辑器
      </a>

      {/* 弹窗结构,根据状态控制是否渲染 */}
      {isModalVisible && (
        <div 
          className="modal-mask" 
          style={{
            position: 'fixed',
            top: 0,
            left: 0,
            width: '100vw',
            height: '100vh',
            background: 'rgba(0,0,0,0.5)',
            zIndex: 999,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center'
          }}
        >
          <div 
            className="modal-content"
            style={{
              background: '#fff',
              padding: '20px',
              borderRadius: '4px',
              width: '80%',
              maxWidth: '800px'
            }}
          >
            {/* 嵌入改造后的编辑器,绑定回传事件 */}
            <TinyMceEditor
              initialContent="<p>初始编辑内容</p>"
              onContentChange={handleEditorContentChange}
              onClose={handleModalClose}
            />
          </div>
        </div>
      )}
    </>
  )
}

export default DogPaddle

上层Home组件(Dog.js)适配逻辑

如果需要把编辑器的最终内容回传到Home组件,只需要在调用DogPaddle时绑定内容保存的回调即可,调整后的Dog.js(Home组件)代码:

import React, { Component } from 'react'
import DogPaddle from './DogPaddle'

class Home extends Component {
  state = {
     user: {},
     user_data: [],
     // 存储从DogPaddle回传的富文本内容
     richTextContent: ''
   }

  // 接收DogPaddle回传的保存内容
  handleContentSaved = (content) => {
    this.setState({
      richTextContent: content
    })
    // 可在此处接入后续业务逻辑,比如提交接口、渲染内容等
    console.log('回传到Home组件的富文本内容:', content)
  }

  render() {
    return (
      <div>
        <div>
          {/* 给DogPaddle绑定内容保存的回调 */}
          <DogPaddle
            onContentSaved={this.handleContentSaved}
          >
          </DogPaddle>
        </div>
      </div>
    );
  }
}

export default Home

关键实现说明

  • 编辑器的内容回传是实时触发的,每次编辑框输入内容都会同步更新DogPaddle组件内的editorContent状态,满足数据不脱离DogPaddle的要求
  • 弹窗采用条件渲染的方式,关闭弹窗时会直接销毁编辑器DOM实例,避免内存泄漏
  • 所有交互逻辑均通过props进行组件间通信,符合React单向数据流的规范
  • 不需要引入额外的弹窗UI库,原生实现的弹窗可以适配绝大多数业务场景

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.25 07:15:03