css的工程化

目录

CSS存在的问题

如何解决CSS存在的问题

BEM命名规范

css模块化

css-loader

style-loader


CSS存在的问题

一、类名冲突

当一个项目的模块和界面变动越来越丰富的时候,命名一个css类名难度越来越大,因为新的类名很可能会在其他模块存在,但是我们并没发现,这样的情况下,会导致css类名冲突,从而所写的样式会影响到其他模块。一般这样的情况下我们都会选择通过css选择器或者嵌套来选择元素,保证不会影响到其他模块,但是这样依然会有影响其他模块的风险,同时通过选择器和层级来选择的元素往往要写很长一段css选择的代码,这样很不容易阅读,并且难以维护和修改。

如下:index.css和block.css的.a 类名冲突

//index.css:

.a{}

.b{}

.b .c .d >.e{}


//block.css
.a{}

.b .e{}

二、样式或属性值重复难以维护

在一个网站里面,相同的样式和属性值是非常多的。如color和其色值,border的样式,在一个网站里复用的概率非常大。这些相同的样式如果要全部修改的话,需要修改多出地方,会变得如果非常难以维护。

如下,color和border重复很多,如要修改其中的颜色,要改很多个地方,非常麻烦。

body{
    background-color:#000
}

.a{
    color:#000
}

.b{
    border:1px solid #000
    color:#000
}

.c{
    border:1px solid #000
    background-color:#000
}

如何解决CSS存在的问题

一、解决类名冲突

方式一使用命名规范约束css类名,来保证css类名的唯一性。常见的命名标准有:OOCSS,ACSS,BEM,SMACSS等。

 

方式二:用js来为元素对象添加css样式。由于此方法是等同于在元素行内直接写style样式,取消了通过css类名来书写样式,从而避免了类名冲突。例如:

html:
<div class="oDiv"></div>

js:
var div = document.getElementsByClassName("oDiv")[0]

//添加样式
div.style.border = "1px solid black"

此方式的缺点

1.样式多的时候,会影响html代码阅读。因为通过js给元素对象添加样式,是添加在元素的行内,如果样式一多的话,会导致整个元素标签很长都是样式,不易阅读。

2.如果全部都用这种方式去书写css的话,要在页面修改样式也很不方便。

 

方式三:css模块化。此方式需要结合webpack和css-loader等工具配合。可以

在css中任意书写类名,当webpack构建css发现了类名冲突的时候,会对冲突的css类名进行转换,来保证css类名的唯一性。

 

二、解决样式或属性值重复难以维护

方案:使用CSS预编译工具

CSS预编译工具是社区团队对css语言问题的一种解决方案。它类似于编程语言:支持变量、函数等高级语法,可以对样式进行封装,优化选择元素。最后经过编译器将其代码编译成浏览器能识别的CSS代码。

常见的CSS预编译器:

  • less
  • sass

BEM命名规范

官方对BEM的原理:

BEM解决这一问题的思路在于,由于项目开发中,每个组件都是唯一无二的,其名字也是独一无二的,组件内部元素的名字都加上组件名,并用元素的名字作为选择器,自然组件内的样式就不会与组件外的样式冲突了。

这是通过组件名的唯一性来保证选择器的唯一性,从而保证样式不会污染到组件外。

这也可以看作是一种“硬性约束”,因为一般来说,我们的组件会放置在同一目录下,那么操作系统中,同一目录下文件名必须唯一,这一点也就确保了组件之间不会冲突。

BEM的命名规矩很容易记:block-name__element-name--modifier-name,也就是模块名 + 元素名 + 修饰器名。

如,在app/component/footer.html

<div class="footer">
    <div class="footer__content">
        <ul class="footer__parners">
            <li class="footer__parner-child"></li>
            <li class="footer__parner-child"></li>
            <li class="footer__parner-child footer__parner-child--active"></li>
        </ul>
    </div>
    <p class="footer__desc">xxx</p>
<div>

footer.css

.footer{margin:0;pading:0}

.footer__content{height:40px}

.footer__parners{float:left}

.footer__parner-child{marging:5px}

.footer__parner-child--active{backgorund-color:#000}

.footer__desc{font-weight:600}

更多细节参考BEM官网:https://www.bemcss.com/

 

css模块化

原理:webpack利用CSS-loader读取模块文件后,一旦发现CSS类名冲突,便会把冲突的CSS类名转换成唯一性的hash字符串(通过hash加密模块路径和类名),从而保证了CSS类名的唯一性。

css-loader

安装css-loader:

npm i css-loader -D

配置webpack.config.js中的loader

    module: {
        rules: [
          {
            test: /\.css$/i,
            use: [
                {
                    loader:'css-loader'
                },
            ],
          },
        ],
    },

案例:

./src/index.js:

import indexCss from './css/main.css'
import blockACss from './css/block-a.css'

console.log("indexCss",indexCss)
console.log("blockACss",blockACss)

./src/css/main.css:

body{
    background: yellow;
    font-size: 20px;
}
.a{
    color: red;
}

./src/css/block-a.css:

body{
    background-color: black;
}
.a{
    color: blue;
}

在浏览器运行打包后的./dist/main.js:

分析:

main.cssblock-a.css两个文件中.a 这个CSS类名冲突了,因此被转化hash字符串保证唯一性。

控制css-loader对类名的转换:

全局的、静态、不需要进行转换的类名,如下设置.base为全局,css-loader便不会对其转化:

:global(.base){
    ...
}

配置默认使用了local

:local(.base){
    ...
}

等于

.base{
    ...
}

案例:

./src/index.js:

import indexCss from './css/index.css'
import aCss from './css/a.css'

console.log("indexCss",indexCss)
console.log('aCss',aCss)

'./src/css/index.css'

:global(.base){
    background-color: red;
}

'./src/css/a.css'

:local(.base){
    background-color: red;
}

结果:

可以看出.base设置了:global没有被转化。

 

css-loader模块化使用注意项

  • css-loader会处理类名选择器和id,不处理其他选择器
  • 使用css-loader没必要使用其他命名规范
  • 使用css-loader尽量只使用顶级类名,不避免使用嵌套,容易阅读也方便webpack对代码的优化。

style-loader

如何应用转换后的CSS类到页面? 需要通过使用style-loader把转换后的css样式都写入到页面

安装style-loader

npm i style-loader -D

webpack.config.js中配置loader:

    module:{
        rules: [
            {
              test: /\.css$/i,
              use: [
                  "style-loader", 
                  {
                    loader:"css-loader", 
                    options:{
                        modules:true
                    }
                  }
                ],
            },
          ],
    }

案例:

./src/index.js:

import indexCss from './css/index.css'
import aCss from './css/a.css'

console.log("indexCss",indexCss)
console.log('aCss',aCss)

./src/css/index.css:

.tab{
    color:red;
    font-size: 16px;
}
.footer{
    padding: 0;
}

./src/css/a.css:

.tab{
    color: blue;
}
.top{
    margin: 0;
}

在浏览器运行打包后的./dist/main.js:

分析:

从以上打印输出的结果可以看出,对象中的键名就是我们所写的css名,而其键值就是hash转换后的Css类名。因此为dom元素添加对应类名,即可获得对应样式。

import indexCss from './css/index.css'
import aCss from './css/a.css'

console.log("indexCss",indexCss)
console.log('aCss',aCss)

//添加dom元素
var oTab = document.getElementById('#tab')
var oTop = document.getElementById('#top')
var oFooter = document.getElementsByName("#footer")
//添加class类名
oTab.className = aCss.tab
oTop.className = aCss.top
oFooter.className = indexCss.footer

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值