CSS-IN-JS

为什么会有 CSS-IN-JS

CSS-IN-JS 是 WEB 项⽬中将 CSS 代码捆绑在 JavaScript 代码中的解决⽅案.

这种⽅案旨在解决 CSS 的局限性, 例如缺乏动态功能, 作⽤域和可移植性.

CSS-IN-JS ⽅案的优点
  1. 让 CSS 代码拥有独⽴的作⽤域, 阻⽌ CSS 代码泄露到组件外部, 防⽌样式冲突

  2. 让组件更具可移植性, 实现开箱即⽤, 轻松创建松耦合的应⽤程序

  3. 让组件更具可重⽤性, 只需编写⼀次即可, 可以在任何地⽅运⾏. 不仅可以在同⼀应⽤程序中重⽤组件, ⽽且可以在使⽤相同框架构建的其他应⽤程序中重⽤组件

  4. 让样式具有动态功能, 可以将复杂的逻辑应⽤于样式规则, 如果要创建需要动态功能的复杂UI, 它是理想的解决⽅案.

CSS-IN-JS ⽅案的缺点
  1. 为项⽬增加了额外的复杂性

  2. ⾃动⽣成的选择器⼤⼤降低了代码的可读性

Emotion
Emotion 介绍

Emotion 是⼀个旨在使⽤ JavaScript 编写 CSS 样式的库.

npm install @emotion/core @emotion/styled

css 属性⽀持
  1. JSX Pragma

    通知 babel, 不再需要将 jsx 语法转换为 React.createElement ⽅法, ⽽是需要转换为 jsx ⽅法.

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-obiU15li-1613630115440)(images/image-20210218112813033.png)]

    React 17 引用

    /** @jsxRuntime classic */
    
    /** @jsx jsx */
    
    import { jsx } from '@emotion/react';
    

    React16 引用

    /** @jsx jsx */
    import { jsx } from '@emotion/core';
    
    Babel Preset
    1. npm run eject

    2. 安装babel依赖

      npm install @emotion/babel-preset-css-prop
      
    3. 在 package.json ⽂件中找到 babel 属性, 加⼊如下内容

       "babel": {
          "presets": [
            "react-app",
            "@emotion/babel-preset-css-prop"
          ]
        }
      
    css()方法
    1. String Styles

      模板字符串调用

      import React from 'react';
      import { css } from '@emotion/react'
      
      const style = css`
      width:100px;
      height:200px;
      background: skyblue`
      
      function App() {
        return (
          <div css={style}>react work!</div>
        );
      }
      
      export default App;
      
      

      普通函数调用

      import React from 'react';
      import { css } from '@emotion/react'
      
      const style = css({
        width:200,
        height: 200,
        background: 'pink'
      })
      
      function App() {
        return (
          <div css={style}>react work!</div>
        );
      }
      
      export default App;
      
      
    2. css属性优先级

      props 对象中的 css 属性优先级⾼于组件内部的 css 属性

      在调⽤组件时可以在覆盖组件默认样式

    3. Styled Components 样式化组件

      样式化组件就是⽤来构建⽤户界⾯的,是 emotion 库提供的另⼀种为元素添加样式的⽅式。

      • 创建样式化组件

        import styled from '@emotion/styled'
        

        string styles

        const Button = styled.button`
        width: 100px;
        height: 30px;
        background: pink;
        `;
        

        Object styles

        const Container = styled.div({
          width: 1000,
          background: 'pink',
          margin: '0 auto'
        });
        
      • 根据props属性覆盖样式

        String styles

        const Button = styled.button`
        width: 100px;
        height: 30px;
        background: ${props => props.bgColor || 'pink'};
        `;
        

        Object styles

        (1)

        const Container = styled.div(props=>({
          width: props.w || 1000,
          background: 'pink',
          margin: '0 auto'
        }));
        

        (2)

        const Container = styled.div({
          width:800,
          background: 'pink'
        },props=>({
          width: props.w,
          background: props.bgColor
        }))
        
      • 为任何组件添加样式

        string styles

        function Demo ({className}) {
          return <div className={className}>Demo</div>;
        }
        
        const Fancy = styled(Demo)`
        color: red;
        `
        

        Object styles

        const Fancy2 = styled(Demo)({
          background: 'tomato',
          color: 'white'
        })
        
      • 通过父组件设置组件样式

        String styles

        import React from 'react';
        import styled from '@emotion/styled'
        
        const Child = styled.div`
          color: red;
        `;
        
        const Parent = styled.div`
        ${Child} {
          color: green
        }`;
        function App() {
          return (
           <div>
            <Child>Child</Child>
            <Parent><Child>child parent</Child></Parent>
            </div>
          );
        }
        
        export default App;
        
        

        Object Styles

        import React from 'react';
        import styled from '@emotion/styled'
        
        const Child = styled.div({
          color: 'red'
        })
        
        const Parent = styled.div({
          [Child]: {
            color: 'pink'
          }
        })
        
        function App() {
          return (
           <div>
            <Child>Child</Child>
            <Parent><Child>child parent</Child></Parent>
            </div>
          );
        }
        
        export default App;
        
        
      • 嵌套选择器 &

      & 表示组件本身.

      const Container = styled.div`
      width: 200px;
      height: 200px;
      background: skyblue;
      color: pink;
      &:hover {
        background: pink;
      }
      & > span {
        color: yellow;
      }
      `;
      
      • as 属性

        要使⽤组件中的样式, 但要更改呈现的元素, 可以使⽤ as 属性.

        import React from 'react';
        import styled from '@emotion/styled'
        
        const Button = styled.button`
        color:red;
        `;
        
        function App() {
          return (
           <div>
          <Button as="a" href="#">button</Button>
            </div>
          );
        }
        
        export default App;
        
        
      • 样式组合

        在样式组合中,后调用的样式优先级高于先调用的样式。

        import React from 'react';
        import { css } from '@emotion/react'
        
        const base =css`
        background: tomato;
        color: white;
        `;
        const danger =css`
        background: red;
        color: black;
        `;
        function App() {
          return (
           <div css={[base, danger]}>
           我的测试数据。。。。
            </div>
          );
        }
        
        export default App;
        
        
      • 全局样式

        import React from 'react';
        import { css, Global } from '@emotion/react'
        import Demo from './demo';
        
        const styles = css`
        body {
          margin: 0;
        }
        a {
          text-decoration: none;
          color: red;
        }
        `;
        function App() {
          return (
           <div>
             <Global styles={styles} />
           <a href="#">我的测试数据。。。。</a>
           <Demo />
            </div>
          );
        }
        
        export default App;
        
        
      • 关键帧动画

        import React from 'react';
        import { css, keyframes } from '@emotion/react';
        
        const move = keyframes`
        0% {
          background: skyblue;
          left: 0;
          top: 0;
        }
        100% {
          background: tomato;
          left: 600px;
          top: 300px;
        }
        `;
        
        const box =css`
        width: 100px;
        height: 100px;
        position: absolute;
        animation: ${move} 2s ease alternate;
        `;
        function App() {
          return (
           <div css={box}>
            </div>
          );
        }
        
        export default App;
        
        
      • 主题

        将 ThemeProvider 放置在视图在最外层

        react17之前 用emotion-theming

        npm install emotion-theming
        

        react17之后引用

        import { useTheme, ThemeProvider, withTheme } from '@emotion/react'
        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值