我有一个简单的组件,它有一个像这样的渲染:
render: function(){
return (
<textarea className="wmd-input" id="wmd-input" ref={this.initiatePagedown}></textarea>
)
}
initiatePagedown: function(input){
//code that initiates markdown editor.
attr = $(input).attr('id').split('wmd-input')[1];
converter = new Markdown.Converter();
Markdown.Extra.init(converter, {highlighter: "highlight"});
editor = new Markdown.Editor(converter, attr);
return editor.run();
},
组件挂载n次,因此创建多个文本区域。
问题是ref回调与第一个组件的输入一起运行,所以它总是第一个被操纵的组件,而不是我选择的那个。所以让我们说这个组件被挂载了两次,那么ref回调将在第一个组件实例上被调用两次,而不是每个组件实例一次。如何解决这个问题?
您正在使用Pagedown编辑器指向页面上的特定元素ID,因为您正在传递第二个参数attr
:
new Markdown.Editor(converter, attr);
查看Markdown.Editor
构造函数的第二个参数的文档:
如果给定,该参数是一个字符串,附加到编辑器使用的三个元素的HTML元素id…因此,您可以创建第二个输入框作为
<textarea id="wmd-input-2">
,并将字符串"-2"作为第二个参数传递给构造函数。
现在你总是用相同的ID创建一个编辑器:
id="wmd-input"
因此编辑器构造函数将始终匹配页面上该ID的每个现有实例。
这是一个非常糟糕的API,迫使您指向元素id。作为一种变通方法,我可能会让id成为你传递进来的一个道具,这样包装组件/页面就可以决定应该有多少编辑器,你可以像这样构建id
return (
<textarea id={ `wmd-input-${ this.props.id }` } ... />
)
然后你可以用类似
的东西实例化这个不幸的APIeditor = new Markdown.Editor(converter, `-${ this.props.id }`);