react引入富文本編輯器TinyMCE

 

這周作了一個PC端的service後臺需求,要求有富文本編輯器,插入圖片、表格,字體字號背景色等等,css

最後引入了富文本編輯器TinyMCEvue

 

對於TinyMCE的簡介:react

TinyMCE是一款易用、且功能強大的所見即所得的富文本編輯器。同類程序有:UEditor、Kindeditor、Simditor、CKEditor、wangEditor、Suneditor、froala等等。nginx

TinyMCE的優點:antd

  • 開源可商用,基於LGPL2.1
  • 插件豐富,自帶插件基本涵蓋平常所需功能
  • 接口豐富,可擴展性強,有能力能夠無限拓展功能
  • 界面好看,符合現代審美
  • 提供經典、內聯、沉浸無干擾三種模式
  • 對標準支持優秀(自v5開始)
  • 多語言支持,官網可下載幾十種語言。

 

 

 

 上圖爲需求中配置的富文本編輯器的內容,個人需求TinyMCE徹底能夠知足,編輯器

  TinyMCE 官網:www.tiny.cloud工具

 

   TinyMCE支持vue、react、angular 字體

 

 此次改動的工程使用的是react,this

在需求中封裝了一個適合咱們的富文本編輯組件:spa

 

 

editor組件中的內容:

import React from 'react';
import './Editor.scss';

import {isDev, nginxPrefix} from '@/config';

import {Upload, Button, Icon, Popconfirm, Spin, message} from 'antd';

import _get from 'lodash/get';
import _uniqueId from 'lodash/uniqueId';

import PropTypes from 'prop-types';

/*
* @props string id? 標識符
* @props number height? 高度
* @props string defaultContent? 初始內容
* @props boolen disabled? 禁用
* @props function onDelete? 刪除事件
* @props function onAdd? 添加事件
* @props object uploadConfig? 自定義上傳配置
* @event function getEditorContent 獲取編輯內容
* @event function setEditorContent 設置編輯內容
* @event function insertContent 插入編輯內容
*/
class Editor extends React.Component {
    constructor(props) {
        super(props);

        const tinymceId = `editor-tinymce-${this.props.id}-${_uniqueId()}-${new Date().getTime()}`;

        this.state = {
            // 編輯器ID
            tinymceId,
            // 編輯器實例
            editor: null
        };
    }

    componentDidMount() {
        const {height = 300, defaultContent = ''} = this.props;
        window.tinymce.init({
            selector: `#${this.state.tinymceId}`,
            language: 'zh_CN',
            height: height,
            min_height: 200,
            width: '100%',
            resize: true,
            default_link_target: '_blank',
            init_instance_callback: editor => {
                if (defaultContent) {
                    editor.setContent(defaultContent);
                }
            },
            paste_enable_default_filters: true,
            // paste_word_valid_elements: () => {
            //
            // },
            // 插件配置
            plugins: 'table image lists link paste',
            // 菜單配置
            menubar: 'file edit view insert format',
            // 工具欄配置
            /* eslint-disable */
            toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | outdent indent | blockquote | table | image link | forecolor backcolor | bullist numlist | removeformat'
            /* eslint-enable */
        }).then(([editor]) => this.setState({editor}));
    }

    componentWillUnmount() {
        // 在某些生命週期中,實例並未生成,沒有卸載方法。(組件掛載階段)
        // if (this.state.editor !== null) {
        //     this.state.editor.destroy();
        // }
        window.tinymce.get(this.state.tinymceId).destroy();
    }

    getEditorContent = () => {
        return this.state.editor.getContent();
    }

    setEditorContent = (content) => {
        window.tinymce.get(this.state.tinymceId).setContent(content);
    }

    insertContent = (content) => {
        try {
            this.state.editor.insertContent(content);
        } catch(e) {
            window.tinymce.get(this.state.tinymceId).insertContent(content);
        }
    }

    // 默認上傳配置
    uploadConfig = {
        name: 'file',
        action: (isDev ? '' : nginxPrefix) + '/admin/common/uploadFile',
        headers: {
            authorization: 'authorization-text',
        },
        onChange: (info) => {
            if (info.file.status === 'done') {
                message.success('圖片上傳成功');
                this.state.editor.insertContent(
                    `<img src="${_get(info, 'file.response.data.result')}" >`
                );
            } else if (info.file.status === 'error') {
                message.error('圖片上傳失敗');
            }
        },
        accept: '.jpg,.jpeg,.jpe,.png,.bmp'
    }

    render() {
        const {uploadConfig} = this.props;
        return (
            <Spin spinning={this.props.disabled} indicator={<Icon type="stop" style={{color: '#555'}} />}>
                <div className="editor-container">
                    <textarea id={this.state.tinymceId} />
                    <div className="btn-bar">
                        <Upload {...(uploadConfig ? uploadConfig : this.uploadConfig)}>
                            <Button><Icon type="upload" />添加本地圖片</Button>
                        </Upload>
                        <span>
                            {
                                this.props.onAdd
                                &&
                                <Button icon="plus" shape="circle" onClick={this.props.onAdd} />
                            }
                            {
                                this.props.onDelete
                                &&
                                <Popconfirm
                                    title="沒法撤回,確認刪除?"
                                    onConfirm={this.props.onDelete}
                                    okText="確認"
                                    cancelText="取消"
                                    placement="leftBottom"
                                >
                                    <Button
                                        type="danger"
                                        icon="delete"
                                        shape="circle"
                                        style={{marginLeft: '4px'}}
                                        onClick={() => {
                                            // 當富文本編輯器中沒有內容時,刪除按鈕不彈窗,直接調用刪除方法
                                            const content = this.getEditorContent();

                                            if (!content) {
                                                this.props.onDelete();
                                            }
                                        }}
                                    />
                                </Popconfirm>
                            }
                        </span>
                    </div>
                </div>
            </Spin>
        );
    }
}

Editor.defaultProps = {
    id: 'no-props-id',
    height: 300,
    defaultContent: '',
    onDelete: null,
    onAdd: null,
    disabled: false,
    uploadConfig: null
};

Editor.propTypes = {
    id: PropTypes.string,
    height: PropTypes.number,
    defaultContent: PropTypes.string,
    onDelete: PropTypes.func,
    onAdd: PropTypes.func,
    disabled: PropTypes.bool
};

export default Editor;

 

 

組件最終提交的是一段HTML,圖片只是一個URL,大小很是小,很是實用

此次的需求中富文本編輯框是錄入案例,

固然有錄入就有展現,對於展現也很簡單,在展現的地方加了個圖片放大的功能

展現的時候有個問題,就是圖片的大小咱們想控制的很小,這樣總體的內容均可以看到,圖片具體內容能夠點擊圖片放大,

 

 

 

 

 

 

 

 

來來來,展現一下我男神圖片點擊放大以後的帥圖:

 

 

相關文章
相關標籤/搜索