Как вы зависаете в ReactJS? - onMouseLeave не зарегистрирован во время быстрого зависания
Как вы можете достичь или всплывающего события, или активного события в ReactJS, когда вы выполняете встроенное моделирование?
Я обнаружил, что подход onMouseEnter, onMouseLeave глючит, поэтому надеюсь, что есть другой способ сделать это.
В частности, если вы наведите курсор мыши на компонент очень быстро, регистрируется только событие onMouseEnter. OnMouseLeave никогда не срабатывает и, следовательно, не может обновлять состояние... оставляя компонент таким, как будто он все еще находится над ним. Я заметил то же самое, если вы попытаетесь имитировать псевдокласс ":active". Если вы нажмете очень быстро, будет зарегистрировано только событие 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 ответов
Вы пробовали что-нибудь из этого?
onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp
https://facebook.github.io/react/docs/events.html
также упоминается следующее:
React нормализует события, чтобы они имели согласованные свойства в разных браузерах.
Приведенные ниже обработчики событий запускаются событием в фазе пузырьков. Чтобы зарегистрировать обработчик события для фазы захвата, добавьте Capture к имени события; например, вместо использования onClick вы должны использовать onClickCapture для обработки события click на этапе захвата.
Предыдущие ответы довольно запутанные. Вам не нужно реагирующее состояние для решения этой проблемы, ни какая-либо специальная внешняя библиотека. Это может быть достигнуто с чистым 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;
}
}
Реакт-Компонент
Просто 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>
Ты можешь использовать onMouseOver={this.onToggleOpen}
а также onMouseOut={this.onToggleOpen}
размышлять над компонентом
Примечание. Этот ответ был для предыдущей версии этого вопроса, где задающий вопрос пытался использовать JavaScript для применения стилей... что должно быть сделано с помощью CSS.
Просто css
Единственное решение.
Решения CSS проще и производительнее, чем решения JS в 99% случаев.
Запустите этот фрагмент кода, чтобы увидеть его в действии…
.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>
Если вы можете создать небольшую демонстрацию, показывающую ошибку onMouseEnter / onMouseLeave или onMouseDown / onMouseUp, было бы целесообразно опубликовать ее на странице проблем ReactJS или в списке рассылки, просто чтобы поднять вопрос и услышать, что разработчики говорят об этом.
В вашем случае использования вы, кажется, подразумеваете, что CSS:hover и:active состояний будет достаточно для ваших целей, поэтому я предлагаю вам использовать их. CSS на несколько порядков быстрее и надежнее, чем Javascript, потому что он напрямую реализован в браузере.
Однако состояния: hover и:active нельзя указывать во встроенных стилях. Что вы можете сделать, это назначить ID или имя класса вашим элементам и записать ваши стили либо в таблице стилей, если они несколько постоянны в вашем приложении, либо в динамически генерируемом <style>
тег.
Вот пример последнего метода: https://jsfiddle.net/ors1vos9/
Я только что столкнулся с этой же проблемой при прослушивании событий 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/
Я бы использовал onMouseOver и onMouseOut. Причина в React
События onMouseEnter и onMouseLeave распространяются от оставленного элемента к элементу, который вводится, вместо обычного всплывания и не имеют фазы захвата.
Вот это в документации React для событий мыши.
Пакет называется styled-components
может решить эту проблему изящным способом.
Ссылка
пример
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>
Вы не можете с одним только встроенным моделированием. Не рекомендуем переопределять функции CSS в JavaScript, у нас уже есть очень мощный и невероятно быстрый язык для этого варианта использования - CSS. Так что используйте это! Made Style Это, чтобы помочь.
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;
Используйте Радий!
Ниже приведен пример с их сайта:
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'
}
};
У меня была похожая проблема, когда вызывался 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 })
) при нажатии на элемент. Таким образом, курсор не покидает элемент "естественно", но во время анимации, управляемой JavaScript... и в этом случае onMouseLeave не был запущен должным образом React (React 15.3.0, Chrome 51, Desktop)
Я лично использую Style It для встроенного стиля в React или храню свой стиль отдельно в файле CSS или SASS...
Но если вы действительно заинтересованы в том, чтобы сделать это встроенным, посмотрите библиотеку, я поделюсь некоторыми примерами использования ниже:
В компоненте:
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 с hover в вашем 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>
Я знаю, что прошло много времени с тех пор, как был задан этот вопрос, но я просто столкнулся с той же проблемой несоответствия с onMouseLeave(). Что я сделал, так это использовал onMouseOut() для выпадающего списка и при отпускании мыши для всего меню, это надежный и работает каждый раз, когда я проверял это. Я видел события здесь в документах: https://facebook.github.io/react/docs/events.html. Вот пример использования 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>
)
}
Наведение - это особенность; он поставляется со стороны приложения, так что делать это правильно - это так весело. Проще говоря, когда мне нужен эффект наведения курсора на элемент в приложении React, сначала я создаю класс в своем файле, а затем добавляю созданный класс в className элемента. Я выполняю следующие шаги:
Создать
CSS
файл, если у вас нетindex.css
Создайте класс с
hover
псевдокласс включен.hover__effect:hover {}
Добавьте нужные эффекты
.hover__effect:hover {цвет фона: rgb(255, 255, 255); цвет: rgb(0, 0, 0); }
Затем добавьте
hover__effect
к компоненту класса, который должен отличаться при наведении указателя мыши на негоПарение
Пожалуйста, проверьте мою чтобы песочницу,увидеть живую демонстрацию.
Я мог бы предложить вам пример, который мне было легко понять, я использую эмоции в 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>
)
}