如何使用“onclick”事件更改 ListItem 元素的样式?

IT技术 reactjs material-ui
2021-05-22 18:36:43

我的目标是当我单击 ListItem 时,它应该更改background-colortext: "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>
    );
  }
}

编辑 v8ojkj2qzy

2个回答

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

下面我复制styles了处理backgroundColorand变量的所有部分textDecoration

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

导致困难的主要样式是button悬停和焦点样式。为了在不求助于“!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
    }
  },

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

编辑 5kv3j6r1xn

所以我尝试将!important添加到这种样式中,它开始按预期工作:

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

演示. 当您将鼠标悬停在元素上,看起来这个material-ui只是覆盖了您的样式(textDecoration 和 backgroundColor)希望有帮助。