这周的主要的工做就是搭建新工程的架子,项目基于vue-cli构建。基本的功能在脚手架里都已经具有,可是仍是须要针对具体的业务场景来作一些定制。css
以如今先后端分离的开发模式来说,一个正常的开发流程大概是这样:前端
这样前端能够不用等后端接口彻底写完才能够开发,先后端并行开发,提升团队效率。vue
而脚手架提供的功能只有一个proxy,不能知足咱们的需求。因此须要咱们本身写一个mock-middleware
。大概是这样的一个功能,就不贴mock-middleware
的代码了:webpack
module.exports = () => {
const argv = Array.prototype.slice.call(process.argv, 2);
const proxyAddress = argv[0];
if (!argv.length || proxyAddress === 'mock') {
return mockMiddleware;
} else {
return proxyMiddleware(proxyAddress);
}
}复制代码
最终的效果就是运行 npm run dev mock
,会将api请求(注意:这里只会代理api请求,而不代理静态资源)转发到mock数据。在先后端开发完成以后,能够运行npm run dev {proxy_ip}
将api请求代理到某台开发服务器进行联调。git
固然这篇文章的重点不是这个,而是想总结下在SPA应用里如何规范的写CSS。github
故事的起点从组件库的选择提及,项目选择了开源的element 做为组件库。而这套组件库并不符合考拉前端组的视觉规范,而目前也没有计划fork一条分支来维护,因而就采起了比较简单粗暴的作法,样式覆盖。先来看一段element中的样式:web
@component-namespace el {
@b progress {
position: relative;
line-height: 1;
@e text {
font-size:14px;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
line-height: 1;
}
@m circle {
display: inline-block;
}
}
}复制代码
可能有同窗在刚看到这段样式的时候会有点蒙,可是仔细看@b,@e,@m,不就是bem规范么。vue-cli
关于BEM规范,网上有不少文章介绍。知乎上也有一篇文章来讨论其优劣,这里不去讨论BEM规范的好处和坏处,我以为只要在一个工程里约定好一种规范并严格执行,这样老是不会错的。npm
一方面为了和组件库的CSS规范保持统一,另外一方面我我的以为BEM的优势仍是大于缺点,所以在项目里也准备按照这个规范来写。gulp
那么问题来了,浏览器是不认识上面这些@b,@e,@m的语法的,这个时候就须要postcss来帮忙了。
postcss和gulp,webpack等工具同样,他自己并非一种预处理器或者后处理器,而是经过各类插件来完成转换(好比很流行的Autoprefixer就是它的一个插件)。
postcss-salad能够认为是一个postcss插件的集合,支持最新的css语法,一些sass嵌套的语法以及bem转化。这时候先来一份配置文件postcss.config.js
:
module.exports = {
plugins: [
require('postcss-salad')({
browsers: ['ie > 9', 'last 2 versions'],
features: {
bem: {
shortcuts: {
component: 'b',
descendent: 'e',
modifier: 'm'
},
separators: {
descendent: '__',
modifier: '--'
}
}
}
})
]
}复制代码
bem之间的链接符能够自定义,这边是为了和element的组件保持一致。这时候咱们能够先经过postcss-cli这个工具来看一下效果。咱们就用上述那段css来用postcss+postcss-salad进行转换,获得结果以下:
.el-progress {
position: relative;
line-height: 1
}
.el-progress__text {
font-size: 14px;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
line-height: 1
}
.el-progress--circle {
display: inline-block
}复制代码
已经达到了咱们预想的效果,那么接下来要想在webpack中使用postcss确定会须要一个loader,也就是postcss-loader。
而后将刚才的postcss.config.js做为postcss-loader的配置文件导入。
{
loader: 'postcss-loader',
options: {
config: {
path: 'path/to/postcss.config.js'
}
}
}复制代码
至此,就能够在webpack项目中,用这种嵌套的bem语法来进行css的书写了。
故事尚未结束,你们都知道在写单页面应用的时候,一个常见的需求是但愿组件间的css做用域是互相隔离的。这时候第一反应想到就是Scoped CSS,vue-loader也是支持Scoped CSS的(实际上对CSS进行转换的仍是postcss)。那么Scoped CSS是如何来处理这个问题的呢:
<style scoped>
.example {
color: red;
}
</style>
=>
<style>
.example[_v-f3f3eg9] {
color: red;
}
</style>复制代码
能够看到Scoped CSS会在class后面加上一段hash,从而来实现CSS做用域的隔离,可是在实践过程当中,会发现几个问题:
这时候就须要CSS Modules出场了,CSS Modules是目前CSS模块化方案中被接受度较高的一种方案,网上也有不少的文章去介绍它。一样的,咱们须要先看下CSS Modules能作什么事情呢?
刚才讲到,postcss有不少的插件,那么确定也会有CSS Modules的插件了。咱们一样经过以前的postcss-cli来进行测试,首先配置上这个插件:
require('postcss-modules')({
generateScopedName: '[local]--[hash:base64:5]'
})复制代码
这里的[local]表明类名,[hash:base64:5]按照给定规则生成的hash值,还能够用的变量有[name]表明标签名,[path]表明路径等
CSS Modules 生成的class能够自定义规则,所以也能够用自定义的规则,而不用bem规范,能够看项目的具体状况来定
仍是一样那段css代码,看下转换的结果:
.el-progress--3tuDF {
position: relative;
line-height: 1
}
.el-progress__text--1W8n3 {
font-size: 14px;
display: inline-block;
vertical-align: middle;
margin-left: 10px;
line-height: 1
}
.el-progress--circle--3OD0E {
display: inline-block
}复制代码
跟咱们预设的样式规则一致,这样就能够解决上述的第一个问题,作到每一个组件内的样式是惟一的。
可是咱们发现CSS Modules一样会改变class,那么也一样没法在组件内覆盖element组件的全局样式,这时候能够用CSS Modules的全局样式写法,:global{.class}
:
:global(.el-progress) {
position: relative;
line-height: 1;
}
=>
.el-progress {
position: relative;
line-height: 1;
}复制代码
这样就不会在class上加上hash后缀,从而能够达到覆盖全局样式的目的。
首先在Vue-loader的配置文件中配置生成class规则:
cssModules: {
localIdentName: '[local]--[hash:base64:5]',
camelCase: true
}复制代码
而后在组件内经过在style上添加module打开CSS Modules。
<style module>
</style>复制代码
css-loader 会将一个 $style
对象注入到当前组件。因此在实际中使用大概是这个样子:
<header :class="$style['titan-header']">
</header>复制代码
有时候咱们会有这样的用法:
<div :class="{ 'active': selectedIndex == index} ">
</div>复制代码
这时候样式就会做为对象的属性名,而咱们知道用了CSS Modules,就必须用$style.active
来替换'active'
,还好咱们有ES6!
ES6有一个特性是用双括号支持用计算属性做为属性名,也就是这样:
<div :class="{ [$style.active]: selectedIndex == index} ">
</div>复制代码
bem+CSS Modules在新项目的实践已经有一周的时间,并无发现什么问题,才写下这篇文章来总结。以上只是我在本次工程搭建过程当中的一些总结,并不保证观点彻底正确,供你们参考。