Làm thế nào để bạn Di chuột trong ReactJS? - onMouse Để lại không được đăng ký khi di chuột qua nhanh


101

Làm cách nào bạn có thể đạt được sự kiện di chuột hoặc sự kiện đang hoạt động trong ReactJS khi bạn tạo kiểu nội tuyến?

Tôi nhận thấy rằng phương pháp onMouseEnter, onMouseLeave còn nhiều lỗi, vì vậy hy vọng có một cách khác để thực hiện.

Cụ thể, nếu bạn di chuột qua một thành phần rất nhanh, chỉ sự kiện onMouseEnter được đăng ký. OnMouseLeave không bao giờ kích hoạt, và do đó không thể cập nhật trạng thái ... để lại thành phần xuất hiện như thể nó vẫn đang được di chuột qua. Tôi đã nhận thấy điều tương tự nếu bạn thử và bắt chước lớp giả css ": active". Nếu bạn nhấp thực sự nhanh, chỉ sự kiện onMouseDown sẽ đăng ký. Sự kiện onMouseUp sẽ bị bỏ qua ... để lại thành phần hoạt động.

Đây là JSFiddle hiển thị sự cố: https://jsfiddle.net/y9swecyu/5/

Video về JSFiddle gặp sự cố: https://vid.me/ZJEO

Mật mã:

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')
)

1
Cám ơn vì sự gợi ý. Tôi đã viết lại nó như một câu hỏi ngay bây giờ.
HelpMeStackOverflowMyOnlyHope

Vui lòng thêm một số ví dụ mã làm nổi bật vấn đề (lý tưởng là jsFiddle hoặc tương đương) vì vẫn chưa rõ vấn đề là gì. Bạn có nghĩa là gì bởi "sự kiện đã được đăng ký"?
WiredPrairie

@HelpMeStackOverflowMyOnlyHope bạn có muốn chọn câu trả lời không? stackoverflow.com/a/35619979/1579789 cảm ơn!
Elon Zito

Câu trả lời:


92

Bạn đã từng thử những thứ này chưa?

onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

SyntheticEvent

nó cũng đề cập đến những điều sau:

React chuẩn hóa các sự kiện để chúng có các thuộc tính nhất quán trên các trình duyệt khác nhau.

Các trình xử lý sự kiện bên dưới được kích hoạt bởi một sự kiện trong giai đoạn sôi sục. Để đăng ký một trình xử lý sự kiện cho giai đoạn chụp, hãy thêm Capture vào tên sự kiện; ví dụ: thay vì sử dụng onClick, bạn sẽ sử dụng onClickCapture để xử lý sự kiện nhấp chuột trong giai đoạn chụp.


4
Chỉ cần đề cập đến onMouseEnter và onMouseLeave, từ các tài liệu:The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.
P Fuster

40

Các câu trả lời trước đây là khá khó hiểu. Bạn không cần trạng thái phản ứng để giải quyết vấn đề này, cũng như bất kỳ lib bên ngoài đặc biệt nào. Nó có thể đạt được với css / sass thuần túy:

Phong cách:

.hover {
  position: relative;

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

  &:hover &__hover {
    opacity: 1;
  }

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

  &__no-hover {
    opacity: 1;
  }
}

Thành phần React

Một Hoverchức năng kết xuất thuần túy đơn giản :

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

Sử dụng

Sau đó, sử dụng nó như thế này:

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

1
Bạn có thể thích câu trả lời này: stackoverflow.com/a/50342093/101290
Beau Smith,

2
Đây là câu trả lời tốt nhất cho câu hỏi này.
Tool

20

bạn có thể sử dụng onMouseOver={this.onToggleOpen}onMouseOut={this.onToggleOpen}tiếp tục sử dụng trên thành phần


Nó hoạt động hoàn hảo cho tôi, cảm ơn rất nhiều. Nhưng, làm thế nào tôi có thể truy cập vào các chức năng khác như tôi chẳng hạn sẽ tồn tại "onMauseOverFirstTime"? Bạn lấy thông tin đó từ đâu?
SmoggeR_js

1
@MtgKhaJeskai reactjs.org/docs/events.html Nếu bạn muốn sth như onMouseOverFirstTime, chẳng hạn, bạn phải tự tạo nó, chẳng hạn như làm cho hàm chỉ kích hoạt khi 'firstMouseOver' ở trạng thái của bạn là true và đặt nó thành false khi hàm đã được gọi một lần.
cubefox

Tôi thành lập! Cảm ơn rât nhiều! : D
SmoggeR_js

Không, nó không tồn tại chức năng "onMauseOverFirstTime"; Tuy nhiên, bạn có thể sử dụng cờ để thực hiện hành động này, thêm cờ này vào các tiểu bang của bạn "tiểu bang: {isFirstTime: false}" và biến nó thành sự thật trong "onMouseOver" @MtgKhaJeskai
Behnam Eskandari

12

Nếu bạn có thể tạo một bản demo nhỏ hiển thị lỗi onMouseEnter / onMouseLeave hoặc onMouseDown / onMouseUp, thì bạn nên đăng nó lên trang các vấn đề hoặc danh sách gửi thư của ReactJS, chỉ để đặt câu hỏi và nghe các nhà phát triển nói gì về nó.

Trong trường hợp sử dụng của bạn, dường như bạn ngụ ý rằng trạng thái CSS: hover và: active sẽ là đủ cho mục đích của bạn, vì vậy tôi khuyên bạn nên sử dụng chúng. CSS là các đơn đặt hàng nhanh hơn và đáng tin cậy hơn Javascript, vì nó được triển khai trực tiếp trong trình duyệt.

Tuy nhiên, các trạng thái: hover và: hoạt động không thể được chỉ định trong các kiểu nội tuyến. Những gì bạn có thể làm là gán một ID hoặc một tên lớp cho các phần tử của bạn và viết các kiểu của bạn trong một biểu định kiểu, nếu chúng không đổi trong ứng dụng của bạn hoặc trong một <style>thẻ được tạo động .

Đây là một ví dụ về kỹ thuật thứ hai: https://jsfiddle.net/ors1vos9/


@clusterBuddy Tôi cho rằng đó là lỗi trong JsFiddle hoặc trong các thư viện, vì mã này đúng và luôn hoạt động tốt.
Tobia

11

Lưu ý: Câu trả lời này dành cho phiên bản trước của câu hỏi này trong đó người đặt câu hỏi đang cố gắng sử dụng JavaScript để áp dụng các kiểu css… điều này có thể đơn giản được thực hiện với CSS.

Một cssgiải pháp đơn giản .

Để áp dụng các kiểu cơ bản, CSS đơn giản hơn và hiệu quả hơn mà JS giải quyết 99% thời gian. (Mặc dù các giải pháp CSS-in-JS hiện đại hơn - ví dụ: Thành phần React, v.v. - được cho là dễ bảo trì hơn.)

Chạy đoạn mã này để xem nó hoạt động…

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

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


11
Điều này không trả lời câu hỏi.
tsujin

@tsujin - xem ghi chú ở trên.
Beau Smith

more performant that JS solutions 99% of the timekhông đúng. đọc các bài báo lật tẩy huyền thoại này. bạn có nguồn nào không
Claudiu Creanga

@ClaudiuCreanga - Vui lòng liên kết đến các bài báo lật tẩy huyền thoại này.
Beau Smith

1
@ClaudiuCreanga - Tôi đã làm rõ câu mà bạn phản đối, ngắn gọn hơn.
Beau Smith

9

Tôi vừa gặp phải vấn đề tương tự này khi nghe các sự kiện onMouseLeave trên một nút bị tắt. Tôi đã giải quyết vấn đề đó bằng cách lắng nghe sự kiện mouseleave gốc trên một phần tử bao bọc nút bị tắt.

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>
    );
}

Đây là một trò chơi hấp dẫn https://jsfiddle.net/qfLzkz5x/8/


Cách tiếp cận này sẽ không làm việc, bởi vì không có cách nào để có được đáng tin cậy các onMouseLeave-Event
dreampulse

Bạn đã kiểm tra fiddle? Có vẻ hoạt động tốt đối với tôi, ngoại trừ việc sự kiện bị ném hai lần khi bạn di chuột ra ngoài.
Cory Danielson

Nó sẽ hoạt động khá thường xuyên, nhưng không phải lúc nào! Xem cuộc thảo luận này: stackoverflow.com/questions/7448468/…
dreampulse

5

Một gói được gọi styled-componentscó thể giải quyết vấn đề này theo cách THẬT SỰ .

Tài liệu tham khảo

  1. Glen Maddern - Ứng dụng phản ứng tạo kiểu với các thành phần được tạo kiểu

Thí dụ

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>


2

Bạn không thể tạo kiểu nội tuyến một mình. Không khuyên bạn nên hoàn thiện lại các tính năng CSS trong JavaScript, chúng tôi đã có một ngôn ngữ cực kỳ mạnh mẽ và được xây dựng cực kỳ nhanh cho trường hợp sử dụng này - CSS. Vì vậy, hãy sử dụng nó! Tạo kiểu Nó để hỗ trợ.

npm install style-it --save

Cú pháp chức năng ( 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;

Cú pháp 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;

1

Sử dụng Radium !

Sau đây là một ví dụ từ trang web của họ:

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'
  }
};


3
Bạn đang trình bày cách áp dụng hiệu ứng CSS di chuột bằng cách sử dụng các kiểu nội tuyến chứ không phải cách chạy mã một cách đáng tin cậy khi con trỏ ở trên phần tử, đó là những gì người dùng yêu cầu.
Gunchars

không chắc tại sao câu trả lời của tôi không được chấp nhận dựa trên điều đó.
fkilaiwi 13/12/16

2
@Gunchars " Làm thế nào bạn có thể đạt được sự kiện di chuột hoặc sự kiện đang hoạt động trong ReactJS khi bạn tạo kiểu nội tuyến? ". Câu đầu tiên của câu hỏi của OP. Đó là khá nhiều chính xác những gì anh ấy yêu cầu.
trixn

1

Tôi muốn sử dụng onMouseOver và onMouseOut. Nguyên nhân trong React

Các sự kiện onMouseEnter và onMouseLeave lan truyền từ phần tử được để lại đến phần được nhập thay vì sủi bọt thông thường và không có giai đoạn nắm bắt.

Đây là tài liệu React cho các sự kiện chuột.


0

Tôi đã gặp sự cố tương tự khi onMouseEnter được gọi nhưng đôi khi sự kiện onMouseLeave tương ứng không được kích hoạt, đây là một cách giải quyết phù hợp với tôi (nó một phần dựa vào 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>
        );
    }
});

Xem trên jsfiddle: http://jsfiddle.net/qtbr5cg6/1/


Tại sao nó lại xảy ra (trong trường hợp của tôi): Tôi đang chạy hoạt ảnh cuộn jQuery (qua $('#item').animate({ scrollTop: 0 })) khi nhấp vào mục. Vì vậy, con trỏ không rời khỏi mục "tự nhiên", nhưng trong hoạt ảnh hướng JavaScript ... và trong trường hợp này, onMouseLeave không được React kích hoạt đúng cách (React 15.3.0, Chrome 51, Desktop)


0

Tôi biết Đã lâu rồi kể từ khi câu hỏi này được hỏi nhưng tôi chỉ gặp phải vấn đề tương tự về sự không nhất quán với onMouseLeave () Những gì tôi đã làm là sử dụng onMouseOut () cho danh sách thả và chuột để lại cho toàn bộ menu, đó là đáng tin cậy và hoạt động mỗi khi tôi thử nghiệm nó. Tôi đã thấy các sự kiện ở đây trong tài liệu: https://facebook.github.io/react/docs/events.html#mouse-events. Đây là ví dụ sử dụng 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>
  )
}

0

Cá nhân tôi sử dụng Style It cho kiểu nội tuyến trong React hoặc giữ kiểu riêng trong tệp CSS hoặc SASS ...

Nhưng nếu bạn thực sự muốn làm nó nội tuyến, hãy nhìn vào thư viện, tôi chia sẻ một số cách sử dụng bên dưới:

Trong thành phần :

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;

Đầu ra :

    <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>


Ngoài ra, bạn có thể sử dụng các biến JavaScript với di chuột trong CSS của mình như bên dưới:

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;

Và kết quả như sau:

<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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.