React - 如果反应更新任何DOM元素,如何通知popper重新定位我的popover

问题描述 投票:-1回答:2

相关版本:React 16.4.2,Bootstrap 4.1.3,popper.js 1.14.4,Typescript 3.0.3

我在我的Popover应用程序中使用Bootstrap react功能。

如果页面的其余部分是静态的,则Popover可以很好地工作。当页面被更改时(在浏览器级别),Popover会非常快速和平滑地重新定位,以便在其锚定到的内容可见时保持可见:

  • 当滚动时,如果它碰到窗户边缘
  • 如果屏幕在手机上旋转
  • 如果窗口调整大小

这一切都运作良好,因为popper.js显然正在观看window.scrollwindow.resize事件,根据这个答案:Bootstrap 4 - how does automatic Popover re-positioning work?

当我的react应用程序开始显示/隐藏DOM元素时,问题就出现了。因为popper.js不了解react,所以它不知道DOM的变化,所以它不知道Popovers可能需要重新定位。

我知道在每个Popover锚上调用popover("update")都有效,因为我已经添加了这样的代码来间歇地执行它:

window.setInterval(()=> $(this.selfRef).popover("update"), 100);

但那令人讨厌和浪费,而且有点笨拙。

有没有办法让react告诉我何时更新DOM中的任何节点,那么我可以告诉popper.js更新弹出窗口的位置?

请注意,导致DOM更改的react组件不一定位于使用Popover的组件附近。它可能是层次结构中完全独立的部分,恰好在带有弹出窗口的组件之前显示 - 所以我认为解决方案不是componentWillReceiveProps()或类似于Popover组件的方法,因为它可能不是组件这引起了运动。

请注意,我知道像react-bootstrapreactstrapreact-popper这样的项目 - 但我不想使用它们。


编辑:似乎MutationObserver可能是一个没有反应的方式来做到这一点。我想,因为React已经完成了所有的协调工作,也许有办法让它在实际编辑DOM时通知我。

reactjs bootstrap-4 popper.js
2个回答
0
投票

“导致DOM更改的react组件不一定位于使用Popover的组件附近。它可能是层次结构完全独立的部分”

如果更改DOM的Component和创建Popover的Component都在同一父级中,则可以在执行.popover('update')的父级中共享一个方法。更改DOM的组件需要触发此事件,但不需要特别“了解”Popover组件。 Popover组件不需要知道DOM更改组件。

class ChangeDom extends React.Component {

  constructor(props) {
     super(props);
     this.changeDom = this.changeDom.bind(this);
  }

  changeDom () {
      this.props.domChanged();
  }

  render() {
    return (
    <div>
        <button className="ml-2 btn btn-primary" onClick={this.changeDom}>Change Dom
        </button>
    </div>)
  }
}

class Pop extends React.Component {

  constructor(props) {
     super(props);
     this.togglePopover = this.togglePopover.bind(this);
  }

  togglePopover() {
      $('[data-toggle="popover"]').popover('toggle');
  }

  render() {
    return (
    <div class="position-relative">
        <button className="mt-4 btn btn-primary" onClick={this.togglePopover} data-toggle="popover"
        </button>
    </div>)
  }
}

class Parent extends React.Component {

  domChanged(){
      $('[data-toggle="popover"]').popover("update");
  }

  render() {
    return (
    <div>
        <ChangeDom domChanged={this.domChanged} />
        <Pop />
    </div>)
  }
}

但是:ぁzxswい


0
投票

这是我目前在基于https://www.codeply.com/go/NhcfE8eAEY的解决方案上的尝试。

MutationObserver是放置在应用程序层次结构顶部的组件。 UserApp类在我的应用程序的各个地方被用于一堆东西。

Popover事件中发射popover("update")引起无限递归的可能性使我对长期使用此解决方案持谨慎态度。它似乎现在正在完成这项工作,但这是单方向绑定意在避免的事情之一。

从好的方面来说,即使你的应用程序中有非反应组件(例如,Bootstrap MutationObserver),这也可以工作。

navbar
© www.soinside.com 2019 - 2024. All rights reserved.