reactjs - 如何使用 "onclick"事件更改 ListItem 元素的样式?

标签 reactjs material-ui

我的目标是当我单击 ListItem 时,它应该更改背景颜色文本:“line-through”。然后,如果我再次单击,这些更改应该被取消。
但这对我来说非常奇怪。我只是不明白为什么只有在单击窗口的任何位置后 ListItem 才会更改 background-color ?为什么只有当我将指针移到元素之外后,ListItem 中的文本才会被划掉

const styles = () => ({
  listItem: {
    borderRadius: "1em"
  },

  listItemDone: {
    borderRadius: "1em",
    backgroundColor: "#F6F6E8",
    textDecoration: "line-through"
  },

  iconButton: {
    padding: 5
  },

  important: {
    color: "#00ACE9",
    fontWeight: "bold"
  }
});

class TodoListItem extends Component {
  state = {
    done: false
  };

  onClickItem = () => {
    this.setState({
      done: !this.state.done
    });
  };

  render() {
    const { label, important = false, classes } = this.props;
    const { done } = this.state;

    return (
      <ListItem
        onClick={this.onClickItem}
        className={done ? classes.listItemDone : classes.listItem}
        button
        divider
      >
        <ListItemText
          primary={label}
          classes={{ primary: important ? classes.important : "" }}
        />
      </ListItem>
    );
  }
}

Edit v8ojkj2qzy

最佳答案

每当您尝试覆盖 Material-UI 样式但它没有像您期望的那样工作时,最好的资源就是源代码。以下是 ListItem 源代码的 URL:https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/ListItem/ListItem.js 。大多数情况下,您只需要查看源文件顶部附近的 styles 变量。

下面我复制了 styles 变量中处理 backgroundColortextDecoration 的所有部分:

export const styles = theme => ({
  /* Styles applied to the (normally root) `component` element. May be wrapped by a `container`. */
  root: {
    textDecoration: 'none',
    '&$selected, &$selected:hover, &$selected:focus': {
      backgroundColor: theme.palette.action.selected,
    },
  },
  /* Styles applied to the inner `component` element if `button={true}`. */
  button: {
    transition: theme.transitions.create('background-color', {
      duration: theme.transitions.duration.shortest,
    }),
    '&:hover': {
      textDecoration: 'none',
      backgroundColor: theme.palette.action.hover,
      // Reset on touch devices, it doesn't add specificity
      '@media (hover: none)': {
        backgroundColor: 'transparent',
      },
    },
    '&:focus': {
      backgroundColor: theme.palette.action.hover,
    },
  },
  /* Styles applied to the root element if `selected={true}`. */
  selected: {},
});

造成困难的主要样式是按钮悬停和焦点样式。为了成功覆盖这些而不诉诸“!important”,您需要具有适当的 CSS 特异性。

以下似乎可以解决问题:

  listItemDone: {
    borderRadius: "1em",
    "&,&:focus,&:hover": {
      backgroundColor: "#F6F6E8",
      textDecoration: "line-through"
    }
  },

但是,上述内容可以防止对“已完成”项目产生任何悬停效果,因此您可能想做一些更像这样的事情:

  listItemDone: {
    borderRadius: "1em",
    "&,&:focus": {
      backgroundColor: "#F6F6E8",
      textDecoration: "line-through"
    },
    "&:hover": {
      textDecoration: "line-through"
    }
  },

这允许已完成项目的悬停背景颜色仍然是theme.palette.action.hover。如果您希望完成的项目的悬停颜色不同,您可以与 textDecoration 一起显式指定它。

还有一个细节需要注意。如果您单击一个列表项将其置于“完成”状态,然后再次单击它,它将不再处于“完成”状态,但会应用 button 焦点样式。为了删除焦点样式,您还需要以下内容:

  listItem: {
    borderRadius: "1em",
    "&,&:focus": {
      backgroundColor: theme.palette.background.paper // or whatever color you want this to be
    }
  },

这是我对沙箱的修改版本:

Edit 5kv3j6r1xn

关于reactjs - 如何使用 "onclick"事件更改 ListItem 元素的样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54497327/

相关文章:

javascript - React Material UI OutlinedInput 不显示错误信息

javascript - React - useMemo 有一个复杂的表达式 - 将其提取到一个单独的变量中,以便对其进行静态检查

javascript - 更新状态数组中的特定对象

javascript - 在 react if 语句中拆分字符串

reactjs - 目前对于哪种 api 设计适合 React/Redux 应用程序达成共识吗?

javascript - 具有多值性能的 React Context API

javascript - 类型 'void' 不可分配给类型 '(event: MouseEvent<HTMLDivElement, MouseEvent>) => void'

performance - 重新渲染列表的单行而不重新渲染整个列表

javascript - MUI 按钮悬停背景颜色和文本颜色

javascript - 从 Material UI TextField 调用电话或打开电子邮件客户端