vue使用什么进行css开发,教你在Vue项目中使用React超火的CSS-in-JS库: styled-components...

什么是CSS-in-JS?

顾名思义,CSS-in-JS就是可以使用JS来编写CSS样式,那么为什么要用JS来编写CSS呢?我写CSS写的好好的,干嘛非给自己找不自在呢?相信以前大家都听说过这么一个词:关注点分离,就算没听过这个词那么你肯定至少也听说过这么一句话:要把HTML、CSS和JS分开编写,不要写在一起形成耦合,不要写行内样式和行内脚本等,比如像这样👇

CSS-in-JS

但是React的出现打破了这一原则,All in JS是它经典的开发理念,虽然这样违背了“关注点分离”这个原则,但是却有利于组件之间的隔离,使得组件间可以高度解耦,可复用性高。

Vue中为何很少见到类似的库

相信有过Vue开发经验的小伙伴们都知道,编写组件的时候是这样的👇

Vue

export default {

name: 'vue'

}

h1 {

color: #999;

}

CSS直接就很完美的组件化了,不像React那样组件和css文件是分离的,而是直接集成在一个文件中,压根就用不到那些花里胡哨的东西。但是这样其实也是有一定的弊端的,比如CSS无法接受JS的传值👇

import img from '@/assets/img.png'

export default {

name: 'vue',

data () {

return {

img

}

}

}

div {

width: 100vw;

height: 100vh;

}

如果想要div有个背景图应该怎么办?在

通常做法是这样👇

import img from '@/assets/img.png'

export default {

name: 'vue',

data () {

return {

img

}

}

}

div {

width: 100vw;

height: 100vh;

}

但是这样的话编译过后就变成了嵌入在div标签里的行内样式,不利于维护。

还有就是有很多样式其实是公用的,比如flex👇

export default {

name: 'vue'

}

div {

display: flex;

align-items: center;

justify-content: center;

}

如果在每一个组件中都写这么一段样式,不仅繁琐、还不利于维护,而且最关键的是每个用到这段样式的组件都会生成一份div[data-v-xxx]的样式,代码有很大的冗余不说,还会大幅度增大你的CSS文件体积,拖慢项目的运行速度。

那么聪明的你也许会想到:我直接定义一份全局CSS样式不就得了嘛?哪里需要就给哪里加个对应的class,像bootstrap那样,在对应的标签上加类名。

没错这确实是一种很好的解决方式,但是还记不记得用bootstrap的时候不仅仅是加个类名,你还需要安装人家官方定义的那种DOM结构来写你的,还是会需要复制粘贴。而且最关键的是没用办法进行传参,虽然flex这个样式比较常用,但并不是所有的地方都是需要居中对齐,也需要动态来改变align-items和justify-content的话,那么就只能使用笨方法:写所有可能取值的类了。

也许你会说,那我写一个公共组件不就得了👇👇👇

export default {

name: 'vue',

props: {

align: {

type: String,

default: 'center'

},

justify: {

type: String,

default: 'center'

},

}

}

div {

display: flex;

}

但是这样又会带来一个问题,就是假如我需要一个组件变成这个样式怎么办?岂不是必须要被div给包裹住,于是乎你又会说:这还不简单?写成动态组件不就得了?

export default {

name: 'vue',

props: {

align: {

type: String,

default: 'center'

},

justify: {

type: String,

default: 'center'

},

dom: {

type: String,

default: 'div'

}

}

}

div {

display: flex;

}

那假如我需要一堆组件共享一个样式呢?比如像Element-UI那样的嵌套写法,而不是像全局CSS那种很Low的办法,你可能会一拍胸口:没问题,看我这就给你给你封装一个出来👇

// Root.vue

export default {

name: 'root',

provide: {

color: 'yellow'

}

}

// Child1.vue

export default {

name: 'child1',

inject: {

color: {

from: 'color',

default: 'blue'

}

}

}

// Child2.vue

export default {

name: 'child2',

inject: {

color: {

from: 'color',

default: 'green'

}

}

}

用的时候只需这样即可:

// App.vue

Child1

Child2

import Root from '@/components/Root'

import Child1 from '@/components/Child1'

import Child2 from '@/components/Child2'

export default {

name: 'app',

components: {

Root,

Child1,

Child2

}

}

1460000021388932

如果觉得这个颜色看不清,只需把Root组件中的provide里面的color: 'yellow'变成color: 'gray'然后再刷新一下页面即可👇

1460000021388924

真正意义上的实现了组件之间共享样式!

但是这样的话不觉得很麻烦吗?

不但多了一层不必要的DOM结构,而且只是为了个样式重用和样式组件化,就费了这么半天劲,甚至一些基础不是很牢固的小伙伴看到这里都晕了,其实市面上早就有封装好的库,我们这样就是在重复造轮子。

这时要是再提出几个需求的话就很难实现了,比如我想继承样式,当然你会说用Sass、Less或者Stylus这种预处理器可以做到,那如果我想继承的是默认标签的样式并进行扩展呢?我想继承a标签的默认样式(下划线、点击变红、点完变紫等)然后再加入一些字体大小、行高等样式,就只能傻傻的纯手写了。那么接下来我就为大家介绍一个写法优(zhuang)雅(bi)、成熟稳定并且在React生态圈大受欢迎但是在Vue生态圈却无人知晓的大名鼎鼎的CSS-in-JS库:styled-components!

vue-styled-components

顾名思义,styled-components就是样式化的组件,由于styled-components是专门为React量身定做的一个库,所以不太适合在Vue项目中使用,我知道你看到这里一定开始想骂人了:我特么津津有味的看了半天,结果你告诉我styled-components不适合在Vue项目中使用?

不要着急,虽然styled-components没法在Vue项目中使用,但是styled-components团队专门为Vue贴身打造了一个vue-styled-components,和React的styled-components用法非常相似,我们先从一个最简单的案例进行入门,首先要进行安装:

npm i -S vue-styled-components

或者

yarn add vue-styled-components

然后写组件的时候不能再写xxx.vue了,取而代之的xxx.js。你可以简单的理解为这是一个极简的组件,没有也没有,只专注于样式,写法如下👇

// Flex.js

import styled from 'vue-styled-components'

const Flex = styled.div`

display: flex;

align-items: center;

justify-content: center;

`

export {

Flex

}

可以看到没有了之前我们熟悉的

然后在它的前面需要一个变量来接收,起什么名字都可以,如:const Okay = styled.xxx

接下来是一个ES6的模板字符串语法``,不懂的话可以参考一下阮一峰老师的博客

1460000021388929

然后就可以在你的字符串模板里面写你想要的任何CSS样式啦!不仅写法和CSS一模一样,甚至还支持类似于Sass、Less和Stylus的那种嵌套语法:

// Flex.js

import styled from 'vue-styled-components'

const Flex = styled.div`

display: flex;

align-items: center;

justify-content: center;

&:hover { background: gray; }

> :first-child { align-self: flex-start }

> :last-child { align-self: flex-start }

`

export {

Flex

}

平时你是怎么用xxx.vue组件的,你就怎么用这个xxx.js组件:

// App.vue

styled

components

import { Flex } from '@/components/Flex'

export default {

name: 'child1',

components: {

Flex

}

}

可以发现我们并没有定义却能插入正常位置当中,他会自动找到默认位置进行插入,因为每一个标签即是一个组件,不会存在比较复杂的DOM嵌套结构。接下来看看如何给CSS传参:

// Ok.js

import styled from 'vue-styled-components'

const Ok = styled('div', {

bg: {

type: String,

default: '#eee'

}

})`

width: 100px;

height: 100px;

background: ${ props => props.bg }

`

export { Ok }

现在styled后面不是不是直接跟一个点和字符串模板了,而是把点换成括号,第一个参数是一个字符串,代表了你想要什么DOM标签,第二个参数和你写Vue组件中的props一模一样,也可以偷懒写成数组形式:

// Ok.js

import styled from 'vue-styled-components'

const Ok = styled('div', ['bg'])`

width: 100px;

height: 100px;

background: ${ props => props.bg }

`

export { Ok }

${}里面可以写一个函数,这个函数返回的结果就会渲染成最后的CSS值,函数的第一个参数就是你的定义的属性的集合,定义过后接下来我们看看如何进行使用:

// App.vue

import { Ok } from '@/components/Ok'

export default {

name: 'app',

components: { Ok }

}

1460000021388933

可以看到我们传进去的值完美生效,函数里面也可以写任何表达式:

// Ok.js

import styled from 'vue-styled-components'

const Ok = styled('div', ['bg'])`

width: 100px;

height: 100px;

background: ${props => {

alert(666)

return props.bg ? 'green' : 'blue'

}}

`

export { Ok }

1460000021388930

可以看到你写的函数逻辑就会运行,我们还可以给添加一个样式:

import styled from 'vue-styled-components'

// 不能直接引入router-link, 而是像这样取到router-link

const RouterLink = Vue.component('router-link')

const StyledLink = styled(RouterLink)`

color: #333;

font-size: 1em;

text-decoration: none;

`

export default StyledLink

用的时候只需把换成即可:

Custom Router Link

还提供了类似于Element-UI的共享数据写法:

import {ThemeProvider} from 'vue-styled-components'

new Vue({

// ...

components: {

'theme-provider': ThemeProvider

},

// ...

})

使用的时候为根组件:

// ...

子组件需要接收一下数据:

const Wrapper = styled.default.section`

padding: 4em;

background: ${props => props.theme.primary};

`

再来看一个继承的例子:

import StyledButton from './StyledButton'

const TomatoButton = StyledButton.extend`

color: tomato;

border-color: tomato;

`

export default TomatoButton

这样就可以非常完美的实现样式的扩展及复用,甚至还可以扩展原生标签:

const Button = styled.button`

background: green;

color: white;

`

const Link = Button.withComponent('a')

与Vue原生组件的对比

vue-styled-components编译过后会生成一个随机的类名:

1460000021388927

1460000021388928

而Vue原生组件写的样式会生成一个data-v-xxx的随机属性:

1460000021388926

1460000021388931

这样一来选择器的效率就会有着较大差距,vue-styled-components只有一个选择器,原生组件却是两个选择器合并,而且属性选择器的效率比较低,无形之中就拉开了差距。

传值方面原生组件给CSS传值只能通过这种方式:

1460000021388925

而vue-styled-components传值后属性不会显示在标签上,而是直接嵌入到CSS里:

1460000021388934

1460000021388935

而且vue-styled-components由于是JS,所以可以写JS代码,非常的方便。

还有更多有趣好玩的功能请戳:styled-components

快去拿这玩意重构一下你的项目吧!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值