暗恋学妹的开心果 · 如何开发一款机器人_机器人开发-CSDN博客· 6 月前 · |
鼻子大的小狗 · 618必抢中端机!红米K70与一加Ace3, ...· 6 月前 · |
爱健身的瀑布 · 你似乎来到了没有知识存在的荒原 - 知乎· 1 年前 · |
考研的紫菜汤 · 深圳篮球:《灌篮高手》——那些年一起追的篮球 ...· 1 年前 · |
好帅的土豆 · 东南大学某院长袁久红这次可能被黑了!色情照竟 ...· 1 年前 · |
如何侦听
contentEditable
-based控件的更改事件?
var Number = React.createClass({
render: function() {
return <div>
<span contentEditable={true} onChange={this.onChange}>
{this.state.value}
</span>
{this.state.value}
</div>;
onChange: function(v) {
// Doesn't fire :(
console.log('changed', v);
getInitialState: function() {
return {value: '123'}
React.renderComponent(<Number />, document.body);
这可能不是你正在寻找的答案,但我自己也在努力解决这个问题,并对建议的答案有问题,我决定让它变得不受控制。
当
editable
属性为
false
时,我会按原样使用
text
属性,但当它为
true
时,我会切换到编辑模式,在该模式下
text
不起作用(但至少浏览器不会崩溃)。在此期间,控件将触发
onChange
。最后,当我将
editable
改回
false
时,它会用传递给
text
的内容填充HTML
/** @jsx React.DOM */
'use strict';
var React = require('react'),
escapeTextForBrowser = require('react/lib/escapeTextForBrowser'),
{ PropTypes } = React;
var UncontrolledContentEditable = React.createClass({
propTypes: {
component: PropTypes.func,
onChange: PropTypes.func.isRequired,
text: PropTypes.string,
placeholder: PropTypes.string,
editable: PropTypes.bool
getDefaultProps() {
return {
component: React.DOM.div,
editable: false
getInitialState() {
return {
initialText: this.props.text
componentWillReceiveProps(nextProps) {
if (nextProps.editable && !this.props.editable) {
this.setState({
initialText: nextProps.text
componentWillUpdate(nextProps) {
if (!nextProps.editable && this.props.editable) {
this.getDOMNode().innerHTML = escapeTextForBrowser(this.state.initialText);
render() {
var html = escapeTextForBrowser(this.props.editable ?
this.state.initialText :
this.props.text
return (
<this.props.component onInput={this.handleChange}
onBlur={this.handleChange}
contentEditable={this.props.editable}
dangerouslySetInnerHTML={{__html: html}} />
handleChange(e) {
if (!e.target.textContent.trim().length) {
e.target.innerHTML = '';
this.props.onChange(e);
module.exports = UncontrolledContentEditable;
这里有一个由lovasoa提供的组件,其中包含了大部分内容: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
他在emitChange中对这一事件进行了垫片
emitChange: function(evt){
var html = this.getDOMNode().innerHTML;
if (this.props.onChange && html !== this.lastHtml) {
evt.target = { value: html };
this.props.onChange(evt);
this.lastHtml = html;
}
我正在成功地使用类似的方法
我建议使用mutationObserver来做这件事。它可以让你更好地控制正在发生的事情。它还提供了有关浏览如何解释所有击键的更多详细信息
在TypeScript这里
import * as React from 'react';
export default class Editor extends React.Component {
private _root: HTMLDivElement; // Ref to the editable div
private _mutationObserver: MutationObserver; // Modifications observer
private _innerTextBuffer: string; // Stores the last printed value
public componentDidMount() {
this._root.contentEditable = "true";
this._mutationObserver = new MutationObserver(this.onContentChange);
this._mutationObserver.observe(this._root, {
childList: true, // To check for new lines
subtree: true, // To check for nested elements
characterData: true // To check for text modifications
public render() {
return (
<div ref={this.onRootRef}>
Modify the text here ...
private onContentChange: MutationCallback = (mutations: MutationRecord[]) => {
mutations.forEach(() => {
// Get the text from the editable div
// (Use innerHTML to get the HTML)
const {innerText} = this._root;
// Content changed will be triggered several times for one key stroke
if (!this._innerTextBuffer || this._innerTextBuffer !== innerText) {
console.log(innerText); // Call this.setState or this.props.onChange here
this._innerTextBuffer = innerText;
private onRootRef = (elt: HTMLDivElement) => {
this._root = elt;
}
这是对我有效的最简单的解决方案。
<div
contentEditable='true'
onInput={e => console.log('Text inside div', e.currentTarget.textContent)}
Text inside div
</div>
因为当编辑完成时,元素的焦点总是丢失的,您可以简单地使用onBlur钩子。
<div onBlur={(e)=>{console.log(e.currentTarget.textContent)}} contentEditable suppressContentEditableWarning={true}>
<p>Lorem ipsum dolor.</p>
</div>
如果你正在寻找一种简单易用的方法,它就在这里。
<div
contentEditable={true}
onSelect={() => callMeOnSelect()}
onChange={() => callMeOnChange()}
onMouseUp={() => callMeOnMouseUp()}
className="myClassNameHere"/>
如果您想要在触发选择时获取所选文本,您可以这样做。
let selection = window.getSelection().toString();
我已经尝试使用上面的 example from Saint Laurent :
<div
onBlur={e => {
console.log(e.currentTarget.textContent);
contentEditable
suppressContentEditableWarning={true}
<p>Lorem ipsum dolor.</p>
</div>
在我尝试将这个值设置为state之前,它一直工作得很好。当我使用一个调用
setState(e.currentTarget.textContent)
的函数组件时,我得到的
currentTarget
为空。
setState
异步工作,而
currentTarget
在那里不可用。
在React 17.0.2中对我起作用的修复方法是使用
e.target.innerText
<div
onBlur={e => setState(e.target.innerText)}
contentEditable
suppressContentEditableWarning={true}
<p>Lorem ipsum dolor.</p>
</div>
这是我基于 https://stackoverflow.com/a/27255103 的基于钩子的版本
const noop = () => {};
const ContentEditable = ({
html,
onChange = noop,
html: string;
onChange?: (s: string) => any;
}) => {
const ref = useRef<HTMLDivElement>(null);
const lastHtml = useRef<string>('');
const emitChange = () => {
const curHtml = ref.current?.innerHTML || '';
if (curHtml !== lastHtml.current) {
onChange(curHtml);
lastHtml.current = html;
useEffect(() => {
if (!ref.current) return;
if (ref.current.innerHTML === html) return;
ref.current.innerHTML = html;
}, [html]);
return (
onInput={emitChange}