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

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

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

<Clickable>
    <Link />
</Clickable>

Clickable有一个悬停状态,并将其作为道具传递给链接。然而,Clickable(我实现它的方式)将链接包装在一个div中,以便它可以设置onMouseEnter和onMouseLeave。这让事情变得有点复杂(例如,在div中包装的span与span的行为不同)。

有没有更简单的方法?


我也有同样的情况。非常喜欢在组件中保持样式的模式,但悬停状态似乎是最后一个障碍。

我所做的是写一个mixin,你可以添加到你的组件,需要悬停状态。 这个mixin将为组件的状态添加一个新的悬停属性。如果用户将鼠标悬停在组件的主DOM节点上,它将被设置为true;如果用户离开元素,它将被设置为false。

现在在你的组件渲染函数中,你可以这样做:

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

现在,每当悬浮状态的状态发生变化时,组件将重新呈现。

我还为此创建了一个沙盒回购,我自己用它来测试这些模式中的一些。如果您想查看我的实现示例,请查看它。

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


你可以使用镭——它是一个开源工具,可以在ReactJS中使用内联样式。它恰好添加了您需要的选择器。非常受欢迎,看看npm上的镭


我认为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)来更改链接的样式。


您可以使用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);

下面是一个webpack css模块的例子


在某种程度上是因为这个原因(其他原因是与其他库/语法的实现不一致,内联样式缺乏对前缀属性值的支持)。相信我们应该能够简单地用JavaScript编写CSS,并拥有完全自包含的组件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 Syntax (j挑战者)

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

我在我最近的一个应用程序中使用了一个相当hack的解决方案,它符合我的目的,我发现它比在香草js中编写自定义悬停设置函数更快(尽管,我承认,在大多数环境中可能不是最佳实践..)所以,如果你还感兴趣,我告诉你。

我创建了一个父元素,只是为了保存内联javascript样式,然后是一个带有className或id的子元素,我的css样式表将锁定并在我的专用css文件中写入悬浮样式。这是因为更细粒度的子元素通过继承接收内联js样式,但其悬停样式被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”属性集。如果是这样,这将不起作用,因为内联样式将优先于样式表。


完全的CSS支持正是大量的CSSinJS库的原因,为了有效地做到这一点,你需要生成实际的CSS,而不是内联样式。此外,内联样式在大系统中的反应要慢得多。免责声明-我维护JSS。


补充乔纳森的回答,这里是事件覆盖的焦点和活跃状态,使用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>
    )
  }

对于styles -components和react-router v4,你可以这样做:

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

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

  &:hover {
    color: white;
  }
`

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

这可以是一个很好的hack内联样式在一个react组件(也使用:hover CSS函数):

...

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

...


onMouseOver和onMouseLeave with setState起初似乎对我来说有点开销-但这就是react的工作方式,对我来说这似乎是最简单和最干净的解决方案。

例如,呈现一个主题CSS服务器端也是一个很好的解决方案,可以使react组件更干净。

如果你不需要将动态样式附加到元素(例如主题),你就不应该使用内联样式,而应该使用CSS类。

这是一个传统的html/css规则,以保持html/ JSX干净简单。


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

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

聚会迟到了,但提出了解决方案。你可以使用“&”来定义悬停第n个子元素的样式。

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"
    }
},

使用钩子:

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的技巧:带有颜色和图像的悬停效果。

`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 (
    <aside className="menu">
        <div className="menu-item">
          <div style={landingImage}>SOME TEXT</div>
        </div>
    </aside>
      ); 
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

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

前徘徊

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

在徘徊

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

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


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

style.js

export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Button.js

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

<Hoverable hoverStyle={styles.linkHover}>
  <a href="https://example.com" style={styles.link}>
    Go
  </a>
</Hoverable>

其中Hoverable定义为:

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

下面是另一个使用CSS变量的选项。这需要一个css悬停定义提前,所以我猜它不是纯粹的内联,但是非常少的代码和灵活。

CSS(设置悬停状态):

.p:hover:{
 color:var(--hover-color) !important,
 opacity:var(--hover-opacity)
}

反应:

<p style={{'color':'red','--hover-color':'blue','--hover-opacity':0.5}}>

这是一个用typescript编写的通用hover包装器。该组件将在hover事件上应用通过props 'hoverStyle'传递的样式。

import React, { useState } from 'react';

export const Hover: React.FC<{
  style?: React.CSSProperties;
  hoverStyle: React.CSSProperties;
}> = ({ style = {}, hoverStyle, children }) => {
  const [isHovered, setHovered] = useState(false);
  const calculatedStyle = { ...style, ...(isHovered ? hoverStyle : {}) };
  return (
    <div
      style={calculatedStyle}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      {children}
    </div>
  );
};    

这可以通过material-ui makestyle调用轻松实现:

import { makeStyles } from '@material-ui/core/styles';

makeStyles({
  root: {
    /* … */
    '&:hover': { /* … */ }
  },
});

我使用这个技巧,混合了内联风格和css:

//inline-style:
const button = {
  fontSize: "2em",
};
return (
  <div style={button} data-hover="button">
    <style>{`[data-hover="button"]:hover {
        font-size: 2.1em !important;
    }`}</style>
    {this.props.text}
  </div>
);

我做了类似的事情,但我没有使用material-ui或makestyle。我在样式对象的css中添加了悬停作为条件:

const styles = {
  hoverStyle: {
    color: 'grey',
    '&:hover': { color: 'blue !important' },
  }
};

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

  return (
    <div>
      <div>
        {menuOptions.map((page) => <div style={styles.hoverStyle} key={page}>{page}</div> )}
      </div>
    </div>
  );
};

这对我很管用。


我找到了一种干净的方法,用useState的包装器来做到这一点,我称之为useHover。 不需要额外的库/框架。

const App = () => {

    const hover = useHover({backgroundColor: "LightBlue"})

    return <p {...hover}>Hover me!</p>
}

包装器的代码:

function useHover(styleOnHover: CSSProperties, styleOnNotHover: CSSProperties = {})
{
    const [style, setStyle] = React.useState(styleOnNotHover);

    const onMouseEnter = () => setStyle(styleOnHover)
    const onMouseLeave = () => setStyle(styleOnNotHover)

    return {style, onMouseEnter, onMouseLeave}
}

注意,当组件未悬停时,useHover有一个可选的第二个参数用于样式。

在这里试试吧


你可以创建一个抽象的悬停类,例如颜色。

.hoverClassColor:hover {
  color:var(--hover-color) !important;
}

然后在悬停时将所有元素的颜色更改为红色:

render() {
  return <a className={'hoverClassColor'} style={{'--hover-color':'red'}}>Test</a>
}

对我来说,它就像内联,因为类是抽象的,可以在你想实现颜色悬停的所有元素中重用。


下面是我如何在功能组件中使用钩子。使用onMouseEnter/Leave, im直接将颜色设置为状态,并在元素的样式道具中使用它(而不是设置悬停状态和使用三元组来改变状态,如前面的答案所示)。

function App() { const [col, setCol] = React.useState('white'); return ( <div className="App"> <button style={{background: `${col}`}} onMouseEnter={() => setCol("red")} onMouseLeave={() => setCol("white")} > Red </button> </div> ); } ReactDOM.render(<App/>, document.getElementById('root')) <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script> <div id='root'></div>


onMouseEnter={(e) => {
    e.target.style.backgroundColor = '#e13570';
    e.target.style.border = '2px solid rgb(31, 0, 69)';
    e.target.style.boxShadow = '-2px 0px 7px 2px #e13570';
}}
onMouseLeave={(e) => {
    e.target.style.backgroundColor = 'rgb(31, 0, 69)';
    e.target.style.border = '2px solid #593676';
    e.target.style.boxShadow = '-2px 0px 7px 2px #e13570';
}}

在样式或类中设置默认属性,然后调用onMouseLeave()和onMouseEnter()来创建悬停功能。


我最近也遇到了同样的情况。这是我的一个非常简单的解决方案,使用一个自定义钩子,如果元素悬停或不悬停则返回。

export const useOnHover = (ref: React.RefObject) => {
    const [hovered, setHovered] = React.useState(false);

    const mouseEntered = React.useCallback(() => {
        setHovered(true);
    }, [ref.current]);

    const mouseLeft = React.useCallback(() => {
        setHovered(false);
    }, [ref.current]);

    React.useEffect(() => {
        if (!ref.current) return;

        ref.current.addEventListener("mouseenter", mouseEntered);
        ref.current.addEventListener("mouseleave", mouseLeft);

        return () => {
            if (!ref.current) return;
            ref.current.removeEventListener("mouseenter", mouseEntered);
            ref.current.removeEventListener("mouseleave", mouseLeft);
        };
    }, [ref.current]);

    return hovered;
};

现在你可以像这样在任何元素上使用它:

const Button = (props) => {
    const buttonRef = React.useRef(null);

    const buttonHovered = useOnHover(buttonRef);
    return (
        <div
            ref={buttonRef}
            style={{
                //your styles
                backgroundColor: "red",
                filter: buttonHovered ? "saturate(100%)" : "saturate(50%)",
            }}
        >
            {props.title}
        </div>
    );
};

这个解决方案确实使用了样式表。然而,如果你的应用程序使用了index.css——也就是说,它有一个样式表被导入到你的顶级组件中,你可以只在那里写下面的代码

.hoverEffect:hover {
 //add some hover styles
}

然后在React组件中,添加类名“hoverEffect”来应用“内联”的悬停效果。

如果悬停状态是作为道具传递的,而你只想将它应用到子组件上,那么在index.css中删除:hover,并执行此操作。

function Link(props) {
  return (
    <a className={props.isHovered ? "hoverEffect" : ""}>Hover me<a/>
  )
}

直接在组件中使用标签,如下所示:

<Wrapper>
  <style>
   .custom-class{
       // CSS here
   }
   .custom-class:hover{
     //query selector
   }
  </style>
  <div className="custom-class"></div>
</Wrapper> 

最简单的方式:2022年: useRef +内联onMouseOver/onMouseOut

例子:

 var bottomAtag = useRef(null)
    
   

...然后在里面返回(

 <a ref={bottomAtag} onMouseOver={() => bottomAtag.current.style.color='#0F0'} ...></a>