Встроенные стили CSS в React:как реализовать: hover?

мне очень нравится встроенный шаблон CSS в React и решил использовать его.

однако, вы не можете использовать :hover и подобные селекторы. Итак, каков наилучший способ реализации подсветки при наведении при использовании встроенных стилей CSS?

одно предложение от #reactjs-иметь Clickable компонент и использовать его как это:

<Clickable>
    <Link />
</Clickable>

на Clickable есть hovered состояние и передает его в качестве реквизита по ссылке. Однако Clickable (путь I реализовано это) обертывает Link на div перед onMouseEnter и onMouseLeave к нему. Это делает вещи немного сложнее, хотя (например,span завернут в div ведет себя иначе, чем span).

есть ли более простой способ?

14 ответов


Я в такой же ситуации. Очень нравится шаблон сохранения стиля в компонентах, но состояния наведения кажется последним препятствием.

то, что я сделал, это написать миксин, который вы можете добавить в свой компонент, который нуждается в состояниях наведения. Этот mixin добавит новый hovered свойство для состояния вашего компонента. Он будет установлен в true если пользователь парит над основным узлом DOM компонента и устанавливает его обратно в false если пользователи покидают элемент.

теперь в вашей функции рендеринга компонентов вы можете сделать что-то вроде:

<button style={m(
        this.styles.container,
        this.state.hovered && this.styles.hover,
      )}>{this.props.children}</button>

теперь каждый раз состояние hovered изменение состояния компонент будет повторно преобразован.

Я также создал репозиторий песочницы для этого, который я использую для тестирования некоторых из этих шаблонов. Проверьте это, если вы хотите увидеть пример моей реализации.

https://github.com/Sitebase/cssinjs/tree/feature-interaction-mixin


Я думаю, что onMouseEnter и onMouseLeave-это способы, но я не вижу необходимости в дополнительном компоненте оболочки. Вот как я это реализовал:

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={linkStyle} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

затем вы можете использовать состояние наведения (true / false) для изменения стиля ссылки.


вы можете использовать Radium-это инструмент с открытым исходным кодом для встроенных стилей с ReactJS. Он добавляет ровно селекторы нужно. Очень популярны, проверьте это -Радий на НПМ


полная поддержка CSS является именно причиной этого огромного количества библиотек CSSinJS, чтобы сделать это эффективно, вам нужно создать фактический CSS, а не встроенные стили. Также встроенные стили намного медленнее реагируют в большей системе. Отказ от ответственности-я поддерживаю стандарте JSS.


составила Стиль -- частично -- по этой причине (другие-разногласия с реализацией других библиотек / синтаксиса и встроенных стилей, отсутствие поддержки значений свойств префикса). Считаем, что мы должны иметь возможность просто писать CSS в JavaScript и иметь полностью автономные компоненты HTML-CSS-JS. С помощью строк шаблона ES5 / ES6 мы теперь можем, и это тоже может быть довольно! :)

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;

можно использовать css модули в качестве альтернативы, и дополнительно react-css-modules для сопоставления имен класса.

таким образом, вы можете импортировать свои стили следующим образом и использовать обычный css локально для ваших компонентов:

import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);

здесь пример модулей css webpack


на Джонатан!--5-->, вот события для покрытия фокуса и активных состояний, а также использование onMouseOver вместо onMouseEnter поскольку последний не будет пузыриться, если у вас есть дочерние элементы в целевой объект, к которому применяется событие.

var Link = React.createClass({

  getInitialState: function(){
    return {hover: false, active: false, focus: false}
  },

  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },

  toggleActive: function(){
    this.setState({active: !this.state.active})
  },

  toggleFocus: function(){
    this.setState({focus: !this.state.focus})
  },

  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else if (this.state.active) {
      linkStyle = {backgroundColor: 'blue'}
    } else if (this.state.focus) {
      linkStyle = {backgroundColor: 'purple'}
    } 

    return(
      <div>
        <a style={linkStyle} 
          onMouseOver={this.toggleHover} 
          onMouseOut={this.toggleHover} 
          onMouseUp={this.toggleActive} 
          onMouseDown={this.toggleActive} 
          onFocus={this.toggleFocus}> 
          Link 
        </a>
      </div>
    )
  }

оформить заказ Typestyle Если вы используете React с Typescript.

Ниже приведен пример кода для: hover

import {style} from "typestyle";

/** convert a style object to a CSS class name */
const niceColors = style({
  transition: 'color .2s',
  color: 'blue',
  $nest: {
    '&:hover': {
      color: 'red'
    }
  }
});

<h1 className={niceColors}>Hello world</h1>

в отношении стиле-компоненты и react-маршрутизатор v4 можно сделать так:

import {NavLink} from 'react-router-dom'

const Link = styled(NavLink)`     
  background: blue;

  &:hover {
    color: white;
  }
`

...
<Clickable><Link to="/somewhere">somewhere</Link></Clickable>

onMouseOver и onMouseLeave с setState сначала показались мне немного накладными расходами - но так как это работает react, это кажется мне самым простым и чистым решением.

рендеринг тематического CSS-сервера, например, также является хорошим решением и сохраняет компоненты react более чистыми.

Если вам не нужно добавлять динамические стили к элементам (например, для тематизации), вы не должны использовать встроенные стили вообще, но использовать классы css вместо.

Это традиционное правило html / css, чтобы сохранить html / JSX чистым и простым.


Я использую довольно Хак-иш-решение для этого в одном из моих последних приложений, которое работает для моих целей, и я нахожу его быстрее, чем писать пользовательские функции настройки наведения в vanilla js (хотя, я признаю, возможно, не лучшая практика в большинстве сред.. Итак, если вы все еще заинтересованы, вот.

Я создаю родительский элемент только для удержания встроенных стилей javascript, а затем дочерний элемент с именем класса или идентификатором, на который будет защелкиваться моя таблица стилей css и напишите стиль наведения в моем выделенном файле css. Это работает, потому что более детализированный дочерний элемент получает встроенные стили js через наследование, но имеет свои стили наведения, переопределенные файлом css.

таким образом, в основном, мой фактический файл css существует с единственной целью удержания эффектов наведения, ничего больше. Это делает его довольно сжатым и простым в управлении и позволяет мне выполнять тяжелую работу в моих стилях компонентов In-line React.

вот пример:

const styles = {
  container: {
    height: '3em',
    backgroundColor: 'white',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    borderBottom: '1px solid gainsboro',
  },
  parent: {
    display: 'flex',
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    color: 'darkgrey',
  },
  child: {
    width: '6em',
    textAlign: 'center',
    verticalAlign: 'middle',
    lineHeight: '3em',
  },
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div style={styles.container}>
      <div style={styles.parent}>
        {menuOptions.map((page) => <div className={'navBarOption'} style={styles.child} key={page}>{page}</div> )}
      </div>
    </div>
  );
};


ReactDOM.render(
  <NavBar/>,
  document.getElementById('app')
);
.navBarOption:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

обратите внимание, что" дочерний "встроенный стиль не имеет набора свойств" цвет". Если бы это было так, это не сработало бы, потому что встроенный стиль будет иметь приоритет над моей таблицей стилей.


Это может быть хороший хак для встроенного стиля внутри компонента react (а также с помощью функции CSS: hover):

... <style> {`.galleryThumbnail.selected:hover{outline:2px solid #00c6af}`} </style> ...


самый простой способ-использовать тернарный оператор

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={this.state.hover ? {"backgroundColor": 'red'}: {"backgroundColor": 'blue'}} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }

самым простым способом было бы просто добавить тег абзаца в ссылку и проанализировать стиль p. <Link to='/'><p style={{ color: '#000000' }}>Some text</p></Link>