компоненты в стиле styled, ссылающиеся на другие компоненты и использующие их реквизиты?

#reactjs #styled-components

#reactjs #компоненты в стиле

Вопрос:

Как мне заставить это работать?

img передается как <Child /> реквизит, и я хочу изменить фоновое изображение дочернего элемента при <Parent /> наведении курсора

 <Parent>
  <Child img={'path/to/img.png'}/>
</Parent>
  
 const Child = styled.div`

`;

const Parent = styled.div`
  amp;:hover {
    ${Child} {
      background-image: url(${props => props.img});
    }
  }
`;

  

Комментарии:

1. Я думаю, это потому, что ‘img’ передается дочернему элементу вместо родительского, но вы обращаетесь к нему внутри родительского элемента.

2. Как сказал хаопенг, в этом случае props содержит реквизиты Parent компонента, а не реквизиты Child компонента. Вам нужно достичь своей цели только с помощью styled-component или вы можете использовать какой-то обходной путь с помощью JS? РЕДАКТИРОВАТЬ: было бы полезно узнать, Child всегда ли будет единственным дочерним элементом Parent ; если да, я могу показать вам решение, использующее только styled-component

Ответ №1:

Надеюсь, это может вам помочь!

    amp;:hover ${Child}{
      background-image: url(${props => props.image amp;amp; css`${props.image}`});
   }
  

Вот рабочий пример https://codepen.io/hardik-chaudhary/pen/rKEKWG


ОБНОВЛЕННЫЙ КОД

Используйте код наведения в дочернем элементе вместо родительского. И все просто отлично работает. Я также обновил код в ручке (https://codepen.io/hardik-chaudhary/pen/rKEKWG ).

 const Child = styled.div`
   ${Parent}:hover amp; {
      background-image: url(${props => props.image amp;amp; css`${props.image}`});
  }
`;
  

Комментарии:

1. это работает, потому что вы передаете image в <Button /> , что, если я захочу image передать в <Child /> , я не хочу <Child /> использовать реквизиты его родителя, это делает код уродливым.

2. Я обновил код в данном pen. Вы можете передать реквизит от дочернего элемента и можете изменить фон при наведении курсора мыши.

Ответ №2:

Итак, мне удалось частично решить проблему (возможно, то, что осталось, в вашем случае не важно, дайте мне знать).

Сначала скрипка, затем пояснения:

 const img1 = "https://images.pexels.com/photos/2047905/pexels-photo-2047905.jpeg?cs=srgbamp;dl=apple-device-art-colorful-2047905.jpgamp;fm=jpg";
const img2 = "https://images.pexels.com/photos/2027104/pexels-photo-2027104.jpeg?auto=compressamp;cs=tinysrgbamp;dpr=2amp;h=650amp;w=940";
const img3 = "https://images.pexels.com/photos/2029478/pexels-photo-2029478.jpeg?auto=compressamp;cs=tinysrgbamp;dpr=2amp;h=650amp;w=940";

window.styled = window.styled.default;

function changeBG(props) {
    if (Array.isArray(props.children)) {   
        let a;
        props.children.forEach(el => {
            if (el.type.styledComponentId === Child.styledComponentId) {
                a = el.props.bgImg;
            }
        });
        return a;
    } else {
        return (props.children.type.styledComponentId === Child.styledComponentId)
            ? props.children.props.bgImg
            : ""
    }    
}

const Child = styled.div`
    width: 200px;
    height: 100px;
    border: 1px solid green;
    background-image: url("${img2}");
    background-size: contain;
`;

const Parent = styled.div`
    width: 400px;
    height: 200px;
    border: 1px solid rgba(0,0,0,0.5);

    amp;:hover {
        ${Child} {            
            background-image: url("${props => changeBG(props)}");
        }
    }
`;

class App extends React.Component {
    constructor(props) {
        super(props);
    }
    
    render() {
        return (
            <Parent>
                <Child bgImg={img1} />
                <Child bgImg={img3} />
            </Parent>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
                      
 const img1 = "https://images.pexels.com/photos/2047905/pexels-photo-2047905.jpeg?cs=srgbamp;dl=apple-device-art-colorful-2047905.jpgamp;fm=jpg";
const img2 = "https://images.pexels.com/photos/2027104/pexels-photo-2027104.jpeg?auto=compressamp;cs=tinysrgbamp;dpr=2amp;h=650amp;w=940";
const img3 = "https://images.pexels.com/photos/2029478/pexels-photo-2029478.jpeg?auto=compressamp;cs=tinysrgbamp;dpr=2amp;h=650amp;w=940";

window.styled = window.styled.defau<

function changeBG(props) {
    console.log(props.children);
    if (Array.isArray(props.children)) {   
        let a;
        props.children.forEach(el => {
            if (el.type.styledComponentId === Child.styledComponentId) {
                a = el.props.bgImg;
            }
        });
        return a;
    } else {
        return (props.children.type.styledComponentId === Child.styledComponentId)
            ? props.children.props.bgImg
            : ""
    }    
}

const Child = styled.div`
    width: 200px;
    height: 100px;
    border: 1px solid green;
    background-image: url("${img2}");
    background-size: contain;
`;

const Parent = styled.div`
    width: 400px;
    height: 200px;
    border: 1px solid rgba(0,0,0,0.5);

    amp;:hover {
        ${Child} {            
            background-image: url("${props => changeBG(props)}");
        }
    }
`;

class App extends React.Component {
    constructor(props) {
        super(props);
    }
    
    render() {
        return (
            <Parent>
                <Child bgImg={img1} />
                <Child bgImg={img3} />
            </Parent>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
                      
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/styled-components/3.4.10/styled-components.min.js"></script>
<div id='root'></div>  

В принципе, Parent styled-component действует так, как вы написали, ожидайте, что он запускает вызываемую функцию changeBG . При этом, проверяя el.type.styledComponentId === Child.styledComponentId , я проверяю, что дочерний элемент имеет тип Child : если это так, мы можем использовать props.bgImg .

Хотя, может возникнуть некоторая проблема, если у Parent компонента есть дочерние элементы, которые не являются Child типом.. И, если дочерних Child компонентов несколько Parent , я все еще не смог отобразить другое фоновое изображение при наведении курсора мыши.. Но, я спрашиваю, это необходимо? Я могу попытаться найти обходной путь и для этого.