Bagaimana cara Anda mengarahkan kursor ke ReactJS? - onMouseLeave tidak terdaftar selama fast hover over

106

Bagaimana Anda bisa mencapai event hover atau event aktif di ReactJS saat Anda melakukan gaya inline?

Saya telah menemukan bahwa pendekatan onMouseEnter, onMouseLeave bermasalah, jadi berharap ada cara lain untuk melakukannya.

Khususnya, jika Anda mengarahkan mouse ke sebuah komponen dengan sangat cepat, hanya acara onMouseEnter yang terdaftar. OnMouseLeave tidak pernah aktif, sehingga tidak dapat memperbarui status ... membiarkan komponen tampak seolah-olah masih di-arahkan. Saya telah memperhatikan hal yang sama jika Anda mencoba dan meniru pseudo-class css ": active". Jika Anda mengklik sangat cepat, hanya acara onMouseDown yang akan mendaftar. Acara onMouseUp akan diabaikan ... membiarkan komponen tampak aktif.

Berikut adalah JSFiddle yang menunjukkan masalahnya: https://jsfiddle.net/y9swecyu/5/

Video JSFiddle dengan masalah: https://vid.me/ZJEO

Kode:

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')
)
HelpMeStackOverflowMyOnlyHope
sumber
1
Terima kasih untuk sarannya. Saya menulis ulang sebagai pertanyaan sekarang.
HelpMeStackOverflowMyOnlyHope
Harap tambahkan beberapa contoh kode yang menyoroti masalah (idealnya sebagai jsFiddle atau yang setara) karena masih belum jelas apa masalahnya. Apa yang Anda maksud dengan "acara terdaftar"?
WiredPrairie
@HelpMeStackOverflowMyOnlyHope apakah Anda ingin memilih jawaban? stackoverflow.com/a/35619979/1579789 terima kasih!
Elon Zito

Jawaban:

95

Sudahkah Anda mencoba semua ini?

onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

SyntheticEvent

itu juga menyebutkan yang berikut:

React menormalkan peristiwa sehingga mereka memiliki properti yang konsisten di berbagai browser.

Penangan peristiwa di bawah ini dipicu oleh peristiwa dalam fase menggelegak. Untuk mendaftarkan event handler untuk fase capture, tambahkan Capture ke nama event; misalnya, alih-alih menggunakan onClick, Anda akan menggunakan onClickCapture untuk menangani peristiwa klik dalam fase penangkapan.

Elon Zito
sumber
5
Hanya untuk menyebutkan onMouseEnter dan onMouseLeave, dari dokumen: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
41

Jawaban sebelumnya cukup membingungkan. Anda tidak perlu status reaksi untuk menyelesaikan ini, atau lib eksternal khusus apa pun. Itu dapat dicapai dengan css / sass murni:

Gaya:

.hover {
  position: relative;

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

  &:hover &__hover {
    opacity: 1;
  }

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

  &__no-hover {
    opacity: 1;
  }
}

Komponen React

Fungsi HoverPure-Rendering sederhana :

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

Pemakaian

Kemudian gunakan seperti ini:

    <Hover onHover={<div> Show this on hover </div>}>
        <div> Show on no hover </div>
    </Hover>
dreampulse
sumber
1
Anda mungkin menyukai jawaban ini: stackoverflow.com/a/50342093/101290
Beau Smith
2
Ini adalah jawaban terbaik untuk pertanyaan ini.
Alat
20

Anda dapat menggunakan onMouseOver={this.onToggleOpen}dan onMouseOut={this.onToggleOpen}merenungkan komponen

Behnam Eskandari
sumber
Ini bekerja dengan sempurna untuk saya, terima kasih banyak. Tapi, bagaimana saya bisa mengakses fungsi lain seperti saya misalnya akan ada "onMauseOverFirstTime"? Darimana Anda mendapatkan informasi itu?
SmoggeR_js
1
@MtgKhaJeskai reactjs.org/docs/events.html Jika Anda ingin sth seperti onMouseOverFirstTime Anda harus membuatnya sendiri, misalnya, membuat fungsi hanya aktif ketika 'firstMouseOver' di negara Anda adalah benar dan setel ke salah ketika fungsi dipanggil sekali.
cubefox
Saya didirikan! Terima kasih banyak! : D
SmoggeR_js
Tidak, itu tidak ada fungsi "onMauseOverFirstTime"; Tetapi Anda dapat menggunakan bendera untuk melakukan tindakan ini, tambahkan ini ke status Anda "menyatakan: {isFirstTime: false}" dan membuatnya benar di "onMouseOver" @MtgKhaJeskai
Behnam Eskandari
12

Jika Anda dapat membuat demo kecil yang menampilkan bug onMouseEnter / onMouseLeave atau onMouseDown / onMouseUp, akan bermanfaat untuk mempostingnya ke halaman masalah atau milis ReactJS, hanya untuk mengajukan pertanyaan dan mendengar apa yang dikatakan pengembang tentangnya.

Dalam kasus penggunaan Anda, Anda sepertinya menyiratkan bahwa status CSS: hover dan: aktif sudah cukup untuk tujuan Anda, jadi saya sarankan Anda menggunakannya. CSS lebih cepat dan lebih dapat diandalkan daripada Javascript, karena itu langsung diterapkan di browser.

Namun,: status hover dan: aktif tidak dapat ditentukan dalam gaya sebaris. Yang dapat Anda lakukan adalah menetapkan ID atau nama kelas ke elemen Anda dan menulis gaya Anda baik dalam stylesheet, jika gaya tersebut agak konstan dalam aplikasi Anda, atau dalam <style>tag yang dibuat secara dinamis .

Berikut adalah contoh teknik terakhir: https://jsfiddle.net/ors1vos9/

Tobia
sumber
@clusterBuddy Saya kira itu bug di JsFiddle atau di perpustakaan, karena kodenya benar dan selalu berfungsi dengan baik.
Tobia
11

Catatan: Jawaban ini untuk versi sebelumnya dari pertanyaan ini di mana penanya pertanyaan mencoba menggunakan JavaScript untuk menerapkan gaya css… yang dapat dilakukan dengan CSS.

cssSolusi -hanya sederhana .

Untuk menerapkan gaya dasar, CSS lebih sederhana dan lebih berkinerja daripada solusi JS 99% dari waktu. (Meskipun solusi CSS-in-JS yang lebih modern - mis. Komponen React, dll - bisa dibilang lebih mudah dipelihara.)

Jalankan cuplikan kode ini untuk melihatnya beraksi ...

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

Beau Smith
sumber
11
Ini tidak menjawab pertanyaan itu.
tsujin
@tsujin - lihat catatan di atas.
Beau Smith
more performant that JS solutions 99% of the timetidak benar. membaca artikel yang membongkar mitos ini. apakah kamu punya sumber?
Claudiu Creanga
@ClaudiuCreanga - Harap tautkan ke artikel yang menyanggah mitos ini.
Beau Smith
1
@ClaudiuCreanga - Saya telah mengklarifikasi kalimat yang Anda keberatan, agar lebih ringkas.
Beau Smith
9

Saya baru saja mengalami masalah yang sama saat mendengarkan acara onMouseLeave dengan tombol nonaktif. Saya mengatasinya dengan mendengarkan acara mouseleave asli pada elemen yang membungkus tombol yang dinonaktifkan.

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

Ini biola https://jsfiddle.net/qfLzkz5x/8/

Cory Danielson
sumber
Pendekatan ini tidak akan berhasil, karena tidak ada cara untuk mendapatkan onMouseLeave-Event
dreampulse
Apakah Anda memeriksa biolanya? Tampaknya berfungsi dengan baik bagi saya, kecuali bahwa acara tersebut dilemparkan dua kali saat Anda mengarahkan mouse keluar.
Cory Danielson
Ini akan bekerja cukup sering, tetapi tidak selalu! Lihat diskusi ini: stackoverflow.com/questions/7448468/…
dreampulse
5

Sebuah paket bernama styled-componentsdapat memecahkan masalah ini dengan cara ELEGAN .

Referensi

  1. Glen Maddern - Menata Aplikasi React dengan Komponen Bergaya

Contoh

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>

Karl Xu
sumber
2

Anda tidak bisa hanya dengan gaya sebaris. Jangan rekomendasikan untuk mengimplementasikan kembali fitur CSS di JavaScript. Kami sudah memiliki bahasa yang sangat kuat dan dibuat sangat cepat untuk kasus penggunaan ini - CSS. Jadi gunakan itu! Membuat Style It untuk membantu.

npm install style-it --save

Sintaks Fungsional ( 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;

Sintaks 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;
Joshua Robinson
sumber
1

Gunakan Radium !

Berikut ini adalah contoh dari situs web mereka:

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

fkilaiwi.dll
sumber
3
Anda menunjukkan cara menerapkan efek CSS hover menggunakan gaya sebaris dan bukan cara menjalankan kode dengan andal saat kursor berada di atas elemen, yang diminta oleh pengguna.
Gunchars
tidak yakin mengapa jawaban saya tidak diterima berdasarkan itu.
fkilaiwi
2
@ Gunchars " Bagaimana Anda bisa mencapai event hover atau event aktif di ReactJS saat Anda melakukan inline styling? ". Kalimat pertama pertanyaan OP. Ini persis seperti yang dia minta.
trixn
1

Saya akan menggunakan onMouseOver & onMouseOut. Penyebab di React

Peristiwa onMouseEnter dan onMouseLeave menyebar dari elemen yang dibiarkan ke elemen yang dimasukkan, bukan menggelembung biasa dan tidak memiliki fase penangkapan.

Ini dia di React dokumentasi untuk event mouse.

hlkughl
sumber
0

Saya memiliki masalah serupa ketika onMouseEnter dipanggil tetapi terkadang acara onMouseLeave yang sesuai tidak diaktifkan, berikut adalah solusi yang berfungsi dengan baik untuk saya (sebagian bergantung pada 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>
        );
    }
});

Lihat di jsfiddle: http://jsfiddle.net/qtbr5cg6/1/


Mengapa itu terjadi (dalam kasus saya): Saya menjalankan animasi gulir jQuery (melalui $('#item').animate({ scrollTop: 0 })) saat mengklik item. Jadi kursor tidak meninggalkan item "secara alami", tetapi selama animasi berbasis JavaScript ... dan dalam hal ini onMouseLeave tidak diaktifkan dengan benar oleh React (React 15.3.0, Chrome 51, Desktop)

kunnix
sumber
0

Saya tahu Sudah lama sejak pertanyaan ini diajukan tetapi saya baru saja mengalami masalah ketidakkonsistenan yang sama dengan onMouseLeave () Apa yang saya lakukan adalah menggunakan onMouseOut () untuk daftar drop-list dan cuti mouse untuk seluruh menu, itu dapat diandalkan dan berfungsi setiap kali saya mengujinya. Saya melihat kejadian di sini di dokumen: https://facebook.github.io/react/docs/events.html#mouse-events di sini adalah contoh menggunakan 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>
  )
}
RamiroIsBack
sumber
0

Saya pribadi menggunakan Style It untuk gaya sebaris di React atau menyimpan gaya saya secara terpisah di CSS atau SASS ...

Tetapi jika Anda benar-benar tertarik melakukannya secara inline, lihat di perpustakaan, saya membagikan beberapa kegunaan di bawah ini:

Dalam komponen :

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;

Keluaran :

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


Anda juga dapat menggunakan variabel JavaScript dengan hover di CSS Anda seperti di bawah ini:

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;

Dan hasilnya seperti dibawah ini:

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