Javascript 使用contenteditable元素的ReactJS类组件render array.map
我遇到了一个无法调试的有趣问题 目标 在类组件上,在render函数内部,使用Javascript 使用contenteditable元素的ReactJS类组件render array.map,javascript,reactjs,jsx,contenteditable,Javascript,Reactjs,Jsx,Contenteditable,我遇到了一个无法调试的有趣问题 目标 在类组件上,在render函数内部,使用this.state.items.map((item,index)=>{})迭代state中的对象数组,并返回contentEditable段落元素 在每个contentEditable段落元素上,侦听onKeyUp事件。如果从e.使用的键是enter(13)键,则使用键控元素的索引向此.state.items添加一个新项,以便使用拼接在该索引后插入一个新元素 看到预期结果吗? 不可以。新添加的项在渲染时将放在循环的末
this.state.items.map((item,index)=>{})迭代state
中的对象数组,并返回contentEditable
段落元素
在每个contentEditable
段落元素上,侦听onKeyUp
事件。如果从e.使用的键
是enter(13)键,则使用键控元素的索引向此.state.items添加一个新项
,以便使用拼接
在该索引后插入一个新元素
看到预期结果吗?
不可以。新添加的项在渲染时将放在循环的末尾
示例情况和再现步骤:
在第一个P
元素中键入“test1”
点击回车键(创建并聚焦一个新的P
元素)
在第二个新创建的P
元素中键入“test2”
通过shift+tab或单击重新聚焦第一个P
元素
按回车键
参见观察结果:创建并聚焦了一个新的P
元素,但它位于列表的末尾,而不是预期的位置,位于“test1”和“test2”P
元素之间
以下是我目前掌握的代码:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
items: [this.paragraphTemplate()]
}
}
render() {
return (
<section>
<div>
{this.state.items.map((item, index) => {
return <p ref={item.ref}
key={index}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e, index, item)}></p>
})}
</div>
</section>
)
}
handleParagraphKeyUp = (e, index, item) => {
if (e.which === 13) {
let addition = this.paragraphTemplate()
this.setState(state => {
state.items.splice(index + 1, 0, addition)
return {
blocks: state.items
}
}, () => {
addition.ref.current.focus()
/* clear out the br and div elements that the browser might auto-add on "enter" from the element that was focused when the "enter" key was used */
this.state.items[index].ref.current.innerHTML = this.state.items[index].ref.current.innerHTML.replace(/<br\s*[\/]?>/gi, '').replace(/<[\/]?div>/gi, '')
})
return false
}
}
paragraphTemplate = () => {
return {
ref: React.createRef()
}
}
}
export default MyComponent
类MyComponent扩展了React.Component{
建造师(道具){
超级(道具)
此.state={
项目:[此.paragraphTemplate()]
}
}
render(){
返回(
{this.state.items.map((项,索引)=>{
returnthis.handleParagraphKeyUp(e,索引,项)}>
})} ) } handleParagraphKeyUp=(e,索引,项目)=>{ 如果(e.which==13){ 让addition=this.paragraphTemplate() this.setState(state=>{ 状态项拼接(索引+1,0,加法) 返回{ 块:state.items } }, () => { addition.ref.current.focus() /*从使用“回车”键时聚焦的元素中清除浏览器可能在“回车”时自动添加的br和div元素*/ this.state.items[index].ref.current.innerHTML=this.state.items[index].ref.current.innerHTML.replace(//gi',).replace(//gi',) }) 返回错误 } } 段落模板=()=>{ 返回{ ref:React.createRef() } } } 导出默认MyComponent 下面是一个示例,其中包含上面的代码 如果您采取上述步骤,您将看到我遇到的问题 如果您需要任何进一步的信息,请告诉我,提前谢谢 另外,如果代码有任何改进,请告诉我。我在React工作了很短的时间,希望得到关于如何使其更好/更干净的任何反馈 已更新在
p
元素中添加了key={index}
。注意:这并不反映任何答案,它只是为了与ReactJS列表呈现保持一致而添加的。要呈现项目列表,React需要键来跟踪元素
见此:
这是你的最新工作报告
<p ref={item.ref}
key={item.id}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e,
this.handleParagraphKeyUp(e,
要呈现项目列表,React需要关键点来跟踪元素
见此:
这是你的最新工作报告
<p ref={item.ref}
key={item.id}
contentEditable
suppressContentEditableWarning
onKeyUp={e => this.handleParagraphKeyUp(e,
this.handleParagraphKeyUp(e,
您需要在
上使用一个键,而该键不能作为索引,否则新项目将在最后呈现;再次。@Thomas是的,您是正确的,我确实忘了将键放入(它在本地代码中,但没有放入小提琴中)。但是,我不知道您不能使用索引。这对我来说是新的。谢谢!我会更新问题,以包括您需要在上使用的键,并且键不能是索引,否则新项目将在最后呈现;再次。@Thomas是的,您是正确的,我这样做了忘记输入键
(它在我的本地代码中,但没有输入小提琴)。然而,我不知道你不能使用索引。
。这对我来说是新的。谢谢!我会更新问题,将KeyThank@Tubc!从@Thomas和这个的评论中删除,我现在知道了一些我不知道的事情,它正在按预期工作。@klye\u g还有一点需要注意的是,我仍然使用索引作为一个键。但只有当我知道列表w时我永远不会更新订单,这更方便,因为我们没有真正的id。谢谢@Tubc!从@Thomas的评论和这个,我现在知道了一些我没有的东西,它正在按预期工作。@klye\u g还有一点需要注意的是,我仍然使用索引作为键。但只有当我知道列表永远不会更新订单时,它才更方便因为我们没有真正的身份证。