стилизованные компоненты: все в одном

внешний интерфейс JavaScript React.js CSS Web Components
стилизованные компоненты: все в одном
  • Первый опыт
  • стилизованный метод: оберните компоненты React в стилизованные компоненты
    • ( ) три случая
    • tagged template literal
      • интерполяции интерполяционные выражения
      • mixin
  • Связанные свойства StyledComponent
    • продлить наследство
    • withComponent
    • component-selector
    • innerRef
    • isStyledComponent
  • Метод attrit: добавить атрибуты по умолчанию в созданные компоненты
  • Компоненты темы
    • defaultProps
    • Об объектах темы
    • ThemeProvider, вложенный в тему Function
    • Получить тему в компоненте React
  • Метод injectGlobal: вставка глобальных стилей
  • метод ключевых кадров: использовать покадровую анимацию
  • разное

pre-notify

previously:

В сегодняшнем все более компонентном развитии мы передаемJSXjs и html/xml были смешаны вместе, так что насчет css?

Хотя в такой среде, как vue, мы можем.vueВ файле css, js и html прописаны вместе, но по факту их связь очень слабая, особенно js и css, они совершенно не умеют общаться.

а такжеstyled-componentsОн очень хорошо решает эту проблему, с его помощью мы можем заставить всю архитектуру CSS следовать за компонентами, а не просто размещаться в файле. Можно сказать, что styled-components делают компонент более полным и более похожим на компонент!

Первый опыт

styled-compnents, как следует из названия, выполнен в стилеreact-component, является перепаковкой компонента реакции, он может не только идти в<Component/>Добавлены фиксированные стили CSS, и CSS можно тесно связать с компонентом через свойства компонента.

Кроме того, он поддерживает почти всеsass/lessи другие функции, которыми обладают препроцессоры CSS, вложенность,&, переменные, интерполяция и многое другое!

Давайте сначала посмотрим на основное использование каштанов.

// 把一个React-Component包装成Styled-Component

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

class Xxx extends React.Component{
  render(){
    return (
      <div className={this.props.className}>
        container
        <h2>title</h2>
        <div>body</div>
      </div>
    )
  }
}

const StyledComponent = styled(Xxx)`
  &{
    color:red;
    h2{
      color:blue;
    }
    div{
      font-size:${props=>props.fontSize};
      color:pink;
    }
  }
`;

export default StyledComponent;

styled()даstyle-componentsСамый важный метод в , он оборачивает компонент React в стилизованный<StyleComponent/>, а также пройдетclassNameАтрибут, значением этого атрибута является строка хеш-значений (для предотвращения конфликтов имен), нам нужнопоместите его на элемент, где он должен быть размещен.

пройти черезstyled(), мы обернули компонент React в компонент Styled и экспортировали его, затем давайте отрендерим этот экспортированный компонент

import React from 'react';
import ReactDOM from 'react-dom';
import StyledComponent from './test.js';

ReactDOM.render(
  <StyledComponent fontSize='30px'/>
  ,window.root
)

Результат рендеринга выглядит так:

Можно обнаружить, что нет никакой разницы между используемым StyledComponent и ReactComponent, эммм, следует сказать, что есть еще немного, мы можем передавать атрибуты компоненту для управления стилем CSS компонента, Итак, StyledComponent на самом деле является надмножеством ReactComponent.

Ну что, интересно? Давайте узнаем больше вместеstyle-componentsБар!

стилизованный метод: оберните компоненты React в стилизованные компоненты

Мы уже знаем, что styled может делать в Shangli, на этот раз давайте полностью проанализируем этот API.

Сначала его формат такой

const StyledCompoent = styled()``

Он получает два параметра (на самом деле это способ написания функции метки в es6, который здесь не будет расширяться) и, наконец, возвращает обернутый компонент React, то есть стилизованный компонент React.

( ) три случая

()может получитьReact-Componentтакже может получитьtagName.

В предыдущем каштане мы продемонстрировали первый случай, так что на самом деле он также может получить tagName, такой какdiv

const StyledCompoent = styled('div')``

На самом деле, это эквивалентно

let ReactComponent = (props,context)=><div className={props.className}></div>; //上栗中我们说过当我们调用styed()时,react组件中会自动传入一个由hash组成的className属性

const StyledCompoent = styled(ReactComponent)``

Кроме того, у него есть ярлык

const StyledCompoent = styled.div``

Что ж, в дополнение к двум вышеупомянутым основным ситуациям, есть еще одна ситуация, которая()также может получить StyledComponent, что чаще всего происходит вКогда стиль StyledComponent должен наследоваться от другого StyledComponent.

const StyledCompoent2 = styled(StyledCompoent1)`
    color:'orange'
`

tagged template literal

эммм... как это перевести? Строка шаблона ярлыка? Литералы шаблонов с тегами?

Неважно~ В любом случае, это относится к скобкам (())После``содержание в.

проходя черезstyled()После того, как мы убедились, чтоЭффективныйАктуальный компонент инициализируется для стилизованного компонента, а затем нам нужно только добавить стиль к этому компоненту.

const StyledCompoent = styled.div`
  /* all declarations will be prefixed */
  //所有css样式会自动添加兼容性前缀
  padding: 2em 1em;
  background: papayawhip;

  /* pseudo selectors work as well */
  //支持伪类选择器
  &:hover {
    background: palevioletred;
  }

  /* media queries are no problem */
  //支持媒体查询
  @media (max-width: 600px) {
    background: tomato;

    /* nested rules work as expected */
    //支持嵌套
    &:hover {
      background: yellow;
    }
  }

  > p {
    /* descendant-selectors work as well, but are more of an escape hatch */
    //支持后代选择器
    text-decoration: underline;
  }

  /* Contextual selectors work as well */
  //支持环境选择器
  html.test & {
    display: none;
  }
`;

Приведенный выше пример из официального документа, видно, что в нем нет поддержки Yali: вложенность,Автодополнение префикса, различные селекторы, медиа-запросы...

интерполяции интерполяционные выражения

Кроме того, конечно, он также поддерживает переменные, и есть два варианта

let color1 = 'orange';

const StyledCompoent = styled.div`
    color:${color1} //支持接收js变量作为css属性值
    ,fontSize:${props=>props.fontSize}; //支持接收组件的props中的某个值来作为css属性值
`

//--- --- --- 

// somewhere
...
<StyledComponent fontSize='30px'/>
...

один из них${}называетсяinterpolationsэм, интерполяционное выражение, его надо назвать?

Следует отметить, что в ${} можно поместить переменную js или функцию. Если это функция, она приметpropsСвойства (то есть объект реквизита, обернутый при инициализации компонента React) используются в качестве параметров.

Эй, есть еще одна возможность, ${} также может получить объект css, например этот

...
${{
    position:'absolute'
    ,left:'100px'
    ,top:'100px'
}}
...

mixin

styled-components также позволяет нам использовать такие вещи, как @mixin в sass.

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

class Xxx extends React.Component{
  render(){
    return (
      <div className={this.props.className}>
        container
        <h2 className='title'>title</h2>
        <div className='content'>body</div>
      </div>
    )
  }
}

let mixin = css`
  &{
    color:red;
    ${{
      position:'absolute'
      ,left:'100px'
      ,top:'100px'
    }}
    .title{
      color:blue;
    }
    .content{
      font-size:${props=>props.someCondition.fontSize};
      color:pink;
    }
  }
`

const StyledComponent = styled(Xxx)`
  ${props=>props.someCondition?mixin:null}
`;

export default StyledComponent;


// --- --- ---

ReactDOM.render(
  <StyledComponent someCondition={{fontSize:'30px'}}/>
  ,window.root
)

Среди них мы использовали еще один метод в styled-componentscss, этот метод фактически создаетmixin, так что мы можем использовать любой<StyledComponent>повторно используйте этот стиль.

должны знать о том,propsсвойства могутпроникнутьДатьmixinсделать так, чтобы он использовался внутри (иначе как бы мы сказали, что это миксин)

Окончательный результат рендеринга выглядит так

Связанные свойства StyledComponent

через предыдущий разделstyled()метод оборачивает компонент реакции в стилизованный компонент реакции, мы называем егоStyledComponent, помимо того, что он тесно связан с компонентами по стилю, он также обладает некоторыми уникальными особенностями.

продлить наследство

Как мы уже говорили, мы можемstyled(StyledCompoent1)StyleComponent для создания StyledComponent2, наследуемого от StyledComponent1.

let StyledCompoent2 = styled(StyledCompoent1)`
    color:xxx
    ...
`

Но такое наследование на самом делезаводской узор, StyledComponent2 на самом деле является совершенно новым классом.

если мы хотим сделатьистинное наследство, вам нужно использовать компоненты стиля, предоставленныеextendметод, который является методом свойства в StyleComponent.

let StyledCompoent2 =StyledCompoent1.extend`
    color:xxx
    ...
`

withComponent

withComponent также является методом свойства в StyleComponent, который может помочь нам заменить метку в исходном компоненте Styled другой меткой.

//会将原本的<button>替换成<a>
const Link = Button.withComponent('a');

[danger] Уведомление:Если исходный компонент Styled является компонентом с составным тегом, то будет заменен весь его DOM, что может оказаться не таким, как вы ожидаете.

component-selector

styled-components позволяет нам использоватьtagged template literalиспользуйте переменную StyledComponent в качестве селектора CSS, давайте назовем ееcomponent-selector.

Уведомление:Все еще нужно вручную найти начальную позицию className

let ReactComponent = (props,context)=>{
    <div className={props.className}>
    	<h2>hello</h2>
    </div>
}
let StyledComponent1 = styled(ReactComponent)``
let StyledComponent2 = styled.div`
    ${StyledComponent1}{
        background:orange;
        h2{
          color:red;
        }
        &:after{
          content:'';
          display:block;
          width:10px;
          height:10px;
          border:1px solid black;
        }
    }
`

//--- --- ---
...
ReactDOM.render(
  <StyledComponent2>
    <StyledComponent1/>
  </StyledComponent2>
  ,window.root
)

innerRef

В styled-components, если мы хотим получить реальную запись DOM StyledComponent, нам нужно использовать innerRef вместо ref (функция и использование одинаковы).

const Input = styled.input`
  padding: 0.5em;
  margin: 0.5em;
  color: palevioletred;
  background: papayawhip;
  border: none;
  border-radius: 3px;
  ${{color:'red'}}
`;

export default class Form extends React.Component {
  render() {
    return (
      <Input
        placeholder="Hover here..."
        innerRef={x => { this.input = x }}
        onMouseEnter={() => this.input.focus()}
      />
    );
  }
}

Нажмите, чтобы увидеть официальный пример

Используемый верхний каштанstyled.inputЭтот быстрый способ создать styledComponent,

Если мы перейдем к использованиюstyled(原生React组件)образом, тогда мы не можем получить дом, как указано выше, мы получаемstyled()Нативный объект компонента React, переданный в круглых скобках

class _B extends React.Component{
  render(){
    return <div></div>
  }
}

const B = styled(_B)``;

export default class A extends React.Component{
  componentDidMount(){
    console.log('this.dom', this.dom);
  }
  render(){
    return <B innerRef={x => this.dom = x}></B>;
  }
}

(То, что вы получаете, это не dom, а объект компонента до того, как он будет стилизован)

Решение находится в_Bиспользовать роднойrefСмонтируйте один раз, смонтируйте дом в_B, чтобы мы могли получить дом, перейдя на один уровень ниже.

isStyledComponent

Иногда нам нужно решить, является ли компонент StyledComponent, чтобы мы могли использовать функции, которые есть только у StyledComponent, такие какcomponent-selector

import React from 'react';
import styled, { isStyledComponent } from 'styled-components';
import MaybeStyledComponent from './somewhere-else';

let TargetedComponent =
  isStyledComponent(MaybeStyledComponent)
    ? MaybeStyledComponent
    : styled(MaybeStyledComponent)``;

const ParentComponent = styled.div`
  color: cornflowerblue;

  ${TargetedComponent} {
    color: tomato;
  }
`

Уведомление:Метод isStyledComponent требует дополнительного импорта из styled-components.

Метод attr: добавление атрибутов по умолчанию к компонентам Styled

Метод attr принимает объект, который позволяет нам добавлять атрибуты по умолчанию и значения стиля по умолчанию в StyledComponent.

Этот метод также является одним из наиболее важных методов в styled-components.

const Input = styled.input.attrs({
  // 定义一些静态属性
  type: 'password',

  // 给css属性动态赋予初始值
  margin: props => props.size || '1em',
  padding: props => props.size || '1em'
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;

  /* here we use the dynamically computed props */
  margin: ${props => props.margin};
  padding: ${props => props.padding};
`;

export default class xxx extends React.Component{
  render(){
    return (
      <div>
        <Input placholder='A small text input' size='1em'/>
        <br/>
        <Input placholder='A bigger text input' size='2em'/>
      </div>
    )
  }
}

Окончательный результат рендеринга выглядит так

Компоненты темы

Предоставлено нам styled-componentsThemeProviderкомпонент (да, компонент React), мы можем настроить тему для нашего StyledComponent.

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

// 定制主题
const theme = {
  main:'mediumseagreen'
}

const Button = styled.button`
  font-size:1em;
  margin:1em;
  padding:0.25em 1em;
  border-radius:3px;
  /*color the border and text with theme.main*/
  color:${props=>props.theme.main}; //——》这里使用主题提供的属性
  border:2px solid ${props=>props.theme.main};
`

export default class xxx extends React.Component{
  render(){
    return(
      <div>
        <Button>Normal</Button>

        <ThemeProvider theme={theme}>
          <Button>Themed</Button>
        </ThemeProvider>
      </div>
    )
  }
}

Нажмите, чтобы увидеть официальный пример

На каштан мы настроилиthemeпредметный объект и передать этот объект<ThemeProvider>компонент, чтобы в любом дочернем компоненте, обернутом этим компонентом, мы могли получить этоthemeОбъекты (независимо от того, сколько уровней вложенности).

defaultProps

На самом деле в Shangli есть ошибка, то есть это не<ThemeProvider>завернутый<Button/>На самом деле нет объекта свойства props.theme, тогда он сообщит об ошибке.

Итак, на данный момент нам нужно установить значение по умолчанию для этого компонента кнопки.

...
// 设置默认属性,
Button.defaultProps = {
  theme:{
    main:'palevioletred'
  }
}

const theme = {
  main:'mediumseagreen'
}
...

Об объектах темы

На самом деле, в дополнение к определению объекта темы вне компонента и передаче<ThemeProvider theme={theme}>Помимо передачи, мы также можем определить объект темы непосредственно в StyledComponent.

...
const theme = {
  main: 'mediumseagreen'
};
...
<ThemeProvider theme={theme}>
  <div>
    <Button>Themed</Button>
    <Button theme={{ main: 'darkorange' }}>Overidden</Button>
  </div>
</ThemeProvider>
...

ThemeProvider, вложенный в тему Function

когдаThemeProviderПри вложенности свойство темы вложенного ThemeProvider может принимать не только объект, но и функцию, если это функция, то функция получит параметр, который получает предыдущий объект ThemeProvide.theme.

...
const theme = {
  fg:'palevioletred'
  ,bg:'white'
};
const invertTheme = ({fg,bg})=>({
  fg:bg
  ,bg:fg
})
...
<ThemeProvider theme={theme}>
    <div>         
      <ThemeProvider theme={invertTheme}>
        <Button>Themed</Button>
      </ThemeProvider>
    </div>
</ThemeProvider>
...

Нажмите, чтобы увидеть официальный пример

Получить тему в компоненте React

Если вы хотите получить тему в компонентах React, styled-compnents также предоставляет намwithThemeметод, после его упаковки мы можем получить props.theme в компоненте React

import { withTheme } from 'styled-components'

class MyComponent extends React.Component {
  render() {
    console.log('Current theme: ', this.props.theme);
    // ...
  }
}
export default withTheme(MyComponent)

Метод injectGlobal: вставка глобальных стилей

Во-первых, это дополнительный метод, предоставляемый styled-components.

import { injectGlobal } from 'styled-components';

injectGlobal`
  @font-face {
    font-family: 'Operator Mono';
    src: url('../fonts/Operator-Mono.ttf');
  }

  body {
    margin: 0;
  }
`;

Что ж, официальная рекомендация заключается в том, что вам лучше использовать его только для шрифта и тела.

метод ключевых кадров: использовать покадровую анимацию

часто иinterpolationиспользовать вместе

import styled, { keyframes } from 'styled-components';

const fadeIn = keyframes`
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
`;

const FadeInButton = styled.button`
  animation: 1s ${fadeIn} ease-out;
`;

Нажмите, чтобы увидеть официальный пример

разное

О рендеринге на стороне сервера

рендеринг на стороне сервера

О машинописном языке

Как использовать стилизованные компоненты в TypeScript

О ReactNative

На что следует обратить внимание при использовании стилизованных компонентов в ReactNative

Обновление для styledComponent

Если передается новое состояние и необходимо добавить новый cssText, он перейдет кstyleДобавьте cssText к тегу,

Обратите внимание, что добавление к нему не удалит предыдущий cssText в стиле. (Даже если текущий реквизит больше не соответствует условиям генерации предыдущего текста CSS, он не будет удален)


Ссылаться на