(翻译)draft.js Entities 实体

entities 是draft.js 抽象出来的基本粒子,我们常用到的@某人、链接及嵌入的其它元素都可以抽象为实体
一个entities 包含
1. type 自己定义的字符串 唯一标识这个实体
2. mutability 标识实体在用户编辑的时候展现出来的特性,分为
Immutable 不可变:有原子性,增、删、改一个地方则全部删除
Mutable 可变:例如链接,链接的文字是可以随意改变的
Segmented 部分可变:(或者翻译为分段不可变),片段数量可以增删改,但是单个片段内部不可变
3. data 实体包含的数据

常用的方法:
Entity.get(key) 静态方法,通过实体的Key获取实体
Entity.create 创建实体 如:Entity.create(‘LINK’, ‘MUTABLE’, {url: urlValue});

demo 演示了富文本编辑器中给部分文字添加链接 和 删除链接的功能

import React from 'react';
import ReactDOM from 'react-dom';
import{
    convertToRaw,
    CompositeDecorator,
    ContentState,
    Editor,
    EditorState,
    Entity,
    RichUtils
    }
from 'draft-js';
class LinkEditorExample extends React.Component {
    constructor(props) {
        super(props);

        // 创建新的decorator
        const decorator = new CompositeDecorator([
            {
                strategy: findLinkEntities,
                component: Link,
            },
        ]);

        this.state = {
            editorState: EditorState.createEmpty(decorator),
            showURLInput: false,
            urlValue: '',
        };

        this.focus = () => this.refs.editor.focus();
        this.onChange = (editorState) => this.setState({editorState});
        // 输出日志
        this.logState = () => {
            const content = this.state.editorState.getCurrentContent();
            console.log(convertToRaw(content));
        };

        this.promptForLink = this._promptForLink.bind(this);
        //  输入url改变
        this.onURLChange = (e) => this.setState({urlValue: e.target.value});
        // 确认URL的输入完成
        this.confirmLink = this._confirmLink.bind(this);
        this.onLinkInputKeyDown = this._onLinkInputKeyDown.bind(this);
        this.removeLink = this._removeLink.bind(this);
    }
    // 添加链接

    _promptForLink(e) {
        e.preventDefault();
        const {editorState} = this.state;
        const selection = editorState.getSelection();
        // 如果开始和结尾不是相同的(意味着选中的东西)
        debugger;
        if (!selection.isCollapsed()) {
            this.setState({
                showURLInput: true,
                urlValue: '',
            }, () => {
                // 设置焦点
                setTimeout(() => this.refs.url.focus(), 0);
            });
        }
    }
    // 确认输入
    _confirmLink(e) {
        // 取消默认事件
        e.preventDefault();

        const {editorState, urlValue} = this.state;
        // 创建一个LINK 实体,可变,值是url 地址
        const entityKey = Entity.create('LINK', 'MUTABLE', {url: urlValue});
        // setState 是异步的,第二个参数是回调函数
        this.setState({
            // 借助 RichUtils 添加链接
            editorState: RichUtils.toggleLink(
                editorState,
                editorState.getSelection(),
                entityKey
            ),
            showURLInput: false,
            urlValue: '',
        }, () => {
            setTimeout(() => this.refs.editor.focus(), 0);
        });
    }
    // 监听回车
    _onLinkInputKeyDown(e) {
        if (e.which === 13) {
            this._confirmLink(e);
        }
    }
    // 删除链接 仅仅会删除选中部分的链接
    _removeLink(e) {
        e.preventDefault();
        const {editorState} = this.state;
        const selection = editorState.getSelection();
        // 疑问:如果选中的是部分链接内容会怎样?
        if (!selection.isCollapsed()) {
            this.setState({
                // 借助 RichUtils 删除链接
                editorState: RichUtils.toggleLink(editorState, selection, null),
            });
        }
    }

    render() {
        let urlInput;
        // 如果需要选择url 输入框
        if (this.state.showURLInput) {
            urlInput =
                <div style={styles.urlInputContainer}>
                    <input
                        onChange={this.onURLChange}
                        ref="url"
                        style={styles.urlInput}
                        type="text"
                        value={this.state.urlValue}
                        onKeyDown={this.onLinkInputKeyDown}
                        />
                    <button onMouseDown={this.confirmLink}>
                        Confirm
                    </button>
                </div>;
        }

        return (
            <div style={styles.root}>
                <div style={{marginBottom: 10}}>
                    Select some text, then use the buttons to add or remove links
                    on the selected text.
                </div>
                <div style={styles.buttons}>
                    <button
                        onMouseDown={this.promptForLink}
                        style={{marginRight: 10}}>
                        Add Link
                    </button>
                    <button onMouseDown={this.removeLink}>
                        Remove Link
                    </button>
                </div>
                {urlInput}
                <div style={styles.editor} onClick={this.focus}>
                    <Editor
                        editorState={this.state.editorState}
                        onChange={this.onChange}
                        placeholder="Enter some text..."
                        ref="editor"
                        />
                </div>
                <input
                    onClick={this.logState}
                    style={styles.button}
                    type="button"
                    value="Log State"
                    />
            </div>
        );
    }
}

// 修饰器的查找方法 通过实体类型的名称进行查找
function findLinkEntities(contentBlock, callback) {
    contentBlock.findEntityRanges(
        (character) => {
            const entityKey = character.getEntity();
            return (
                entityKey !== null &&
                Entity.get(entityKey).getType() === 'LINK'
            );
        },
        callback
    );
}


// 链接的component
const Link = (props) => {
    // 取得Link 实体的数据(url) 进行绘制
    const {url} = Entity.get(props.entityKey).getData();
    return (
        <a href={url} style={styles.link}>
            {props.children}
        </a>
    );
};

// 样式
const styles = {
    root: {
        fontFamily: '\'Georgia\', serif',
        padding: 20,
        width: 600,
    },
    buttons: {
        marginBottom: 10,
    },
    // 输入框样式
    urlInputContainer: {
        marginBottom: 10,
    },
    urlInput: {
        fontFamily: '\'Georgia\', serif',
        marginRight: 10,
        padding: 3,
    },
    editor: {
        border: '1px solid #ccc',
        cursor: 'text',
        minHeight: 80,
        padding: 10,
    },
    button: {
        marginTop: 10,
        textAlign: 'center',
    },
    link: {
        color: '#3b5998',
        textDecoration: 'underline',
    },
};

ReactDOM.render(
    <LinkEditorExample />,
    document.getElementById('container')
);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值