项目需求实现一个划词功能,由于textarea的局限性,考虑到使用div来实现,通过设置div的contentEditable来模拟文本框。实现代码如下:
class ContentEditable extends Component {
constructor(props) {
super(props)
}
shouldComponentUpdate(nextProps) {
return nextProps.html !== this.elem['innerText']
}
onChange = (e) => {
const value = this.elem['innerText']
this.props.onChange(e, value)
}
render() {
const { html, contentEditable, ...props } = this.props
return (
<div
{...props}
ref={(elem) => { this.elem = elem }}
dangerouslySetInnerHTML={{ __html: html }}
contentEditable={contentEditable}
onInput={ this.onChange }
/>
)
}
}
e.g.
<ContentEditable
html={this.state.value}
className="editable-sample-selection"
contentEditable={isPatternCheckSuccess}
onChange={this.handleEditTextChange}
/>
...
handleEditTextChange = (e, value) => {
this.setState({
title: value
})
}
重点注意该方法
shouldComponentUpdate(nextProps) {
return nextProps.html !== this.elem['innerText']
}
通过shouldComponentUpdate控制组件的渲染,从而解决不用每次输入都重新渲染组件,导致光标回位到初始状态的问题。
需要普及的关于dangerouslySetInnerHTML需要了解的
https://www.cnblogs.com/daowangzhizhu-pt/p/6385088.html
关于contentEditable属性可参看张鑫旭大神的两篇文章
http://www.zhangxinxu.com/wordpress/2016/01/contenteditable-plaintext-only/
http://www.zhangxinxu.com/wordpress/2010/12/div-textarea-height-auto/
网友评论