【问题标题】:How to implement react with on type (realtime) emojis?如何实现对类型(实时)表情符号的反应?
【发布时间】:2018-07-11 02:51:26
【问题描述】:

我有一个用 react 编写的聊天应用。

我需要以下物品:

  • 当用户写一个微笑的名字时,例如。 :smile: 应该转换成 emojione不是 unicode
  • 输入必须是下面的代码。
  • 输入中的表情符号应该与对话中的表情相同。
<div contentEditable
     styles={this.state.messageInputStyle}
     className="message-input">
</div>

【问题讨论】:

  • 你研究和尝试了什么?
  • @SterlingArcher 我试过 react-emojione, onKeyUp 我检查输入的 innerHTML 是否有 Text 节点并包含例如:smile:,然后我申请emojify 然后插入它。真的很丑,我相信有更好的解决方案。

标签: javascript reactjs emoji emojione


【解决方案1】:

here 是使用htmlonChange 道具制作contentEditable div 的好方法。我将它与emojioneshortnameToImage 函数一起使用。

here is a working codepen

如果您希望样式来自该州,可以将样式添加到 ContentEditable 道具

唯一需要修复的是添加表情符号后的插入符号位置。

class Application extends React.Component {
  state = {
    value: "Start Writing Here"
  };

  render() {
    return (
      <ContentEditable
        html={emojione.shortnameToImage(this.state.value)}
        onChange={this._onChange}
      />
    );
  }

  _onChange = e => {
    this.setState({ value: e.target.value });
  };
}

var ContentEditable = React.createClass({
  render: function() {
    return (
      <div
        contentEditable
        className="message-input"
        onInput={this.emitChange}
        onBlur={this.emitChange}
        dangerouslySetInnerHTML={{ __html: this.props.html }}
      />
    );
  },

  shouldComponentUpdate: function(nextProps) {
    return nextProps.html !== this.getDOMNode().innerHTML;
  },

  componentDidUpdate: function() {
    if (this.props.html !== this.getDOMNode().innerHTML) {
      this.getDOMNode().innerHTML = this.props.html;
    }
  },

  emitChange: function() {
    var html = this.getDOMNode().innerHTML;

    if (this.props.onChange && html !== this.lastHtml) {
      this.props.onChange({ target: { value: html } });
    }

    this.lastHtml = html;
  }
});

React.render(<Application />, document.getElementById("app"));
html, body {
  height: 100%
}

.message-input {
  width: 100%;
  height: 100%;
  font-size: 30px;
}

.emojione {
  height: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.min.js"></script>
<div id="app"></div>

【讨论】:

    【解决方案2】:

    我使用emojionethis code snippet 基本上想出了一个非常无反应的解决方案,如下所示。希望对您有所帮助。

    import React from 'react';
    import {render} from 'react-dom';
    import emojione from 'emojione';
    
    class App extends React.Component {
    
        constructor(props) {
            super(props);
        }
    
        updateText = () => {
            const html = emojione.shortnameToImage(this.refs.inputDiv.innerHTML);
            let sel, range;
    
            if (window.getSelection) {
                // IE9 and non-IE
                sel = window.getSelection();
    
                if (sel.getRangeAt && sel.rangeCount) {
                    range = sel.getRangeAt(0);
                    range.deleteContents();
    
                    // Range.createContextualFragment() would be useful here but is
                    // non-standard and not supported in all browsers (IE9, for one)
                    let el = this.refs.inputDiv;
                    el.innerHTML = html;
                    let frag = document.createDocumentFragment(), node, lastNode;
    
                    while ((node = el.firstChild)) {
                        lastNode = frag.appendChild(node);
                    }
                    range.insertNode(frag);
    
                    // Preserve the selection
                    if (lastNode) {
                        range = range.cloneRange();
                        range.setStartAfter(lastNode);
                        range.collapse(true);
                        sel.removeAllRanges();
                        sel.addRange(range);
                    }
                }
            } else if (document.selection && document.selection.type !== "Control") {
                // IE < 9
                document.selection.createRange().pasteHTML(html);
            }
        };
    
    
        render() {
            return (
                <div ref="inputDiv" contentEditable onInput={this.updateText}/>
            );
        }
    
    }
    
    render(<App/>, document.getElementById('root'));
    

    这是工作示例 https://codesandbox.io/s/ol2lmkqqlq

    【讨论】:

      猜你喜欢
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 2021-10-25
      • 2022-01-19
      • 2020-07-30
      相关资源
      最近更新 更多