Javascript SVG foreignObject未捕获onClick事件(ReactJS)
我使用创建一个界面,用户可以在其中创建和编辑状态机。界面在某种程度上是可用的(至少在通过键盘快捷键创建或删除节点方面),但我需要更新界面本身,以便用户只需使用鼠标即可完成此操作。为此,我设想了以下界面: 就代码而言,这相当简单。关于API,我只需重写方法Javascript SVG foreignObject未捕获onClick事件(ReactJS),javascript,reactjs,events,svg,Javascript,Reactjs,Events,Svg,我使用创建一个界面,用户可以在其中创建和编辑状态机。界面在某种程度上是可用的(至少在通过键盘快捷键创建或删除节点方面),但我需要更新界面本身,以便用户只需使用鼠标即可完成此操作。为此,我设想了以下界面: 就代码而言,这相当简单。关于API,我只需重写方法renderNode,并使用foreignObject元素将HTML插入API使用的SVG中: public renderNode = (nodeRef: any, data: any, id: string, selected: boolea
renderNode
,并使用foreignObject
元素将HTML插入API使用的SVG中:
public renderNode = (nodeRef: any, data: any, id: string, selected: boolean, hovered: boolean) => {
const positioning = data.type === 'required' ? styles.required : styles.optional;
return (
<g className={`shape`}>
{!selected ? null : (
<foreignObject x="-77" y="-77" width="154" height="77" xmlnsXlink="http://www.w3.org/1999/xlink">
<i className={`fas fa-edit ${styles.btn} ${positioning} ${styles.edit}`} />
<i
className={`fas fa-minus-square ${styles.btn} ${positioning} ${styles.delete}`}
onClick={() => {
console.log('onClick');
this.deleteNode(id);
}}
/>
</foreignObject>
)}
<use
className={`node ${hovered ? 'hovered' : ''} ${selected ? 'selected' : ''}`}
x="-77"
y="-77"
width="154"
height="154"
xlinkHref={`#${data.type}`}
>
<svg viewBox="-27 0 154 154" id={data.type} width="154" height="154">
<rect transform="translate(50) rotate(45)" width="109" height="109" />
</svg>
</use>
</g>
);
};
知道为什么会这样吗
提前谢谢
编辑:根据James Delaney的建议,我尝试向所有可用节点添加引用,并随后添加事件侦听器。因为我可能从后端获取机器的信息,所以我不能静态地创建所有引用。因此,在获取节点后,我尝试在
componentDidMount
上创建一个“引用列表”,并在找到的所有节点上调用addEventListener
方法,将事件侦听器添加到此列表中,并在呈现节点时连接引用。实际上,这是组件didmount
:
public componentDidMount(): void {
const { machine } = this.props;
this.setState({ graph: machine ? stateMachineToGraph(machine) : initialGraph }, () => {
this.state.graph.nodes.forEach(node => {
const del = `${node.id}delete`,
edit = `${node.id}edit`;
this[del].addEventListener('click', this.deleteNode(node.id));
this[edit].addEventListener('click', this.editNode(node.id));
});
});
}
这将是前面所述的外来对象
:
<foreignObject x="-77" y="-77" width="154" height="77" xmlnsXlink="http://www.w3.org/1999/xlink">
<i
ref={edit => (this[`${id}edit`] = edit)}
className={`fas fa-edit ${styles.btn} ${positioning} ${styles.edit}`}
/>
<i
ref={del => (this[`${id}delete`] = del)}
className={`fas fa-minus-square ${styles.btn} ${positioning} ${styles.delete}`}
/>
</foreignObject>
现在我不测试特定节点的事件侦听器是否已经存在,我将进一步进行测试。对于这个实现,我最终可以删除节点,但它无法识别“click”事件。我只需将鼠标悬停在一个节点上,事件就会被触发(与“编辑”事件一起),节点就会被删除。为什么会这样
谢谢。- 尝试在svg元素上放置ref
- 在componentDidMount上,将click事件侦听器添加到引用
- 在componentWillUnmount中删除事件侦听器
componentDidMount() {
this.ref.addEventListener('click', this.deleteNode(id));
}
componentWillUnmount(){
this.ref.removeEventListener('click', this.deleteNode(id));
}
}
我不确定这是解决方案,但你可以试试 可以粘贴deleteNode函数的代码吗?当然可以。但是,我无法测试它,因为正如我所说的,它没有被调用:public deleteNode=id=>{const{graph}=this.state;graph.nodes.splice(0,1);graph.nodes=[…this.state.graph.nodes.filter(node=>node.id!==id)];this.setState({graph,});};我希望这能奏效,但不幸的是没有。看起来图形最初并没有呈现,因此每当我向引用添加一个事件侦听器时,它都是未定义的。。。不幸的是,我还没有找到一种方法来实现这一点,但我将通过这次尝试来更新主要帖子。谢谢你的意见。
public renderNode = (nodeRef: any, data: any, id: string, selected: boolean, hovered: boolean) => {
console.log(id);
if (this[`${id}edit`] && this[`${id}delete`]) {
this[`${id}edit`].addEventListener('click', this.editNode(id));
this[`${id}delete`].addEventListener('click', this.deleteNode(id));
}
const positioning = data.type === 'required' ? styles.required : styles.optional;
...
componentDidMount() {
this.ref.addEventListener('click', this.deleteNode(id));
}
componentWillUnmount(){
this.ref.removeEventListener('click', this.deleteNode(id));
}