【问题标题】:React SVG not rerendering on attribute updateReact SVG不会在属性更新时重新渲染
【发布时间】:2019-08-20 13:52:16
【问题描述】:

我正在通过滑块输入控件更新 SVG 过滤器属性,但它不会持续更新呈现的过滤器。

这是工作代码:https://codepen.io/dgwyer/pen/EXmqrb

如果我使用dangerouslySetInnerHTML 来设置过滤器,那么它可以工作,但是这个 hack 还不足以在生产代码中使用?

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { blur: 2 };
    this.blurChange = this.blurChange.bind(this);
  }

  blurChange(event) {
    this.setState({ blur: Number(event.target.value) });
  }

  render() {
    return (
      <div>
        <svg width="0" height="0" viewBox="0 0 0 0">
          <filter id="outline"
            dangerouslySetInnerHTML={{
              __html: `<feGaussianBlur result="blurOut" stdDeviation="${this.state.blur}" />`
            }}
          />
          <filter id="outline1">
            <feGaussianBlur result="blurOut" stdDeviation={this.state.blur} />`
          </filter>            
        </svg>
        <h1 className="fe">Working</h1>
        <div className="control"><input type="range" min="0" max="50" onChange={this.blurChange} value={this.state.blur} /><h3>Blur Slider</h3></div>
        <h1 className="fe1">Not Working</h1>
        <div className="control"><input type="range" min="0" max="50" onChange={this.blurChange} value={this.state.blur} /><h3>Blur Slider</h3></div>
        </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

在不使用dangerouslySetInnerHTML hack 的情况下,是否可以像平常使用 React 一样更新 SVG 过滤器属性?

【问题讨论】:

    标签: reactjs svg filter attributes jsx


    【解决方案1】:

    有趣的是,显然必须重新安装 &lt;feGaussianBlur /&gt; 才能正确应用更改,而 React 不会重新安装它,而只会更新 stdDeviation 属性。要修复它,请在 &lt;feGaussianBlur /&gt; 上额外使用 key 属性,以便 React 每次 this.state.blur 更改时都会重新安装它:

    <filter id="outline1">
      <feGaussianBlur key={this.state.blur} stdDeviation={this.state.blur} />
    </filter>
    

    【讨论】:

    • 谢谢,这确实有效,这意味着不需要丑陋的dangerouslySetInnerHTML hack。更有趣的是,您是否在 SVG 过滤器原语或它所应用的 HTML 元素上设置键似乎并不重要。不确定我是否了解幕后发生的事情,但如果关键在 HTML 元素上。这将如何触发 SVG 原语重新挂载?是因为它们是链接的,并且更新任何一个上的密钥都会强制重新安装吗?我已经更新了笔以包含两种情况:codepen.io/dgwyer/pen/EXmqrb
    • 它不会触发 SVG 原语重新挂载。关键是我们需要触发浏览器在该 HTML 元素上重新应用样式。因此,您可以通过重新安装 SVG 或 HTML 元素来触发它。基本上,它们是使用您的 CSS 样式链接的(与 React 无关)。当您重新安装应用这些样式的 HTML 元素时,浏览器当然会重新计算其样式并重新渲染。