¿Cómo escucho el cambio de evento para el contentEditable
control basado en?
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);
initialValue
enstate
y lo uso enrender
, pero no dejo Reaccionar actualización aún más.contentEditable
cambio de mi enfoque, en lugar de unspan
oparagraph
, he usado uninput
junto con sureadonly
atributo.Respuestas:
Editar: vea la respuesta de Sebastien Lorber que corrige un error en mi implementación.
Utilice el evento onInput y, opcionalmente, onBlur como respaldo. Es posible que desee guardar el contenido anterior para evitar enviar eventos adicionales.
Personalmente tendría esto como mi función de renderizado.
jsbin
Que usa este simple contenedor alrededor de contentEditable.
fuente
this.setState({html: "something not in the editable div"}})
this.getDOMNode().innerHTML
enshouldComponentUpdate
no está muy optimizado derechastate.html
el último valor "conocido", React no actualizará el DOM porque el nuevo html es exactamente el mismo en lo que respecta a React (aunque el DOM real es diferente). Consulte jsfiddle . No he encontrado una buena solución para esto, por lo que cualquier idea es bienvenida.shouldComponentUpdate
debe ser puro (no tener efectos secundarios).Editar 2015
Alguien ha hecho un proyecto en NPM con mi solución: https://github.com/lovasoa/react-contenteditable
Edición 06/2016: Acabo de encontrar un nuevo problema que ocurre cuando el navegador intenta "reformatear" el html que le acaba de dar, lo que lleva a que el componente siempre vuelva a renderizarse. Ver
Edición 07/2016: aquí está mi contenido de producción Implementación editable. Tiene algunas opciones adicionales sobre las
react-contenteditable
que quizás desee, que incluyen:Resumen:
La solución de FakeRainBrigand me ha funcionado bastante bien durante algún tiempo hasta que tuve nuevos problemas. ContentEditables son una molestia, y no son realmente fáciles de manejar con React ...
Este JSFiddle demuestra el problema.
Como puede ver, cuando escribe algunos caracteres y hace clic en
Clear
, el contenido no se borra. Esto se debe a que intentamos restablecer el contenteditable al último valor de dom virtual conocido.Entonces parece que:
shouldComponentUpdate
evitar los saltos de posición del cursorshouldComponentUpdate
esta manera.Por lo tanto, necesita una línea adicional para que, siempre que
shouldComponentUpdate
devuelva sí, esté seguro de que el contenido DOM está realmente actualizado.Entonces, la versión aquí agrega ay se
componentDidUpdate
convierte en:El dom virtual permanece desactualizado y puede que no sea el código más eficiente, pero al menos funciona :) Mi error está resuelto
Detalles:
1) Si pones shouldComponentUpdate para evitar saltos de intercalación, entonces el contenteditable nunca se vuelve a reproducir (al menos en las pulsaciones de teclas)
2) Si el componente nunca se vuelve a reproducir con la pulsación de una tecla, React mantiene un dom virtual obsoleto para este contenteditable.
3) Si React mantiene una versión desactualizada de contenteditable en su árbol de dom virtual, entonces si intenta restablecer el contenteditable al valor desactualizado en el dom virtual, entonces durante la diferencia de dom virtual, React calculará que no hay cambios en aplicar al DOM!
Esto sucede principalmente cuando:
fuente
{...this.props}
que lo uses para que el cliente pueda personalizar este comportamiento desde afuerashouldComponentUpdate
código previene los saltos de intercalación?Esta es la solución más simple que funcionó para mí.
fuente
onInput
como se indica en el ejemplo.Probablemente esta no sea exactamente la respuesta que está buscando, pero habiendo luchado con esto yo mismo y teniendo problemas con las respuestas sugeridas, decidí hacerlo sin control.
Cuando
editable
es propfalse
, utilizotext
prop tal como está, pero cuando lo estátrue
, cambio al modo de edición en el quetext
no tiene ningún efecto (pero al menos el navegador no se asusta). Durante este tiempoonChange
son disparados por el control. Finalmente, cuando vuelvo a cambiareditable
afalse
, llena HTML con lo que se pasótext
:fuente
shouldComponentUpdate
tan fácilmente, por lo que ya no me salva de los saltos de intercalación. Finalmente, tengo:empty:before
marcadores de posición de pseudoelementos CSS, pero estashouldComponentUpdate
implementación impidió que FF y Safari limpiaran el campo cuando el usuario lo borraba. Tardé 5 horas en darme cuenta de que puedo eludir todos estos problemas con la CE incontrolada.editable
enUncontrolledContentEditable
. ¿Podría proporcionar un ejemplo ejecutable?editable
desde afuera. Piense en un campo que se puede editar en línea cuando el usuario presiona "Editar" y debería ser de nuevo de solo lectura cuando el usuario presiona "Guardar" o "Cancelar". Entonces, cuando es de solo lectura, uso accesorios, pero dejo de mirarlos cada vez que entro en el "modo de edición" y solo miro los accesorios nuevamente cuando salgo de él.escapeTextForBrowser
de nombre aescapeTextContentForBrowser
.Dado que cuando se completa la edición, el enfoque del elemento siempre se pierde, simplemente puede usar el gancho onBlur.
fuente
Sugiero usar un mutationObserver para hacer esto. Te da mucho más control sobre lo que está sucediendo. También le brinda más detalles sobre cómo el navegador interpreta todas las pulsaciones de teclas
Aquí en TypeScript
fuente
Aquí hay un componente que incorpora mucho de esto por lovasoa: https://github.com/lovasoa/react-contenteditable/blob/master/index.js
Calza el evento en el emisChange
Estoy usando un enfoque similar con éxito
fuente