CSS in JS 简介

yeyun0995 2年前
   <p>1、以前,网页开发有一个原则,叫做 "关注点分离" (separation of concerns)。</p>    <p><img src="https://simg.open-open.com/show/5a957c2cccd5d5da6b0c47c9c14276a8.jpg"></p>    <p>它的意思是,各种技术只负责自己的领域,不要混合在一起,形成耦合。对于网页开发来说,主要是三种技术分离。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/11ff0bf1fcab52693cc0d2f76cdd9b3b.jpg"></p>    <ul>     <li>HTML 语言:负责网页的结构,又称语义层</li>     <li>CSS 语言:负责网页的样式,又称视觉层</li>     <li>JavaScript 语言:负责网页的逻辑和交互,又称逻辑层或交互层</li>    </ul>    <p>简单说,就是一句话,不要写"行内样式"(inline style)和"行内脚本"(inline script)。比如,下面代码就很糟糕(查看 <a href="/misc/goto?guid=4959746620131924272" rel="nofollow,noindex">完整代码</a> )。</p>    <pre>  <code class="language-css"><h1 style="color:red;font-size:46px;"  onclick="alert('Hi')">    Hello World  </h1></code></pre>    <p>2、React 出现以后,这个原则不再适用了。因为,React 是组件结构,强制要求把 HTML、CSS、JavaScript 写在一起。</p>    <p>上面的例子使用 React 改写如下(查看 <a href="/misc/goto?guid=4959746620217935041" rel="nofollow,noindex">完整代码</a> )。</p>    <pre>  <code class="language-css">const style = {    'color': 'red',    'fontSize': '46px'  };    const clickHandler = () => alert('hi');     ReactDOM.render(    <h1 style={style} onclick={clickHandler}>       Hello, world!    </h1>,    document.getElementById('example')  );</code></pre>    <p>上面代码在一个文件里面,封装了结构、样式和逻辑,完全违背了"关注点分离"的原则,很多人不适应。</p>    <p>但是,这有利于组件的隔离。每个组件包含了所有需要用到的代码,不依赖外部,组件之间没有耦合,很方便复用。所以,随着 React 的走红和组件模式深入人心,这种"关注点混合"的新写法逐渐成为主流。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/cdfa87aa5215aaac1911ab1adf76c465.png"></p>    <p>3、表面上,React 的写法是 HTML、CSS、JavaScript 混合在一起。但是,实际上不是。现在其实是用 JavaScript 在写 HTML 和 CSS。</p>    <p>React 在 JavaScript 里面实现了对 HTML 和 CSS 的封装,我们通过封装去操作 HTML 和 CSS。也就是说,网页的结构和样式都通过 JavaScript 操作。</p>    <p>4、React 对 HTML 的封装是 JSX 语言 ,这个在各种 React 教程都有详细介绍,本文不再涉及了,下面来看 React 对 CSS 的封装。</p>    <p>React 对 CSS 封装非常简单,就是沿用了 DOM 的 style 属性对象 ,这个在前面已经看到过了。</p>    <pre>  <code class="language-css">const style = {    'color': 'red',    'fontSize': '46px'  };</code></pre>    <p>上面代码中,CSS 的 font-size 属性要写成 fontSize ,这是 JavaScript 操作 CSS 属性的 约定 。</p>    <p>由于 CSS 的封装非常弱,导致了一系列的第三方库,用来加强 React 的 CSS 操作。它们统称为 CSS in JS,意思就是使用 JS 语言写 CSS。根据不完全统计,各种 CSS in JS 的库至少有 47种 。老实说,现在也看不出来,哪一个库会变成主流。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/cafad305358d8aa3e45e79b73975ad0b.jpg"></p>    <p>你可能会问,它们与"CSS 预处理器"(比如 Less 和Sass,包括 PostCSS)有什么区别?回答是 CSS in JS 使用 JavaScript 的语法,是 JavaScript 脚本的一部分,不用从头学习一套专用的 API,也不会多一道编译步骤。</p>    <p>5、上周,我看到一个新的 CSS in JS 库,叫做 polished.js 。它将一些常用的 CSS 属性封装成函数,用起来非常方便,充分体现使用 JavaScript 语言写 CSS 的优势。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c5555a1403fdcb412f4061cd236cdfcd.png"></p>    <p>我觉得这个库很值得推荐,这篇文章的主要目的,就是想从这个库来看怎么使用 CSS in JS。</p>    <p>首先,加载 polished.js。</p>    <pre>  <code class="language-css">const polished = require('polished');</code></pre>    <p>如果是浏览器,插入下面的脚本。</p>    <pre>  <code class="language-css"><script src="https://unpkg.com/polished@1.0.0/dist/polished.min.js">  </script></code></pre>    <p>polished.js 目前有50多个方法,比如 clearfix 方法用来清理浮动。</p>    <pre>  <code class="language-css">const styles = {    ...polished.clearFix(),  };</code></pre>    <p>上面代码中, clearFix 就是一个普通的 JavaScript 函数,返回一个对象。</p>    <pre>  <code class="language-css">polished.clearFix()  // {  //  &::after: {  //    clear: "both",  //    content: "",  //    display: "table"  //  }  // }</code></pre>    <p>"展开运算符"( ... )将 clearFix 返回的对象展开,便于与其他 CSS 属性混合。然后,将样式对象赋给 React 组件的 style 属性,这个组件就能清理浮动了。</p>    <pre>  <code class="language-css">ReactDOM.render(    <h1 style={style}>Hello, React!</h1>,    document.getElementById('example')  );</code></pre>    <p>从这个例子,大家应该能够体会 polished.js 的用法。</p>    <p>6、</p>    <p>下面再看几个很有用的函数。</p>    <p>ellipsis 将超过指定长度的文本,使用省略号替代(查看 <a href="/misc/goto?guid=4959746620305826018" rel="nofollow,noindex">完整代码</a> )。</p>    <pre>  <code class="language-css">const styles = {    ...polished.ellipsis('200px')  }    // 返回值  // {  //   'display': 'inline-block',  //   'max-width': '250px',  //   'overflow': 'hidden',  //   'text-overflow': 'ellipsis',  //   'white-space': 'nowrap',  //   'word-wrap': 'normal'  // }</code></pre>    <p>hideText 用于隐藏文本,显示图片。</p>    <pre>  <code class="language-css">const styles = {    'background-image': 'url(logo.png)',    ...polished.hideText(),  };    // 返回值  // {    'background-image': 'url(logo.png)',    'text-indent': '101%',    'overflow': 'hidden',    'white-space': 'nowrap',  }</code></pre>    <p>hiDPI 指定高分屏样式。</p>    <pre>  <code class="language-css">const styles = {   [polished.hiDPI(1.5)]: {     width: '200px',   }  };    // 返回值  //'@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  // only screen and (min--moz-device-pixel-ratio: 1.5),  // only screen and (-o-min-device-pixel-ratio: 1.5/1),  // only screen and (min-resolution: 144dpi),  // only screen and (min-resolution: 1.5dppx)': {  //  'width': '200px',  //}</code></pre>    <p>retinaImage 为高分屏和低分屏设置不同的背景图。</p>    <pre>  <code class="language-css">const styles = {   ...polished.retinaImage('my-img')  };    // 返回值  //   backgroundImage: 'url(my-img.png)',  //  '@media only screen and (-webkit-min-device-pixel-ratio: 1.3),  //   only screen and (min--moz-device-pixel-ratio: 1.3),  //   only screen and (-o-min-device-pixel-ratio: 1.3/1),  //   only screen and (min-resolution: 144dpi),  //   only screen and (min-resolution: 1.5dppx)': {  //    backgroundImage: 'url(my-img_2x.png)',  //  }</code></pre>    <p>7、polished.js 提供的其他方法如下 。</p>    <ul>     <li>normalize() :样式表初始化</li>     <li>placeholder() :对 placeholder 伪元素设置样式</li>     <li>selection() :对 selection 伪元素设置样式</li>     <li>darken() :调节颜色深浅</li>     <li>lighten() :调节颜色深浅</li>     <li>desaturate() :降低颜色的饱和度</li>     <li>saturate() :增加颜色的饱和度</li>     <li>opacify() :调节透明度</li>     <li>complement() :返回互补色</li>     <li>grayscale() :将一个颜色转为灰度</li>     <li>rgb() :指定红、绿、蓝三个值,返回一个颜色</li>     <li>rgba() :指定红、绿、蓝和透明度四个值,返回一个颜色</li>     <li>hsl() :指定色调、饱和度和亮度三个值,返回一个颜色</li>     <li>hsla() :指定色调、饱和度、亮度和透明度三个值,返回一个颜色</li>     <li>mix() :混合两种颜色</li>     <li>em() :将像素转为 em</li>     <li>rem() :将像素转为 rem</li>    </ul>    <p>目前, polished.js 只是1.0版,以后应该会有越来越多的方法。</p>    <p>8、polished.js 还有一个特色:所有函数默认都是柯里化的,因此可以进行函数组合运算,定制出自己想要的函数。</p>    <pre>  <code class="language-css">import { compose } from 'ramda';  import { lighten, desaturate } from 'polished';    const tone = compose(lighten(10), desaturate(10))</code></pre>    <p>上面代码使用 Ramda 函数库完成组合运算。Ramda 的用法可以参考我写的教程。</p>    <p> </p>    <p> </p>    <p>来自:http://www.ruanyifeng.com/blog/2017/04/css_in_js.html</p>    <p> </p>