ReactJS'de Nasıl Gezinirsiniz? - hızlı üzerine gelme sırasında onMouseLeave kayıtlı değil


104

Satır içi şekillendirme yaparken ReactJS'de bir hover olayı veya aktif olayı nasıl elde edebilirsiniz?

OnMouseEnter, onMouseLeave yaklaşımının hatalı olduğunu buldum, bu yüzden bunu yapmanın başka bir yolu olduğunu umuyorum.

Özellikle, fareyi bir bileşenin üzerine çok hızlı bir şekilde getirirseniz, yalnızca onMouseEnter olayı kaydedilir. OnMouseLeave hiçbir zaman ateşlemez ve bu nedenle durumu güncelleyemez ... bileşeni, sanki hala üzerindeymiş gibi görünmesi için bırakır. ": Active" css sözde sınıfını denerseniz ve taklit ederseniz, aynı şeyi fark ettim. Gerçekten hızlı tıklarsanız, yalnızca onMouseDown etkinliği kaydedilecektir. OnMouseUp olayı yok sayılacaktır ... bileşen etkin görünecek şekilde bırakılacaktır.

İşte sorunu gösteren bir JSFiddle: https://jsfiddle.net/y9swecyu/5/

JSFiddle'ın sorunlu videosu: https://vid.me/ZJEO

Kod:

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
Önerin için teşekkürler. Şimdi soru olarak yeniden yazdım.
HelpMeStackOverflowMyOnlyHope

Sorunun ne olduğu hala net olmadığı için lütfen sorunu vurgulayan bazı kod örnekleri ekleyin (ideal olarak jsFiddle veya eşdeğeri olarak). "Etkinlik kayıtlıdır" derken neyi kastediyorsunuz?
WiredPrairie

@HelpMeStackOverflowMyOnlyHope bir cevap seçmek istediniz mi? stackoverflow.com/a/35619979/1579789 teşekkürler!
Elon Zito

Yanıtlar:


93

Bunlardan herhangi birini denedin mi?

onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

SyntheticEvent

ayrıca şunlardan da bahseder:

React, olayları farklı tarayıcılarda tutarlı özelliklere sahip olacak şekilde normalleştirir.

Aşağıdaki olay işleyicileri köpürme aşamasındaki bir olay tarafından tetiklenir. Yakalama aşaması için bir olay işleyicisi kaydetmek için, olay adına Yakalama ekleyin; örneğin, onClick kullanmak yerine, yakalama aşamasında tıklama olayını işlemek için onClickCapture kullanırsınız.


4
Dokümanlardan onMouseEnter ve onMouseLeave'den bahsetmek gerekirse: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

Önceki cevaplar oldukça kafa karıştırıcı. Bunu çözmek için bir react-state'e veya herhangi bir özel harici kütüphaneye ihtiyacınız yok. Saf css / sass ile elde edilebilir:

Stil:

.hover {
  position: relative;

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

  &:hover &__hover {
    opacity: 1;
  }

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

  &__no-hover {
    opacity: 1;
  }
}

React Bileşeni

Basit bir HoverPure-Rendering-İşlevi:

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

Kullanım

O zaman şu şekilde kullanın:

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

1
Bu yanıtı beğenebilirsiniz: stackoverflow.com/a/50342093/101290
Beau Smith

2
Bu sorunun en iyi cevabı budur.
Araç

20

Bileşen üzerinde derin düşünmek için kullanabilir onMouseOver={this.onToggleOpen}ve onMouseOut={this.onToggleOpen}


Benim için mükemmel çalıştı, çok teşekkürler. Ancak, benim gibi diğer işlevlere, örneğin "onMauseOverFirstTime" var olacağına nasıl erişebilirim? Bu bilgiyi nereden aldın?
SmoggeR_js

1
@MtgKhaJeskai reactjs.org/docs/events.html OnMouseOverFirstTime gibi bir şey istiyorsanız, örneğin, işlevi yalnızca eyaletinizdeki 'firstMouseOver' doğru olduğunda ateşleyin ve yanlış olarak ayarlayın. işlevi bir kez çağrıldı.
cubefox

Ben kurdum! Çok teşekkür ederim! : D
SmoggeR_js

Hayır, "onMauseOverFirstTime" işlevi mevcut değil; Ancak bu eylemi yapmak için bir bayrak kullanabilirsiniz, bunu eyaletinizin "durumlarına ekleyin: {isFirstTime: false}" ve "onMouseOver" @MtgKhaJeskai
Behnam Eskandari

12

OnMouseEnter / onMouseLeave veya onMouseDown / onMouseUp hatasını gösteren küçük bir demo oluşturabilirseniz, soruyu sormak ve geliştiricilerin bu konuda söyleyeceklerini duymak için bunu ReactJS'nin sorunlar sayfasına veya posta listesine göndermeniz faydalı olacaktır.

Kullanım durumunuzda, CSS: hover ve: active durumlarının amaçlarınız için yeterli olacağını ima ediyorsunuz, bu yüzden onları kullanmanızı öneririm. CSS, doğrudan tarayıcıda uygulandığı için Javascript'ten daha hızlı ve daha güvenilirdir.

Ancak: hover ve: active durumları satır içi stillerde belirtilemez. Yapabilecekleriniz, öğelerinize bir kimlik veya sınıf adı atamak ve stillerinizi ya uygulamanızda bir şekilde sabitse bir stil sayfasında ya da dinamik olarak oluşturulmuş bir <style>etikette yazmaktır .

İkinci tekniğin bir örneği: https://jsfiddle.net/ors1vos9/


@clusterBuddy Bunun JsFiddle'da veya kitaplıklarda bir hata olduğunu düşünüyorum, çünkü kod doğrudur ve her zaman iyi çalıştı.
Tobia

11

Not: Bu yanıt, soruyu soran kişinin css stillerini uygulamak için JavaScript kullanmaya çalıştığı bu sorunun önceki bir sürümü içindi… ki bu sadece CSS ile yapılabilir.

Basit bir cssçözüm.

Temel stilleri uygulamak için CSS, JS çözümlerinin% 99'una göre daha basit ve daha yüksek performanslı. (Daha modern CSS-in-JS çözümleri - ör. React Bileşenleri, vb. - muhtemelen daha fazla bakım yapılabilir.)

Eylem halinde görmek için bu kod parçacığını çalıştırın…

.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
Bu soruya cevap vermiyor.
tsujin

@tsujin - yukarıdaki nota bakın.
Beau Smith

more performant that JS solutions 99% of the timedoğru değil. bu efsaneyi çürüten makaleler okuyun. kaynağınız var mı
Claudiu Creanga

@ClaudiuCreanga - Lütfen bu efsaneyi çürüten makalelere bağlantı verin.
Beau Smith

1
@ClaudiuCreanga - Daha kısa olmak için itiraz ettiğiniz cümleyi açıkladım.
Beau Smith

9

Devre dışı bırakılmış bir düğmede onMouseLeave olaylarını dinlerken de aynı problemle karşılaştım. Devre dışı bırakılan düğmeyi saran bir öğe üzerindeki yerel fare etkinliğini dinleyerek bunun etrafında çalıştım.

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

İşte bir keman https://jsfiddle.net/qfLzkz5x/8/


Bu yaklaşım olmaz iş, güvenilir olsun yolu yoktur, çünkü onMouseLeave-Olay
dreampulse

Kemanı kontrol ettin mi? Benim için iyi çalışıyor gibi görünüyor, ancak fareyi dışarı çıkardığınızda olay iki kez atılıyor.
Cory Danielson

Oldukça sık çalışacak, ancak her zaman değil! Bu tartışmaya bakın: stackoverflow.com/questions/7448468/…
dreampulse

5

Adlı bir paket styled-componentsbu sorunu ŞIK bir şekilde çözebilir .

Referans

  1. Glen Maddern - React Uygulamalarına Tarz Bileşenlerle Stil Verin

Misal

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

Satır içi stil ile tek başına yapamazsınız. CSS özelliklerinin JavaScript'te yeniden uygulanmasını önermeyin, zaten bu kullanım örneği için son derece güçlü ve inanılmaz derecede hızlı oluşturulmuş bir dile sahibiz - CSS. Öyleyse kullan! Yapılmış Stil Yardımcı olmak için.

npm install style-it --save

İşlevsel Sözdizimi ( 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 Sözdizimi ( 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

Radium'u kullanın !

Aşağıdaki web sitelerinden bir örnek:

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
Satır içi stilleri kullanarak bir fareyle üzerine gelme CSS efektinin nasıl uygulanacağını ve imleç öğenin üzerindeyken kodun nasıl güvenilir bir şekilde çalıştırılacağını göstermiyorsunuz, bu da kullanıcının istediği şeydir.
Gunchars

Buna dayanarak cevabımın neden kabul edilmediğinden emin değilim.
fkilaiwi

2
@Gunchars " Satır içi şekillendirme yaptığınızda ReactJS'de bir vurgulu olayı veya aktif olayı nasıl elde edebilirsiniz? ". OP'nin sorusunun ilk cümlesi. Tam olarak istediği şey buydu.
trixn

1

OnMouseOver ve onMouseOut kullanırım. React'te Neden

OnMouseEnter ve onMouseLeave olayları, normal köpürme yerine bırakılan öğeden girilen öğeye doğru yayılır ve bir yakalama aşamasına sahip değildir.

Burada fare olayları için React belgelerinde bulunmaktadır.


0

OnMouseEnter çağrıldığında benzer bir sorun yaşadım, ancak bazen karşılık gelen onMouseLeave olayı tetiklenmedi, işte benim için iyi çalışan bir geçici çözüm (kısmen jQuery'ye dayanır):

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'a bakın: http://jsfiddle.net/qtbr5cg6/1/


Neden oluyordu (benim durumumda): $('#item').animate({ scrollTop: 0 })Öğeye tıklarken bir jQuery kaydırma animasyonu (üzerinden ) çalıştırıyorum . Yani imleç öğeyi "doğal olarak" terk etmiyor, ancak JavaScript güdümlü bir animasyon sırasında ... ve bu durumda onMouseLeave, React (React 15.3.0, Chrome 51, Masaüstü) tarafından düzgün şekilde tetiklenmedi.


0

Bu sorunun sorulmasının üzerinden epey zaman geçtiğini biliyorum ama onMouseLeave () ile aynı tutarsızlık sorunuyla karşılaştım.Yaptığım şey, açılır liste için onMouseOut () ve tüm menü için fare bırakıldığında, güvenilir ve her test ettiğimde çalışıyor. Ben docs burada olayları gördük: https://facebook.github.io/react/docs/events.html#mouse-events burada kullanarak bir örnek 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

Ben şahsen Style It kullanıyorumReact'te satır içi stil için veya stilimi bir CSS veya SASS dosyasında ayrı ayrı tutuyorum ...

Ancak bunu satır içi yapmakla gerçekten ilgileniyorsanız, kitaplığa bakın, aşağıda bazı kullanımları paylaşıyorum:

Bileşende :

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;

Çıktı :

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


Ayrıca aşağıdaki gibi CSS'nizde hover ile JavaScript değişkenlerini kullanabilirsiniz:

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;

Ve aşağıdaki gibi sonuç:

<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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.