我有一个在 react 上写的聊天应用程序。
我需要以下内容:
- 当用户写下微笑名称时,例如
:smile:
应该转换为表情符号,而不是Unicode。 - 输入必须为下面的代码。
- 输入中的表情符号应与对话中的表情符号相同。
<div contentEditable
styles={this.state.messageInputStyle}
className="message-input">
</div>
这里有一个用html
和onChange
道具制作contentEditable
div的好方法。 我将其与emojione
的shortnameToImage
函数一起使用。
这是一个有效的代码笔
如果您希望样式来自状态,可以将样式添加到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>
我使用了表情符号和这个代码片段,基本上提出了一个非常无反应的解决方案,如下所示。希望对您有所帮助。
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