事件触发样式组件 css 更改

Event triggered styled component css change

我现在才切换到样式化组件,找不到这个相当简单的逻辑的答案:如果字段验证失败,它应该有红色边框。

带有 classic CSS classes:

const validateMail = (e) => {
    let mail = e.target.value;
    if (!mailRegex.test(mail)) {
        e.target.classList.add("error");
        return;
    }
    e.target.classList.remove("error");
}

我怎样才能做类似于e.target.classList.add("error")的事情?我假设我必须以某种方式将此列表更改为可以更改字段样式的内容。这是触发此功能的输入样式组件的完整 class:

const Field = styled.div`
    display: flex;
    flex-direction: column;
`;

const Label = styled.label`
    font: ${fonts.body1};
    font-size: .75rem;
`;

const Input = styled.input`
    font: ${fonts.body1};
    padding: 10px;
    border-radius: 5px;
    outline: none;
    border: 1px solid rgba(0, 0, 0, 0.3);
    width: 100%;
    resize: none;
    box-sizing: border-box;
    &:focus {
        border: 1px solid ${palette.primary_blue};
    }
`;

function InputField(props) {
    return (
        <Field>
            <Label htmlFor={"txt" + props.name}>{props.name + ":"}</Label>
            <Input name={"txt" + props.name} onKeyUp={props.onKeyUp}></Input>
        </Field>
    );
}

export default InputField;

如您所见,带样式的组件不遵循 classic class 列表范例。有几种方法可以达到您想要的结果。我已经演示了 2.

方法 1:将 prop 传递给样式化组件。

您可以像这样将自定义 isValid 道具传递给样式化组件:

<Input
  isValid={isValid}
  name={"txt" + props.name}
  onKeyUp={props.onKeyUp}
/>

然后您可以根据 prop 的评估方式在样式化组件中添加条件渲染逻辑。

请注意,样式化组件定义中的以下箭头函数(代替 styled.input)可确保将 prop 视为组件 prop 而不是实际的 DOM 元素属性(这将不是有效标记并可能导致错误):

const Input = styled(({
  isValid,
  ...props
}) => <input {...props} />)`
  border: 1px solid ${({ isValid }) =>
  isValid ? `rgba(0, 0, 0, 0.3)` : `red`)};

  /* ... the rest of your styles... */
`;

有关上述内容的实例,请参阅此 Code Sandbox。请注意第 41 行,其中 isValid 被设置为 false 作为实际验证逻辑的替代。尝试将其更改为 true,您会看到边框颜色发生变化。


方法 2:为有效状态和错误状态创建 2 个独立样式的组件:

const Input = styled.input`
  border: 1px solid rgba(0, 0, 0, 0.3);

  /* ... the rest of your styles... */
`;

const ErrorInput = styled(Input)`
  border-color: red;
`;
const StyledInput = isValid ? Input : ErrorInput;

return (
  <Field>
    <Label htmlFor={"txt" + props.name}>{props.name + ":"}</Label>
    <StyledInput
      name={"txt" + props.name}
      onKeyUp={props.onKeyUp}
    />
  </Field>
);

这是此方法的 Code Sandbox。与第一种方法相同,请参阅第 45 行以了解硬编码 isValid 值。

关于转换的注意事项

我更喜欢第一个解决方案,因为它允许在变化的值之间平滑过渡(就像 classes)。第二种方法适用于静态渲染元素,但当组件引用从 Input 更改为 ErrorInput 时,它基本上会 destroy/create 动态生成一个新元素。如果你想要平滑过渡,那么你应该使用第一种方法。