使用BEM+css module+classnames/bind来写优雅的css

1,608 阅读1分钟

如何编写优雅的css,我采用的方案是BEM+css module+classnames/bind,下面我们在react组件里面写个todo的例子:

import React from 'react';
import classnames from 'classnames/bind';
import styles from './app.less';

const cx = classnames.bind(styles);

// app.jsx
export default function App(){
    return (
    <div className={cx('todo')}>
        <header className={cx('todo__header')}>this is a header</header>
        <main>
            <ul className={cx('todo__list')}>
            	<li className={cx('todo__list__item')}>to do item</li>
            	<li className={cx('todo__list__item--active')}>to do item in active</li>
            </ul>
        </main>
    </div>
    )
}
// app.less
.todo{
    &__header{
        font-weight:bold;
    }
    &__list{
        font-size:12px;
        &__item{
            color:#666;
            &--active{
                color:red;
            }
        }
    }
}

问题环节

  • Q: 这里为什么要采用classnames/bind? A: cx('todo')对比styles.todocx('todo__list__item--active')对比styles['todo__list__item--active'],使用cx的方法会简短和优雅许多。同时,如果不安装特殊插件的话,styles.todo会被编辑器识别成变量,在代码高亮上会对组件的状态变量造成视觉上的干扰,cx则不会有这个问题。 cx函数其实没有任何魔法,我们也可以自己简单写一个: function myBind(styles){ return function cx(className){ return styles[className] } }
  • Q: 为什么这里要采用BEM? A: 一个是BEM对于团队协作本身的重要意义,可以提高className的可读性,通过className即可知道组件的层次和状态等信息。另一个是性能优化,app.less里面编译出来的都是单个className,通过尽量减少className 的嵌套来优化css性能。
  • Q: less写法上有什么特点: A: 结合BEM的话,要大量利用&字符来简化样式代码,这样可以让样式代码更优雅、层次更明确。