你如何在ReactJS中盘旋? - onMouseLeave在快速悬停期间未注册

时间:2015-05-01 03:26:13

标签: css javascript-events mouseevent reactjs

在进行内联样式设置时,如何在ReactJS中实现悬停事件或活动事件?

我发现onMouseEnter,onMouseLeave方法有问题,所以希望还有另一种方法可以做到。

具体来说,如果您非常快速地将鼠标悬停在某个组件上,则只会注册onMouseEnter事件。 onMouseLeave永远不会触发,因此无法更新状态......使组件看起来好像仍然悬停在上面。如果你试图模仿":活跃的"我已经注意到了同样的事情。 css伪类。如果你真的很快点击,只会注册onMouseDown事件。 onMouseUp事件将被忽略...使组件显示为活动状态。

这是一个显示问题的JSFiddle:https://jsfiddle.net/y9swecyu/5/

JSFiddle的视频问题:https://vid.me/ZJEO

代码:

var Hover = React.createClass({
    getInitialState: function() {
        return {
            hover: false
        };
    },
    onMouseEnterHandler: function() {
        this.setState({
            hover: true
        });
        console.log('enter');
    },
    onMouseLeaveHandler: function() {
        this.setState({
            hover: false
        });
        console.log('leave');
    },
    render: function() {
        var inner = normal;
        if(this.state.hover) {
            inner = hover;
        }

        return (
            <div style={outer}>
                <div style={inner}
                    onMouseEnter={this.onMouseEnterHandler}
                    onMouseLeave={this.onMouseLeaveHandler} >
                    {this.props.children}
                </div>
            </div>
        );
    }
});

var outer = {
    height: '120px',
    width: '200px',
    margin: '100px',
    backgroundColor: 'green',
    cursor: 'pointer',
    position: 'relative'
}

var normal = {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'red',
    opacity: 0
}

var hover = {
    position: 'absolute',
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'red',
    opacity: 1
}

React.render(
    <Hover></Hover>,         
    document.getElementById('container')
)

15 个答案:

答案 0 :(得分:42)

你有没有尝试过这些?

onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

https://facebook.github.io/react/docs/events.html

它还提到了以下内容:

React规范化事件,以便它们在不同的浏览器中具有一致的属性。

下面的事件处理程序由冒泡阶段的事件触发。要为捕获阶段注册事件处理程序,请将Capture附加到事件名称;例如,不使用onClick,而是使用onClickCapture来处理捕获阶段的click事件。

答案 1 :(得分:23)

以前的答案非常令人困惑。您不需要react-state来解决这个问题,也不需要任何特殊的外部库。它可以通过纯css / sass来实现:

风格:

.hover {
  position: relative;

  &:hover &__no-hover {
    opacity: 0;
  }

  &:hover &__hover {
    opacity: 1;
  }

  &__hover {
    position: absolute;
    top: 0;
    opacity: 0;
  }

  &__no-hover {
    opacity: 1;
  }
}

React-Component

一个简单的Hover Pure-Rendering-Function:

const Hover = ({ onHover, children }) => (
    <div className="hover">
        <div className="hover__no-hover">{children}</div>
        <div className="hover__hover">{onHover}</div>
    </div>
)

<强>用法

然后像这样使用它:

    <Hover onHover={<div> Show this on hover </div>}>
        <div> Show on no hover </div>
    </Hover>

答案 2 :(得分:11)

如果您可以制作一个显示onMouseEnter / onMouseLeave或onMouseDown / onMouseUp错误的小型演示,那么将其发布到ReactJS的问题页面或邮件列表是值得的,只是为了提出问题并听取开发人员的意见不得不说。

在您的用例中,您似乎暗示CSS:hover和:active状态足以满足您的目的,因此我建议您使用它们。 CSS比Javascript更快,更可靠,因为它直接在浏览器中实现。

但是,:hover和:无法在内联样式中指定活动状态。您可以做的是为元素分配ID或类名,并在样式表中编写样式,如果它们在您的应用程序中有些不变,或者在动态生成的<style>标记中。

以下是后一种技术的示例:https://jsfiddle.net/ors1vos9/

答案 3 :(得分:8)

我在禁用按钮上侦听onMouseLeave事件时遇到了同样的问题。我通过在包含禁用按钮的元素上侦听本机mouseleave事件来解决它。

componentDidMount() {
    this.watchForNativeMouseLeave();
},
componentDidUpdate() {
    this.watchForNativeMouseLeave();
},
// onMouseLeave doesn't work well on disabled elements
// https://github.com/facebook/react/issues/4251
watchForNativeMouseLeave() {
    this.refs.hoverElement.addEventListener('mouseleave', () => {
        if (this.props.disabled) {
            this.handleMouseOut();
        }
    });
},
render() {
    return (
        <span ref='hoverElement'
            onMouseEnter={this.handleMouseEnter}
            onMouseLeave={this.handleMouseLeave}
        >
            <button disabled={this.props.disabled}>Submit</button>
        </span>
    );
}

这是一个小提琴https://jsfiddle.net/qfLzkz5x/8/

答案 4 :(得分:7)

您可以使用onMouseOver={this.onToggleOpen}onMouseOut={this.onToggleOpen}在组件上反复浏览

答案 5 :(得分:5)

名为styled-components的软件包可以 ELEGANT 方式解决此问题。

<强>参考

  1. Glen Maddern - Styling React Apps with Styled Components
  2. 示例

    const styled = styled.default
    const Square = styled.div`
      height: 120px;
      width: 200px;
      margin: 100px;
      background-color: green;
      cursor: pointer;
      position: relative;
      &:hover {
        background-color: red;
      };
    `
    class Application extends React.Component {
      render() {
        return (
          <Square>
          </Square>
        )
      }
    }
    
    /*
     * Render the above component into the div#app
     */
    ReactDOM.render(<Application />, document.getElementById('app'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
    <script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
    <div id='app'></div>

答案 6 :(得分:5)

  

注意:此答案适用于此问题的先前版本,其中提问者尝试使用JavaScript来应用css样式...这可以简单地使用CSS完成。

一个简单的css - 唯一的解决方案。

对于应用基本样式,CSS在99%的时间内比JS解决方案更简单,更高效。 (虽然更现代的CSS-in-JS解决方案 - 例如React Components等 - 可以说更易于维护。)

运行此代码段以查看其实际操作...

&#13;
&#13;
.hover-button .hover-button--on,
.hover-button:hover .hover-button--off {
  display: none;
}

.hover-button:hover .hover-button--on {
  display: inline;
}
&#13;
<button class='hover-button'>
  <span class='hover-button--off'>Default</span>
  <span class='hover-button--on'>Hover!</span>
</button>
&#13;
&#13;
&#13;

答案 7 :(得分:2)

您无法单独使用内联样式。不建议在JavaScript中重新实现CSS功能,我们已经拥有一种非常强大的语言,并且非常快速地构建了这个用例 - CSS。所以用吧!让Style It协助。

npm install style-it --save

功能语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }

    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

JSX语法JSFIDDLE

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}

      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    </Style>
  }
}

export default Intro;

答案 8 :(得分:1)

我会使用onMouseOver和onMouseOut。 React中的原因

onMouseEnter和onMouseLeave事件从剩下的元素传播到要输入的元素,而不是普通的冒泡事件,并且没有捕获阶段。

这是在React documentation中的鼠标事件。

答案 9 :(得分:0)

使用Radium

以下是他们网站上的一个例子:

&#13;
&#13;
var Radium = require('radium');
var React = require('react');
var color = require('color');

@Radium
class Button extends React.Component {
  static propTypes = {
    kind: React.PropTypes.oneOf(['primary', 'warning']).isRequired
  };

  render() {
    // Radium extends the style attribute to accept an array. It will merge
    // the styles in order. We use this feature here to apply the primary
    // or warning styles depending on the value of the `kind` prop. Since its
    // all just JavaScript, you can use whatever logic you want to decide which
    // styles are applied (props, state, context, etc).
    return (
      <button
        style={[
          styles.base,
          styles[this.props.kind]
        ]}>
        {this.props.children}
      </button>
    );
  }
}

// You can create your style objects dynamically or share them for
// every instance of the component.
var styles = {
  base: {
    color: '#fff',

    // Adding interactive state couldn't be easier! Add a special key to your
    // style object (:hover, :focus, :active, or @media) with the additional rules.
    ':hover': {
      background: color('#0074d9').lighten(0.2).hexString()
    }
  },

  primary: {
    background: '#0074D9'
  },

  warning: {
    background: '#FF4136'
  }
};
&#13;
&#13;
&#13;

答案 10 :(得分:0)

调用onMouseEnter时遇到了类似的问题,但有时相应的onMouseLeave事件没有被触发,这是一个适用于我的解决方法(它部分依赖于jQuery):

var Hover = React.createClass({
    getInitialState: function() {
        return {
            hover: false
        };
    },
    onMouseEnterHandler: function(e) {
        this.setState({
            hover: true
        });
        console.log('enter');

        $(e.currentTarget).one("mouseleave", function (e) {
            this.onMouseLeaveHandler();
        }.bind(this));

    },
    onMouseLeaveHandler: function() {
        this.setState({
            hover: false
        });
        console.log('leave');
    },
    render: function() {
        var inner = normal;
        if(this.state.hover) {
            inner = hover;
        }

        return (
            <div style={outer}>
                <div style={inner}
                    onMouseEnter={this.onMouseEnterHandler} >
                    {this.props.children}
                </div>
            </div>
        );
    }
});

请参阅jsfiddle:http://jsfiddle.net/qtbr5cg6/1/

为什么会这样(在我的情况下):我在点击项目时运行jQuery滚动动画(通过$('#item').animate({ scrollTop: 0 }))。因此光标不会自然地离开项目#34;但是在JavaScript驱动的动画期间...并且在这种情况下,React没有正确地触发onMouseLeave(React 15.3.0,Chrome 51,桌面)

答案 11 :(得分:0)

我知道自从提出这个问题以来已经有一段时间但是我遇到了与onMouseLeave()不一致的问题 我所做的是使用onMouseOut()作为整个菜单的下拉列表和鼠标离开,它是可靠的,每次我测试它时都可以工作。 我在文档中看到了这些事件:https://facebook.github.io/react/docs/events.html#mouse-events 以下是使用https://www.w3schools.com/bootstrap/bootstrap_dropdowns.asp的示例:

handleHoverOff(event){
  //do what ever, for example I use it to collapse the dropdown
  let collapsing = true;
  this.setState({dropDownCollapsed : collapsing });
}

render{
  return(
    <div class="dropdown" onMouseLeave={this.handleHoverOff.bind(this)}>
      <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
      <span class="caret"></span></button>
      <ul class="dropdown-menu" onMouseOut={this.handleHoverOff.bind(this)}>
        <li><a href="#">bla bla 1</a></li>
        <li><a href="#">bla bla 2</a></li>
        <li><a href="#">bla bla 3</a></li>
      </ul>
    </div>
  )
}

答案 12 :(得分:0)

悬停是一个 CSS 功能;它带有应用程序的 CSS 端,因此以正确的方式进行操作非常有趣。简单地说,当我需要在 React 应用程序中的元素上添加悬停效果时,首先,我在 CSS 文件中创建一个类,然后将创建的类添加到元素的 className 中。我遵循的步骤是:

  1. 创建一个 CSS 文件,除非您有 index.css

  2. 创建一个启用 hover 伪类的类

    .hover__effect:hover {}

  3. 添加您需要的效果

    .hover__effect:hover { 背景颜色:rgb(255, 255, 255); 颜色:rgb(0, 0, 0); }

  4. 然后将 hover__effect 添加到类的组件中,当鼠标指针悬停在它上面时该组件应该不同

    悬停

请查看我的 sandbox 以获取现场演示。

答案 13 :(得分:-1)

我个人在React中使用 Style It 作为内联样式,或者将我的样式分别保存在 CSS SASS 文件中...... < / p>

但是如果你真的有兴趣在线实现,请查看库,我分享下面的一些用法:

在组件中

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
        {`
          .intro {
            font-size: 40px;
          }
        `}

        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}

export default Intro;

<强>输出

    <p class="intro _scoped-1">
      <style type="text/css">
        ._scoped-1.intro {
          font-size: 40px;
        }
      </style>

      CSS-in-JS made simple -- just Style It.
    </p>


    您也可以将JavaScript变量悬停在CSS中,如下所示:

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    const fontSize = 13;

    return Style.it(`
      .intro {
        font-size: ${ fontSize }px;  // ES2015 & ES6 Template Literal string interpolation
      }
      .package {
        color: blue;
      }
      .package:hover {
        color: aqua;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

结果如下:

<p class="intro _scoped-1">
  <style type="text/css">
    ._scoped-1.intro {
      font-size: 13px;
    }
    ._scoped-1 .package {
      color: blue;
    }
    ._scoped-1 .package:hover {
      color: aqua;
    }
  </style>

  CSS-in-JS made simple -- just Style It.
</p>

答案 14 :(得分:-1)

我可以为您推荐一个易于理解的示例,我在React JS中使用情感来给出样式。 在这里您可以找到有关它的更多信息https://emotion.sh/docs/introduction,希望对您有所帮助。

const secondStyle = css`
  background: blue;
  height: 20px;
  width: 20px;
  :hover {
    cursor: pointer;
    background: red;
`

function myComponent() {
  return (
     <div className={firstStyle}>
       <button className={secondStyle}>Submit<button>
  )
}