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

105

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

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

Одно предложение от #reactjs состоит в том, чтобы иметь компонент Clickable и использовать его следующим образом:

<Clickable>
    <Link />
</Clickable>

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

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

  • 1
    Вы абсолютно правы - единственный способ имитировать: селекторы hover и т.д. со встроенными стилями - это использовать onMouseEnter и onMouseLeave . Что касается точной реализации этого - это полностью зависит от вас. Чтобы взглянуть на конкретный пример, почему бы не сделать оболочку <Clickable/> span ?
  • 3
    Я бы предложил использовать внешние таблицы стилей вместе с плагином ExtractText Webpack, это поможет вам в более длительной работе, если вы когда-либо захотите ServerRender, в противном случае вы можете попробовать Radium github.com/FormidableLabs/radium
Показать ещё 1 комментарий
Теги:

15 ответов

28
Лучший ответ

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

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

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

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

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

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

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

  • 2
    не лучшее решение для более долгой работы, лучше будет использовать Radium или использовать внешнюю таблицу стилей
  • 11
    @ abhirathore2006 Radium работает точно так же, и вопрос в том, как это сделать без использования внешней таблицы стилей.
72

Я думаю, что 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), чтобы изменить стиль ссылки.

  • 1
    Казалось бы, это охватывает :hover но не :focus
  • 3
    Реакция @AdamTuttle имеет событие onFocus ; так что вы можете сделать то же самое для :focus как :hover , за исключением того, что вместо onMouseEnter и onMouseLeave вам понадобится только onFocus
Показать ещё 1 комментарий
22

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

  • 0
    Я только что наткнулся на этот пост, как бы вы внедрили Radium в следующей ситуации? module.exports = React.createClass({ displayName: 'App',})
  • 1
    @Rkhayat Вы можете либо обернуть его как module.exports = Radium(React.createClass({ displayName: 'App',})) либо присвоить классу значение и добавить декоратор @Radium над ним, поскольку в документах упоминается github.com. / FormidableLabs / радий # использование
Показать ещё 1 комментарий
6

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

6

Made Style It - частично - по этой причине (из-за несогласия с реализацией других библиотек/синтаксиса и встроенных стилей отсутствует поддержка префикса значений свойств). Поверьте, мы должны иметь возможность просто писать 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;
  • 0
    Я заметил, что в примере с синтаксисом JSX ссылка JSFiddle имеет правильный код, но в показанном здесь примере отсутствует закрывающая скобка после закрывающего тега Style, а отступы, вероятно, отключены из-за отсутствующей скобки.
3

Что касается styled-components и response-router v4 вы можете сделать это:

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

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

  &:hover {
    color: white;
  }
`

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

Добавляя к ответ Джонатана, здесь перечислены события для охвата фокуса и активных состояний и использование 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>
    )
  }
3

Вы можете использовать css modules в качестве альтернативы, а также 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

  • 0
    К вашему сведению: если вы используете Meteor, проверьте этот пакет: github.com/nathantreid/meteor-css-modules . Я сам пользуюсь им с большим успехом.
  • 0
    Это отличный способ стилизовать реагирующие компоненты, но не совсем дает вам полный контроль над встроенными стилями. Например, вы не можете изменить :hover стили при :hover во время выполнения, как вы можете с помощью Radium или другого решения на основе onMouseOver
2

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

рендеринг тематических css серверов, например, также является хорошим решением и обеспечивает более чистую реакцию компонентов.

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

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

2

Оформить покупку 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>
0

Поздно на вечеринку, но прийти с решением. Вы можете использовать "&", чтобы определить стили для hover nth Child и т. Д.:

 day: {
    display: "flex",
    flex: "1",
    justifyContent: "center",
    alignItems: "center",
    width: "50px",
    height: "50px",
    transition: "all 0.2s",
    borderLeft: "solid 1px #cccccc",

    "&:hover": {
      background: "#efefef"
    },
    "&:last-child": {
      borderRight: "solid 1px #cccccc"
    }
  },
  • 0
    Это не решение, вопрос был в том, как сделать это с INLINE css, а не с отдельной таблицей стилей.
  • 1
    Чувак, взгляни поближе. Это встроенный стиль.
Показать ещё 1 комментарий
0

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

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

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

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

0

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

0

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

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

Итак, мой фактический файл css существует с единственной целью - удерживать эффекты зависания, ничего другого. Это делает его довольно кратким и легким в управлении, и позволяет мне делать тяжелую работу в моих встроенных стилях 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>

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню