React.js关于从组件中侦听窗口事件的最佳实践 [英] React.js best practice regarding listening to window events from components

查看:125
本文介绍了React.js关于从组件中侦听窗口事件的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我根据它们在视口中的位置设置了几个React.js组件的动画。如果组件位于视口中,则将不透明度设置为1,如果它不在视口中,则将其不透明度设置为0.我使用 getBoundingClient() top bottom 属性,用于确定组件是否在视口中。

I am animating several React.js components based on their position in the viewport. If the component is in the viewport, animate the opacity to 1, if it's not in the viewport, animate its opacity to 0. I am using getBoundingClient()'s top and bottom properties to determine if the component is within the viewport.

ComponentA显示了其他B,C和D组件所遵循的模式。他们每个人都在监听窗口滚动事件。

ComponentA shows the pattern I followed for the other B, C, and D components. They each are listening for the window scroll event.

这是React方法,每个组件必须向窗口添加一个事件监听器?同一窗口上有多个滚动事件侦听器?

Is this the "React" way to do this by each component having its having to add an event listener to the window? Multiple scroll event listeners on the same window?

或者,在 Home 所有者组件中,将滚动事件监听器添加到窗口是否有更好的方法?那么ownee子组件是否仍然能够使用 getBoundingClient()知道它们在DOM中的位置?

Or is there a better way by adding the scroll event listener to the window once at the Home owner component? Then would the ownee child components still be able to know where they are in the DOM using the getBoundingClient()?

Home = React.createClass({
 render: function() {
    <div>
       <ComponentA />
       <ComponentB />
       <ComponentC />
       <ComponentD />
    </div>
  };
});

ComponentA = React.createClass({
  componentDidMount: function() {
   window.addEventListener('scroll', this.handleScroll);
},
  componentWillUnmount: function() {
    window.removeEventListener('scroll', this.handleScroll);
   },

handleScroll: function() {
  var domElement = this.refs.domElement.getDOMNode();
  this.inViewPort(domElement);
},

inViewPort: function(element) {
  var elementBounds = element.getBoundingClientRect();
  (elementBounds.top <= 769 && elementBounds.bottom >= 430) ? TweenMax.to(element, 1.5, { opacity: 1 }) : TweenMax.to(element, 1.5, { opacity: 0 });
},
render: function() {
  return (/* html to render */);
 }

});


推荐答案

有几种不同的方法可以做到这一点。一个是通过组合:

There are a few different ways you could do this. One is through composition:

var React = require("react");
var _ = require("underscore");

var ScrollWrapper = React.createClass({
    propTypes: {
        onWindowScroll: React.PropTypes.func
    },

    handleScroll: function(event) {
        // Do something generic, if you have to
        console.log("ScrollWrapper's handleScroll");

        // Call the passed-in prop
        if (this.props.onWindowScroll) this.props.onWindowScroll(event);
    },

    render: function () {
        return this.props.children;
    },

    componentDidMount: function() {
        if (this.props.onWindowScroll) window.addEventListener("scroll", this.handleScroll);
    },

    componentWillUnmount: function() {
        if (this.props.onWindowScroll) window.removeEventListener("scroll", this.handleScroll);
    }
});

var ComponentA = React.createClass({
    handleScroll: function(event) {
        console.log("ComponentA's handleScroll");
    },

    render: function() {
        return (
            <ScrollWrapper onWindowScroll={this.handleScroll}>
                <div>whatever</div>
            </ScrollWrapper>
        );
    }
});

现在,您可以将通用逻辑放在 ScrollWrapper 组件,突然变得可重用。你可以创建一个 ComponentB 来呈现 ScrollWrapper 就像 ComponentA 的确如此。

Now, you can place your generic logic in the ScrollWrapper component, and suddenly it becomes reusable. You could create a ComponentB that renders a ScrollWrapper just like ComponentA does.

为了满足你的例子,也许你必须从<$ c $传递 ScrollWrapper 一些额外的道具C> ComponentA 。也许你会传递一个包含 ref 实例的道具来调用你的逻辑。您甚至可以传递一些选项或参数来自定义补间或边界。我没有编写任何代码,因为我认为你会理解它,并且能够使用我提供的基础为你自己定制/编写它。

To satisfy your example, maybe you'll have to pass the ScrollWrapper some extra props from ComponentA. Maybe you'll pass it a prop that contains an instance of the ref to call your logic on. You could even pass it some options or arguments to customize the tween or the bounds. I didn't code any of this because I think you'll understand it and be able to customize/write it for yourself with the base I've provided.

其他实现此类事情的方法是通过Mixin。尽管如此,有很多关于Mixins是好还是坏的讨论,他们甚至可能在未来被React弃用?你可以阅读一下这个,然后自己决定你的想法。

The other way to achieve this sort of thing is through a Mixin. Although, there's a lot of talk about if Mixins are good or bad, and they might even be being deprecated by React in the future? You can do some reading about this and decide for yourself what you think.

这篇关于React.js关于从组件中侦听窗口事件的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆