
# CSS 在 React 和 Vue 中的应用
# Vue 中使用 CSS 方案
# Vue 自带的Scoped CSS
加上 scoped 属性的style会自动添加一个唯一的属性 。比如 data-v-0767f757 为组件内 CSS 指定作用域,编译的时候 .isShow 会被编译成类似 .isShow[data-v-0767f757]
<style lang="css" scoped>  
  .isShow{ 
			background:red;
  }
</style>
2
3
4
5
缺点:.errShow[data-v-0467f817]并不能保证是唯一的,另外在性能上也不是很好
# CSS modules
需要同时使用 webpack 的 Vue Loader
CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统。vue-loader 提供了与 CSS Modules 的一流集成,可以作为模拟 scoped CSS 的替代方案。
// webpack.config.js
{
  module: {
    rules: [
      // ... 其它规则省略
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              // 开启 CSS Modules
              modules: true,
              // 自定义生成的类名
              localIdentName: '[local]_[hash:base64:8]'
            }
          }
        ]
      }
    ]
  }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
构建步骤中对CSS类名选择器限定作用域的一种方式(通过hash实现类似于命名空间的方法)。类名是动态生成的,唯一的,并准确对应到源文件中的各个类的样式
<template>
  <p :class="$style.red">
    This should be red
  </p>
</template>
<style module>
.red {
  color: red;
}
.bold {
  font-weight: bold;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
用法
- 在style标签中添加module属性,表示打开CSS-loader的模块模式。
- 在模板中使用动态类绑定:class,并在类名前面加上'$style.'。
- 如果类名包含中划线,则使用中括号语法$style['header-tit'] 也可以使用数组或对象语法。
# React 中使用CSS 方案
# CSS module
CSS Modules 通过webpack配置引入项目,不依赖于任何框架,只要使用webpack配置后就可以用于React/Vue/Angular/jQuery 项目中.
- 在webpack.config.js的module中添加如下配置:
module.exports = {
  entry: __dirname + '/index.js',
  output: {
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    rules:[
  {
    test:/.css$/,
    use:[
      {loader:'style-loader'},
      {loader:'css-loader',
        option:{modules:true,localIdentName:'[path][name]__[local]-[hase:base64:5]'}
        ]
  }
]
  }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
上面代码中,关键的是在css-loader的option里配置option:{modules:true},表示打开 CSS Modules 功能。
/* components/submit-button.js */
import React, { Component } from 'react';
import classNames from 'classnames';
// 重点
import styles from './submit-button.css';
export default class SubmitButton extends Component {
render () {
  let text = this.props.store.submissionInProgress ? 'Processing...' : 'Submit';
  let className = classNames({
    [`${styles.base}`]: true,
    [`${styles.inProgress}`]: this.props.store.submissionInProgress,
    [`${styles.error}`]: this.props.store.errorOccurred,
    [`${styles.disabled}`]: this.props.form.valid,
  });
  return <button className={className}>{text}</button>;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
详细查看:https://github.com/jd-smart-fe/shared/issues/11
# CSS-in-JS
以 styled components 方案为例
安装
npm install --save styled-components
使用
import styled from 'styled-components';
export default class SubmitButton extends Component {
// 给标签加样式
const Button = styled.button`
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;
// 给组件加样式,覆盖原来的部分样式
const TomatoButton = styled(Button)`
  color: tomato;
  border-color: tomato;
`;
render(){
  return (
    <div>
      <Button>Normal Button</Button>
      <TomatoButton>Tomato Button</TomatoButton>
    </div>
)};
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Atomic CSS 原子化 CSS
原子 CSS 就像是实用工具优先(utility-first)CSS 的一个极端版本: 所有 CSS 类都有一个唯一的 CSS 规则。
/* 原子 CSS */
.bw-2x {
  border-width: 2px;
}
.bss {
  border-style: solid;
}
.sans {
  font-style: sans-serif;
}
.p-1x {
  padding: 10px;
}
/* 不是原子 CSS 因为这个类包含了两个规则 */
.p-1x-sans {
  padding: 10px;
  font-style: sans-serif;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Tailwind 使用的方法是非常便捷的,并且解决了上述一些问题。
以 Tailwindcss 为例它通过 Utility-First 的理念来解决 CSS 的一些缺点,通过抽象出一组类名 -> 原子功能的集合,来避免你为每个 div 都写一个专有的 class,然后整个网站重复写很多重复的样式。
它提供了一些公用的命名约定。通过一个配置文件,你可以为你的网站生成一套专属的实用工具 CSS
// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'sm': '640px',
      // => @media (min-width: 640px) { ... }
      'md': '768px',
      // => @media (min-width: 768px) { ... }
      'lg': '1024px',
      // => @media (min-width: 1024px) { ... }
      'xl': '1280px',
      // => @media (min-width: 1280px) { ... }
    }
  }
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
