关于React:React中的内联CSS样式:如何实现a:hover?

Inline CSS styles in React: how to implement a:hover?

我非常喜欢React中的内联CSS模式,并决定使用它。

但是,不能使用:hover和类似的选择器。 那么在使用内联CSS样式时实现悬停时高亮显示的最佳方法是什么?

#reactjs的一个建议是拥有一个Clickable组件并像这样使用它:

1
2
3
<Clickable>
    <Link />
</Clickable>

Clickable具有hovered状态,并将其作为道具传递给链接。 但是,Clickable(我实现它的方式)将Link包裹在div中,以便可以为其设置onMouseEnteronMouseLeave。 尽管这使事情有些复杂(例如包装在div中的span的行为不同于span的行为)。

有没有更简单的方法?


我认为onMouseEnter和onMouseLeave是可行的方法,但是我认为不需要额外的包装器组件。这是我的实现方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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(
     
        Link
     
    )
}

然后,您可以使用悬停状态(true / false)更改链接的样式。


我处于同样的情况。确实像在组件中保留样式的模式,但悬停状态似乎是最后的障碍。

我所做的是编写一个mixin,您可以将其添加到需要悬停状态的组件中。
该混合将为组件的状态添加一个新的hovered属性。如果用户将鼠标悬停在组件的主DOM节点上,则将其设置为true;如果用户离开该元素,则将其设置回false

现在,在组件渲染函数中,您可以执行以下操作:

1
2
3
4
<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


晚会,但要有解决方案。您可以使用"&"来定义第n个Child等的样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"
    }
},


您可以使用Radium-它是ReactJS用于内联样式的开源工具。它恰好添加了您需要的选择器。非常受欢迎,请查看-Radium on npm


完全的CSS支持正是这大量CSSinJS库有效运行的原因,您需要生成实际的CSS,而不是内联样式。此外,在较大的系统中,内联样式的响应速度要慢得多。免责声明-我维护JSS。


Made Style It(部分原因)是由于这个原因(其他人则不同意其他libs /语法的实现和内联样式缺乏对前缀属性值的支持)。相信我们应该能够简单地用JavaScript编写CSS并拥有完全独立的组件HTML-CSS-JS。现在有了ES5 / ES6模板字符串,它也可以变得很漂亮! :)

npm install style-it --save

功能语法(JSFIDDLE)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;


关于样式化组件和react-router v4,您可以执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
import {NavLink} from 'react-router-dom'

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

  &:hover {
    color: white;
  }
`

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

加上乔纳森的答案,以下是涵盖焦点和活动状态的事件,以及使用onMouseOver而不是onMouseEnter的事件,因为如果将事件应用于目标中的任何子元素,后者不会冒泡。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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(
     
        <a style={linkStyle}
          onMouseOver={this.toggleHover}
          onMouseOut={this.toggleHover}
          onMouseUp={this.toggleActive}
          onMouseDown={this.toggleActive}
          onFocus={this.toggleFocus}>
          Link
       
     
    )
  }

对于在react组件中具有内联样式(以及还使用:hover CSS函数),这可能是一个不错的技巧:

1
2
3
4
5
6
7
...

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

...

如果您将React与Typescript一起使用,请签出Typestyle。

以下是:hover的示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

您可以使用css模块作为替代,并另外使用react-css-modules进行类名映射。

这样,您可以按照以下方式导入样式,并使用本地范围内的常规css到组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return
           
                A0
                B0
           
        ;
    }
}

export default CSSModules(Table, styles);

这是一个webpack css模块示例


首先,使用setState的onMouseOver和onMouseLeave对我来说似乎有些负担-但是由于这是React的工作方式,因此这对我来说似乎是最简单,最干净的解决方案。

例如,在服务器端渲染主题css也是一个很好的解决方案,并且可以使React组件更加干净。

如果您不必在元素上添加动态样式(例如用于theming),则根本不应该使用内联样式,而应使用css类。

这是传统的html / css规则,用于保持html / JSX的简洁和简洁。


简单的方法是使用三元运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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(
     
        Link
     
    )
  }

这是我使用React Hooks的解决方案。它结合了扩展运算符和三元运算符。

style.js

1
2
3
4
5
6
7
8
9
export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Button.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React, {useState} from 'react';
import style from './style.js'

function Button(){

  const [hover, setHover] = useState(false);

  return(
    <button
      onMouseEnter={()=>{
        setHover(true);
      }}
      onMouseLeave={()=>{
        setHover(false);
      }}
      style={{
        ...style.normal,
        ...(hover ? style.hover : null)
      }}>

        MyButtonText

    </button>
  )
}

1
2
3
4
5
<Hoverable hoverStyle={styles.linkHover}>
 
    Go
 
</Hoverable>

可悬停定义为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function Hoverable(props) {
  const [hover, setHover] = useState(false);

  const child = Children.only(props.children);

  const onHoverChange = useCallback(
    e => {
      const name = e.type ==="mouseenter" ?"onMouseEnter" :"onMouseLeave";
      setHover(!hover);
      if (child.props[name]) {
        child.props[name](e);
      }
    },
    [setHover, hover, child]
  );

  return React.cloneElement(child, {
    onMouseEnter: onHoverChange,
    onMouseLeave: onHoverChange,
    style: Object.assign({}, child.props.style, hover ? props.hoverStyle : {})
  });
}

我在最近的一个可以满足我的目的的应用程序中使用了一个不错的解决方案,并且发现它比在vanilla js中编写自定义悬停设置功能要快(尽管我知道,在大多数环境中,这也许不是最佳实践) ..)所以,如果您仍然有兴趣,请继续。

我创建一个父元素只是为了保持内联javascript样式,然后创建一个具有className或id的子代,我的css样式表将其锁定到该子代中,并将悬停样式写入我的专用css文件中。之所以可行,是因为更细的子元素通过继承接收内联js样式,但是其悬浮样式被css文件覆盖。

因此,基本上,我的实际css文件存在的唯一目的是保持悬停效果,仅此而已。这使得它非常简洁,易于管理,并且使我能够进行嵌入式React组件样式的繁重工作。

这是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 (
   
     
        {menuOptions.map((page) => {page} )}
     
   
  );
};


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

请注意,"子级"内联样式没有设置"颜色"属性。如果是这样,这将不起作用,因为内联样式将优先于我的样式表。


使用钩子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const useFade = () => {
  const [ fade, setFade ] = useState(false);

  const onMouseEnter = () => {
    setFade(true);
  };

  const onMouseLeave = () => {
    setFade(false);
  };

  const fadeStyle = !fade ? {
    opacity: 1, transition: 'all .2s ease-in-out',
  } : {
    opacity: .5, transition: 'all .2s ease-in-out',
  };

  return { fadeStyle, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeStyle, ...fadeProps } = useFade();

  return (
    <Paper
      style={{...fadeStyle, ...style}}
      {...fadeProps}
    >
      {...}
    </Paper>
  );
};

我不是100%确定这是否是答案,但我使用内联颜色和图像来模拟CSS:hover效果的技巧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
`This works best with an image`

class TestHover extends React.PureComponent {
render() {
const landingImage = {    
"backgroundImage":"url(https://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg)",
"BackgroundColor":"Red", `this can be any color`
"minHeight":"100%",
"backgroundAttachment":"fixed",
"backgroundPosition":"center",
"backgroundRepeat":"no-repeat",
"backgroundSize":"cover",
"opacity":"0.8", `the hove trick is here in the opcaity slightly see through gives the effect when the background color changes`
    }

  return (
   
       
          SOME TEXT
       
    </aside>
      );
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.menu {
top: 2.70em;
bottom: 0px;
width: 100%;
position: absolute;
}

.menu-item {
cursor: pointer;
height: 100%;
font-size: 2em;
line-height: 1.3em;
color: #000;
font-family:"Poppins";
font-style: italic;
font-weight: 800;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}

Before hover

1
2
3
4
.menu-item:nth-child(1) {
color: white;
background-color: #001b37;
}

On hover

1
2
3
4
.menu-item:nth-child(1):hover {
color: green;
background-color: white;
}

示例:https://codepen.io/roryfn/pen/dxyYqj?editors = 0011