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

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

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

<Clickable>
    <Link />
</Clickable>

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

有没有更简单的方法?


当前回答

这个解决方案确实使用了样式表。然而,如果你的应用程序使用了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/>
  )
}

其他回答

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

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

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

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

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

下面是另一个使用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}}>
<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 : {})
  });
}

这是一个用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>
  );
};