<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                - 初體驗 - styled方法:將React組件包裝成Styled組件 - ()的三種情況 - tagged template literal - interpolations 插值表達式 - mixin - StyledComponent相關特性 - extend 繼承 - withComponent - component-selector - innerRef - isStyledComponent - attr方法:給Styled組件添加默認屬性 - 主題組件 - defaultProps - 關于theme對象 - ThemeProvider嵌套與Function theme - 在React組件中獲取theme - injectGlobal方法:插入全局樣式 - keyframes方法:使用幀動畫 - 其它 [TOC] ## pre-notify >previously: - [JSX,了解一下?](https://juejin.im/post/5ab065716fb9a028c5230164) - [React文檔精讀(上篇)](https://juejin.im/post/5ab20d67f265da237c68c949) 在越來越組件化開發的今天,我們通過`JSX`已經將js好html/xml很好的柔和在了一起,那么css呢? 雖然在vue這樣的框架里我們能在`.vue`文件里將css、js、html寫在一起,但實際上它們的聯系很弱,特別是js和css,它們完全無法溝通。 而`styled-components`很好的解決了這個問題,通過它,我們能讓整個css架構跟著組件走,而不再僅僅是貌合神離的被放置在一個文件中。可以這么說,styled-components讓一個組件變得更加得完整,更加得像一個組件! ## 初體驗 `styled-compnents`,正如其名,就是有樣式的`react-component`,是對react組件的再封裝,它不僅可以往`<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/>`,并且它還會往原本的React組件中傳遞一個`className`屬性,這個屬性的值是一串hash值(防止命名沖突),我們需要**將它放置到它應該被放置的元素身上**。 通過`styled()`,我們已經將一個React組件包裝成了一個Styled組件并導出,接下來我們去渲染這個導出的組件 ``` import React from 'react'; import ReactDOM from 'react-dom'; import StyledComponent from './test.js'; ReactDOM.render( <StyledComponent fontSize='30px'/> ,window.root ) ``` 渲染結果長這樣: ![](https://box.kancloud.cn/ad1611df2ad5ebff5d9b2b9c2ebea0f1_484x205.png) 可以發現,在使用上,一個StyledComponent和ReactComponent完全木有區別,emmm,應該說還是有一點的,我們能過給一個組件傳遞屬性來控制該組件的css樣式,So,StyledComponent其實是ReactComponent的超集。 嗯,是不是有那么一點興趣了耶,接下來讓我們一起更加深入的學習`style-components`吧! ## styled方法:將React組件包裝成Styled組件 上栗中我們已經知道了styled能干什么,這一回讓我們來完整的分析下這個API。 首先它的格式是這樣的 ``` const StyledCompoent = styled()`` ``` 它接收兩次傳參(這其實是es6中的標簽函數的寫法,這里不再展開),并最終返回一個包裝后的React組件,即具有樣式的React組件。 ### ()的三種情況 `()`可以接收一個`React-Component`也可以接收一個`tagName`。 上栗子中我們演示了第一種情況,So,其實它還能接收一個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 emmm...這貨怎么翻譯?標簽模板字符串?帶有標簽的模板字面量? 不管啦~反正就是指括號(`()`)后的 **\`\`** 里的內容。 在經過`styled()`后,我們已經確保將一個**有效的**react組件初始化為了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; } `; ``` 以上示例出自官方文檔,可見它無鴨梨支持:嵌套、**前綴自動補全**、各類選擇器、媒體查詢... #### interpolations 插值表達式 除此之外,Of Course,它也支持變量,并且有兩種可選 ``` 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組件初始化時包裝而成的props對象)作為參數。 哎嘿,還有種可能,${}也能接收一個css對象,like this ``` ... ${{ position:'absolute' ,left:'100px' ,top:'100px' }} ... ``` #### mixin styled-components中也允許我們使用像sass中@mixin一樣的東東 ``` 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-components中的另外一個方法`css`,這個方法其實就是創建一個`mixin`,使我們可以在任何`<StyledComponent>`中復用這份樣式。 需要注意的是, `props`屬性可以**透傳**給`mixin`使其在內部使用(要不我們怎么說這貨是一個mixin呢) 最終的渲染結果長這樣 ![](https://box.kancloud.cn/fd27757a1c87b24d36e103805e462eff_216x299.png) ## StyledComponent相關特性 通過上節中的`styled()`方法能將一個react組件包裝成一個具有樣式的react組件,我們將它稱之為`StyledComponent`,它除了在樣式上和組件強耦合外,還具有一些它獨有的特性。 ### extend 繼承 前面我們說過,我們能通過`styled(StyledCompoent1)`一個StyleComponent來創建一個繼承自StyledCompoent1的StyledComponent2組件。 ``` let StyledCompoent2 = styled(StyledCompoent1)` color:xxx ... ` ``` 但這樣繼承內部其實是一個**工廠模式**,StyledComponent2其實是一個全新的class。 如果我們想要做到**真正的繼承**,需要使用style-components提供的`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`。 ![](https://box.kancloud.cn/698fa4c9e641e6841ca56df3e4142743_610x142.png) > **注意:** 依然需要手動定位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 ) ``` ![](https://box.kancloud.cn/076e999d96beddedaed32359ffc6fd75_197x158.png) ### innerRef 在styled-components中,我們要想獲取到一個StyledComponent的真實入口DOM,需要使用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()} /> ); } } ``` [點我查看官方示例](https://www.styled-components.com/docs/advanced#refs) 上栗中使用的是`styled.input`這種快捷創建styledComponent的方式, 如果我們改成使用`styled(原生React組件)`的方式,那么像上面那樣我們是無法獲取到dom的,獲取的是`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>; } } ``` ![](https://box.kancloud.cn/629f5489f59915553028fc2cbeb49af0_701x245.png) (獲取到的不是dom,而是styled包裹之前的組件對象) 解決辦法是在`_B`內再使用原生的`ref`掛載一次,把dom掛載在`_B`上,這樣我們就可以通過往下再深一層訪問的方式拿到dom。 ### 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> ) } } ``` 最終的渲染結果長這樣 ![](https://box.kancloud.cn/13c2d9dd03b5e3359d6abf0150d1a85a_538x279.png) ## 主題組件 通過styled-components為我們提供的`ThemeProvider`組件(沒錯,是一個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> ) } } ``` [點我查看官方示例](https://www.styled-components.com/docs/advanced#theming) 上栗中,我們定制了一個`theme`主題對象,并將這個對象傳遞給`<ThemeProvider>`組件,這樣在被這個組件包裹的任何子組件中我們就能獲取到這個`theme`對象(無論嵌套多少層)。 ### defaultProps 在上栗中其實有一個bug,那就是沒有被`<ThemeProvider>`包裹住的`<Button/>`其實是沒有props.theme屬性對象的,那么它就會報錯。 So,這個時候我們需要給這個Button組件設置一個默認值 ``` ... // 設置默認屬性, Button.defaultProps = { theme:{ main:'palevioletred' } } const theme = { main:'mediumseagreen' } ... ``` ### 關于theme對象 其實我們除了在組件外部定義一個theme對象,并通過`<ThemeProvider theme={theme}>`來傳遞外,我們也可以直接在一個StyledComponent上定義theme對象 ``` ... const theme = { main: 'mediumseagreen' }; ... <ThemeProvider theme={theme}> <div> <Button>Themed</Button> <Button theme={{ main: 'darkorange' }}>Overidden</Button> </div> </ThemeProvider> ... ``` ### ThemeProvider嵌套與Function theme 當`ThemeProvider`嵌套時,被嵌套的當ThemeProvider的theme屬性此時不僅可以接收一個對象也可以接收一個函數,如果是個函數,那么這個函數會接受到一個參數,這個參數則是上一級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> ... ``` [點擊查看官方示例](https://www.styled-components.com/docs/advanced#function-themes) ### 在React組件中獲取theme 如果你想要在React組件中獲取theme,styled-compnents也為我們提供了一個`withTheme`的方法,經過它包裝后,我們就能在一個React組件中獲取到props.theme ``` 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; } `; ``` 嗯,官方推薦你最好只在font-face和body方面使用它。 ## keyframes方法:使用幀動畫 往往和`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; `; ``` [點我查看官方示例](https://www.styled-components.com/docs/basics#animations) ## 其它 ### 關于服務端渲染 > [服務端渲染](https://www.styled-components.com/docs/advanced#server-side-rendering) ### 關于TypeScript > [如何在TypeScript中使用styled-components](https://www.styled-components.com/docs/api#typescript) ### 關于ReactNative > [在ReactNative中使用styled-components需要注意的事情](https://www.styled-components.com/docs/basics#react-native) ### 關于styledComponent的更新 如果有一個新的狀態傳入導致需要添加新的cssText,那么會往`style`標簽中追加cssText, 注意是往里追加,并不會刪除style里之前的cssText。(即使當前的props已經不滿足之前css文本的生成條件也不會刪除) ![](https://box.kancloud.cn/b71027f935849364fcac5c8cc07ab426_675x387.png) ### 關于className 給一個styled-component直接添加一個`className`,那么這個className也會作為`props.className`中的一員,且作為第一個classname而存在(優先于 兩個有styled-component隨即生成的類名) ![](https://box.kancloud.cn/2eb654b89485e465d4db1edf5368ee7b_500x313.png) ### 關于css屬性 如果你在一個組件的 ``` styled` width:2px; ` ``` 中設置了一個css屬性,比如像上面這樣 然后,如果個組件的入口元素也是一個Styled組件,并且給這個組件設置一個同樣的css屬性 ``` width:5px; ``` 那么此時2px會生效而不是5px ![](https://box.kancloud.cn/624b25aa61d43cb24a8959b09ccb5f7a_319x108.png) 因為css解析是按照類名的 從右往左解析 故若兩個類名之間存在同名屬性,取左邊的那個 --- 參考 - [www.styled-components.com](https://www.styled-components.com/)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看