我希望使用类似于
这个问题很老了,但我刚刚为自己解决了它,所以想分享一下。
onChange 永远不会触发,onInput 也不是最好的方法。你需要用 onFocus 和 onBlur 来模拟 onChange。
当 onFocus 发生时,将 innerHTML 的值复制到一个变量中。
当 onBlur 发生时,将 innerHTML 与该变量进行比较,看是否有更改。如果有更改,则执行 onChange 相关操作。你需要像这样:
const onFocus = (e) => {
val_start = e.target.innerHTML;
};
const onBlur = (e) => {
if(val_start !== e.target.innerHTML) {
//Whatever you put here will act just like an onChange event
const html = e.target.innerHTML;
setValue(html);
}
};
contentEditable
可以使 div
内容可编辑。
你可以使用 onBlur
而不是 onInput
,这样闪烁的光标就不会不停地移动到文本开头。
无论你对文本做出什么更改,都将在屏幕上显示,并且一旦你将焦点移出元素,状态就会更新。
<div onBlur={onChange} contentEditable>
{value}
</div>
注意:下面的代码是一个简化版本,原本是一个更长的代码片段,其中使用了zod。为了简单起见,我删除了一些部分。
export const EmailForm: React.FC = () => {
const {register, handleSubmit, formState: {errors}, setValue} = useForm();
// Optional: for when the <label> gets clicked
const emailRef = useRef<HTMLDivElement>(null);
const onSubmit = async (data: FieldValues) => {
// Send data here. In catch statement use setError or formError
console.log(data);
}
const onInput = (e: FormEvent<HTMLInputElement>) => {
setValue('email', e.currentTarget.innerText);
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* The actual field which react hook form validates */}
<input type="hidden" {...register('email')} />
<div>
<label onClick={() => emailRef.current?.focus()}>Email</label>
<div contentEditable onInput={onInput} ref={emailRef}
role="textbox" tabIndex={0}></div>
<div>{errors.email?.message}</div>
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
);
}
<textarea>
一样工作。这样做的好处各有不同,但通常我会让它在用户输入时自动扩展。
由于这是 React,我使用 RHF 来管理内容,所以我们需要在用户输入时填充一个隐藏字段。这个字段也可以是一个 <textarea>
,但请确保它是不可见的。
<input type="hidden" {...register('email')} />
<label onClick={() => emailRef.current?.focus()}>Email</label>
<div contentEditable onInput={onInput} ref={emailRef}
role="textbox" tabIndex={0}></div>
<label>
在点击时像标签一样聚焦在 <div>
上,你可以选择使用 useRef
来实现这个功能。const emailRef = useRef<HTMLDivElement>(null);
onInput={onInput}
回调函数,现在每当用户输入内容时,setValue
函数就会被调用,使得RHF可以像处理其他字段一样访问数据。这进而有助于生成错误信息。<div>{errors.email?.message}</div>
onSubmit
回调函数。从那里,您可以将其发送到您的服务器。<div onChange={onChange} contentEditable>
应该使用 onChange
而不是 onInput
demo:https://codesandbox.io/s/react-editable-cell-forked-ey7o1?file=/src/App.js