react-富文本 react-editor react-contenteditable

本身寫的一個簡單的編輯器  尚在簡潔 具體功能 加粗 斜體 下劃線 連接地址 顏色字體大小 粘貼圖片 excel  截屏 拖拽 上傳 功能都有 默認值 是否顯示工具欄 是否可編輯  測試經過能實現軟件開發大部分需求 可本身繼續添加其餘需求 html

樣子:react

部分代碼:antd

/** * Created by zhanglei on 2017/5/23. */import React, { Component } from 'react';import { Modal,message } from 'antd';import PropTypes from 'prop-types';import './edit.less'import ToolBar from './toolBar'export default class Editor extends Component {    static propTypes = {        className: PropTypes.string,        value:PropTypes.string,        editColor:PropTypes.string,    };    constructor(props){        super(props);        this.state={            value:null,            tableData:[],            linkModel:false,            visible:false,            isColor:false,            editValue:'',            myDisabled:false,            isEdit:true,            isFace:false,            isBackground:false,            linkValue:null,            isSent:true,        }    };    componentDidMount(){        document.addEventListener('click',this.documentClick);    };    moveToEnd = () =>{        const range = window.getSelection();        range.selectAllChildren(this.refs['inputText']);        range.collapseToEnd();    };    documentClick=(e)=>{        const { isColor, isBackground } = this.state;        if(isColor||isBackground){            let en = e.srcElement||e.target;            const name = '.color-content';            while(en){                if(en.className&&en.className === name.replace('.','')){                    return;                }                en = en.parentNode;            }            this.setState({ isColor:false, isBackground:false });        }    };    componentWillUnmount(){        document.removeEventListener('click',this.documentClick)    }    onPaste=(e)=>{        let cbd = e.clipboardData;        if ( !(e.clipboardData && e.clipboardData.items) ) {            return ;        }        this.onParseOrDrop(cbd,e);    };    onDrop=(e)=>{        e.preventDefault();        let cbd = e.dataTransfer;        if ( !(e.dataTransfer && e.dataTransfer.items) ) {            return ;        }        this.onParseOrDrop(cbd,e);    };    onParseOrDrop = (cbd,e) =>{        let ua = window.navigator.userAgent;        if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&            cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&            ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){            return;        }        if(cbd.items&&cbd.items.length === 4){            document.createElement('table');            return false;        }        const myArray = Object.keys(cbd.items).map(item=>{            return cbd.items[item];        });        const arr = myArray.some((u)=>{            if(u.kind === 'file'&&u.type!=='image/jpeg'&&u.type!=='image/png'){                message.error('僅支持PNG或者JPG的圖片格式上傳');                return !1            }            return u.kind === 'file'&&(u.type==='image/jpeg'||u.type==='image/png')        });        if(!arr) return !1;        myArray.forEach(item=>{            if(item.kind === 'string'){                e.preventDefault();                return;            }            if(item.kind === "file"){                e.preventDefault();                const blob = item.getAsFile();                if (blob.size === 0) return;                this.bind_parse(blob);            }        })    };    bind_parse = (file) =>{        const reader = new FileReader();        reader.onload = ((e)=>{            const newImg = `<img class="edit-img" title='點擊放大' src="${ e.target.result}"/>`;            const {onChange} = this.props;            if(onChange){                onChange( this.inputText.innerHTML+newImg );            }        });        reader.readAsDataURL(file);    };    textHtml=(e)=>{        e.preventDefault();        const {isEdit} = this.state;        let html =null;        if(isEdit){            html = this.refs['inputText'].innerHTML;            this.refs['inputText2'].value = html;            this.setState({ isEdit:false, myDisabled:true });        }else{            html = this.refs['inputText2'].value;            this.refs['inputText'].innerHTML = html;            this.setState({ isEdit:true, myDisabled:false });        }    };    emitChange = (e) => {        const { onChange } = this.props;        const html = e.target.innerHTML;        if (onChange && html !== this.lastHtml) {            onChange(html)        }        this.lastHtml = html;    };    shouldComponentUpdate(nextProps,nextState){        return nextProps.value !== this.props.value||            this.state.editValue !== nextState.editValue||            this.state.visible !== nextState.visible||            this.state.myDisabled !== nextState.myDisabled;    }    render() {        const { isEdit, visible, myDisabled } = this.state;        const { disabled, editColor } = this.props;        const isDisabled = !('disabled' in this.props) || !disabled;        return (            <div className="editor-full">                {                    isDisabled &&                    <ToolBar                        id={ this.props.id }                        myDisabled={ myDisabled }                        bind_parse={(this.bind_parse)}                        textHtml={(this.textHtml)}                    />                }                <div className="inputText" style={{ borderColor:editColor }}>                    <div                        className="input-content-edit"                        onPaste={ this.onPaste }                        onDrop={ this.onDrop }                        onInput={this.emitChange}                        contentEditable={ isDisabled }                        onBlur={ this.emitChange }                        dangerouslySetInnerHTML={{ __html:this.props.value }}                        onClick={e =>{                            if(e.target.title === '點擊放大'){                                this.setState({ url:e.target.src, visible:true })                            }                        }}                        ref={ref =>this.inputText = ref}                        style={{                            display:isEdit ? 'block' : 'none',                            height:isDisabled ? '200px' : 'auto'                        }}>                    </div>                    <textarea style={{ display:isEdit ? 'none' : 'block' }} ref="inputText2" id="editor-con"/>                </div>                <Modal                    className="chat-model"                    style={{ width:'70%' }}                    visible={ visible }                    footer={ null }                    onCancel={() =>this.setState({ visible:false })}                >                    <img src={this.state.url} alt="img"/>                </Modal>            </div>        );    }}
相關文章
相關標籤/搜索