是否可以根据复选框的状态为复选框的子项设置样式,而无需在“样式化组件”中使用三元样式?

时间:2019-04-01 19:19:45

标签: javascript css reactjs styled-components

我正在尝试使用样式化的组件对这个组件进行样式设置,但是我的解决方案似乎有些破旧。使用“样式化的组件”对该组件进行样式设置的最佳实践是什么?

使用普通HTML和CSS,我可以创建它:

HTML:

<label>
  <input type="checkbox" value="s1"/>
  <div class="container">s1</div>
</label>
<label>
  <input type="checkbox" value="s2"/>
  <div class="container">s2</div>
</label>
<label>
  <input type="checkbox" value="s3"/>
  <div class="container">s3</div>
</label>
<label>
  <input type="checkbox" value="s4"/>
  <div class="container">s4</div>
</label>

CSS:

input[type=checkbox] {
  position: absolute;
  width: 0;    
}

.container {
  width: 5em;
  border: solid #aaa 1px;
  background: #fff
  color: #000;
}
.container:hover {
  background: #999;
}  

.container:active {
  background: #333;
  color:#fff
}

input[type=checkbox]:checked + .container {   
  background: #000;
  color: #fff;
}    

input[type=checkbox]:checked + .container:hover {
  background: #ddd;
}  

input[type=checkbox]:checked + .container:hover:active {
  background: white;
  color: black;
}  

使用React组件和样式化组件,我也可以创建它,但是我不喜欢使用两个不同的样式化组件和三元函数来完成使用input[type=checkbox]:checked + .container在CSS中可以完成的工作。

import React, { useState } from 'react';
import styled from 'styled-components'

function Test() {
  const [selectedStations, setSelectedStations] = useState([]);  

  const Input = styled.input`
    position: absolute;
    width: 0;    
  ` 
  const UncheckedContainer = styled.div` 
    width: 5em;    
    border: solid #aaa 1px;
    background: #fff;
    color: #000;

  &:hover {
    background: #999;
  }  

  &:active {
      background: #333;
      color: #fff;
  }
  `
  const CheckedContainer = styled.div`
    width: 5em;
    border: solid black 1px;
    background: #000;
    color: #fff;

  &:hover {
    background: #ddd;
  }  

  &:active {
      background: #fff;
      color: #000;
  }  
  `

  function selectStations(e) {    
    let station = e.target.value;
    const s = [...selectedStations]
    const stationIndex = s.indexOf(station)

    if (stationIndex > -1) {
      s.splice(stationIndex, 1);
    } else {
      s.push(station);
      s.sort();
    }

    setSelectedStations(s)
  };


  return (
    <div>
        {new Array(4).fill('').map((v, i) =>{

          let checked = selectedStations.indexOf(`s${i+1}`) > -1         

          return(
            <label key={`station${i + 1}`}>
            <Input              
              type="checkbox"
              value={`s${i+1}`}
              checked={checked}
              onChange={(e)=>selectStations(e)}              
            />

            {checked ? 
              <CheckedContainer>
                  {`s${i+1}`}
              </CheckedContainer>            
            : 
              <UncheckedContainer>
                  {`Station ${i+1}`}
              </UncheckedContainer>
            }


          </label>
          )}
        )}
    </div>
  )
}

export default Test;

是否可以清理一点但仍使用样式化组件?

2 个答案:

答案 0 :(得分:0)

您可以在变量中包含复选框的状态,并将其传递给样式化的组件,例如:

<StyledComponent isChecked={isChecked} />

然后在样式化组件中:

const StyledComponent = styled.input`

 color: ${props => props.isChecked ? '#fff' : '#000'};

`

..等等,用于背景颜色和边框。

答案 1 :(得分:0)

您可以访问styled-component内的道具,也可以使用诸如嵌套之类的无礼来瞄准孩子。

const Checkbox = styled.label`
  postion: relative;
  input[type="checkbox"] {
    // style here
  }
  .inner-checkbox {
    color: ${props => props.checked ? "red" : "blue"};
    // style here
  }
`

const List = props => {
  return props.list.map(item => (
    <Checkbox key={item.id} checked={item.checked}>
      <input checked={item.checked} type="checkbox" onChange={this.updateState} />
      <div className="inner-checkbox" />
    </Checkbox>
  ))
}

我极力避免的另一件事是在另一个组件内部创建样式化的组件。