手机版

Vue中CSS和CSS模块的区别

时间:2021-08-29 来源:互联网 编辑:宝哥软件园 浏览:

现代Web开发中的CSS远非完美也就不足为奇了。如今,项目通常相当复杂,而CSS样式是全局的,因此样式冲突最终总是非常容易发生:样式相互重叠或隐式级联到我们没有考虑的元素。

为了缓解CSS的主要痛点,我们在项目中一般采用边界元法。但是,这只能解决一小部分CSS问题。

对我们来说幸运的是,社区已经开发了解决方案,可以帮助我们更彻底地解决问题。你可能听说过CSS模块,风格组件,魅力或JSS。这些只是我们今天可以添加到项目中的一些最流行的工具。如果你对这个话题感兴趣,可以查看这篇文章:@ indreklassn详细介绍了JS中CSS的所有思想。

用Vue-cli构建的Vue应用程序提供了两个很好的内置解决方案:限定范围的CSS和CSS模块。它们都有一些优点和缺点,让我们仔细看看哪种解决方案更适合您。

范围CSS

在Vue中,引入了CSS作用域的概念。scoped的设计思想是,当前组件的样式不会影响其他地方的样式,编译后的选择器会以data-v-hash的方式应用到相应的组件中,这样CSS就不需要添加额外的选择器。也会解决CSS中选择器范围和选择器权重的问题。

在Vue中,为了使范围样式起作用,只需要将范围属性添加到样式标签中:

!-button . vue-template button class=' BTN ' slot/slot/button/template style作用域。btn { color:红色;}/style通过使用PostCSS并将上面的示例转换为下面的示例,它只将我们的样式应用于同一组件中的元素:

可以看到,整个过程不需要做任何事情就可以达到很好的效果:范围风格(CSS中让人头疼的问题之一)。

现在假设您需要调整Button组件的宽度,您可以添加一个额外的类来设置它的样式,该组件通常在这里被调用:

!-app . vue-template div id=' app ' Button class=' BTN-LG '单击/Button /div/templatescript从导入Button '。/组件/按钮';导出默认{ name: 'App ',components: { Button } }/scriptstyle作用域。BTN-LG { padd : 10px 30px;}/style是这样转换的:

这次是一样的。你不需要做任何事情来控制风格。

但是,请注意,此功能有一个缺陷,即如果子组件元素上的类已经在此父组件中定义,则此父组件的样式也将应用于子组件。只不过它的重量没有子部件同名的重。例如,以下示例:

!-button . vue-template button class=' BTN BTN-LG ' slot/slot/button/template style scoped . BTN { color : red;}.BTN-LG { padd : 10px 20px;border: 2px纯红;}/style!-app . vue-template div id=' app ' Button class=' BTN-LG '单击/Button /div/templatescript从导入Button '。/组件/按钮';导出默认{ name: 'App ',components: { Button } }/script style scoped . BTN-LG { padd : 30px;border: 5px纯绿色;}/style编译结果如下:

在其他情况下,我们需要设计子组件的深层结构。虽然不建议这样做,但应该尽可能避免。例如,在下面的示例中,在Button组件下有一个span标记,并且span样式是在调用Button组件的父组件App中设置的:

!-button . vue-template button class=' BTN ' span slot/slot/span/button/template style scoped . BTN { color : red;}/style!-app . vue-template div id=' app ' Button class=' BTN-LG '单击/Button /div/templatescript从导入Button '。/组件/按钮';导出默认{ name: 'App ',components: { Button } }/script style scoped . BTN span { color : green;font-weight:粗体;border: 1px纯绿色;padding: 10px}/style编译结果如下:

从以上结果可以看出,父组件App.vue中的样式:btn span { color:绿色;font-weight:粗体;border: 1px纯绿色;padding: 10px}以上样式未编译,应用于子组件Button.vue中的span.

在限定范围的样式中,这种情况可以通过使用连接器或/deep/:

!- App.vue风格范围。btn span { color:绿色;font-weight:粗体;border: 1px纯绿色;padding: 10px}/style此时在App.vue中的scoped control Button.vue组件中仍然是span,但上面的区别是这个样式生效了。编译结果如下:

使用范围样式也有问题。也就是说,它对v-html中固有的标签样式没有影响。例如,以下示例:

!-button . vue-template button class=' BTN ' slot/slot/button/template style scoped . BTN { color : red;}/style!-app . vue-template div id=' app ' Button class=' BTN-LG ' v-html=' vhtml '/Button/div/template script import Button from '。/组件/按钮';导出默认{ name: 'App ',data () {返回{ vhtml : ' Click strong 7/strong ' } },components: { Button } }/script style scoped trong { color : green;border: 1px纯绿色;padding: 10px}/style编译结果如下:

从上图可以看出,v-html中的强标签样式没有生效。这与之前在父组件的范围内设置子组件的内部标签是一样的。当然,解决方法是一样的。使用连接器或/deep/可以使v-html中的标签样式生效。例如,在上面的示例中,您可以将代码修改为:

!- App.vue风格范围。btn /deep/strong { color:绿色;border: 1px纯绿色;padding: 10px}/style这时,v-html中的强样式生效,如下图所示:

话又说回来,虽然/deep/可以帮助我们穿透封装组件中的样式,但也失去了组件封装的效果。回到之前CSS里头疼的问题:CSS范围。

简单总结一下,Vue中作用域属性的呈现规则:

向DOM节点添加一个非重复的数据属性(如data-v-7ba5bd90),以表达其唯一性。在每个CSS选择器(编译后生成的CSS)的末尾添加一个当前组件的数据属性选择器(如[data-v-7ba5bd90]),将样式私有化。选择器末尾的数据属性与其对应的DOM中的数据属性相匹配。如果组件中有其他组件,则只有当前组件的数据属性会添加到其他组件的最外层标签中。上面我们看到的是CSS在Vue机制范围内的使用。在Vue中,除了范围CSS之外,还有另一种机制,那就是CSS Modules,也就是模块化的CSS。

CSS模块

CSS模块的流行源于React社区,很快被社区采用。更重要的是,Vue强大而简单的功能,加上Vue-cli开箱即用的支持,将它发展到了更高的水平。

在Vue中使用CSS模块就像在作用域中使用CSS一样简单。在范围上类似于CSS,在样式标签中添加模块属性。例如,像这样:

样式模块。btn { color:红色;}/style,然后将其写入模板:

template button 3360 class=' $ style。BTN ' { msg } }/按钮/模板。此时的编译效果如下:

如上图所示,class='$style.btn '将被编译成类名。Button_btn_3ykLd由vue-template-编译器生成,样式选择器会自动相应改变。

但在这里有一点需要注意,我们平时有可能在类名中会使用分隔线,比如:

样式模块BTN-LG { border 3360 1px固体红色;padd : 10px 30px }/样式如果通过$style调用该类名时要是写成$style.btn-lg,这样写是一个不合法的Java脚本语言变量名。此时在编译的时候,会报一个错话信息:

按钮的样式也不会生效。如果要生效,我们需要通过下面这样的方式来写:

模板按钮: class=' $ style[' BTN-LG ']' { { msg } }/按钮/模板编译出来的结果如下:

除了$style.btn-lg这种方式会报错之外,写在驼峰($style.btnLg)的也会报错。

上面说的组件属性会经由真空装载机编译后,在我们的成分产生一个叫$style的隐藏的计算属性。也就是说,我们甚至可以在某视频剪辑软件生命周期的创造钩子中取得由半铸钢钢性铸铁(Cast Semi-Steel)模块生成的班级类名:

脚本导出默认值{ created(){ console。日志(这$style['btn-lg']) }}/script在浏览器的安慰中可以看到模块编译出来对应的类名:

利用这样的特性,在模板也可以这样写:

!-app。vue-template div id=' app ' Button msg=' Default Button '/Button : class=' {[$ style[' BTN-LG ']]: isLg } ' msg=' bigger Button '/Button : class=' {[$ style[' BTN-sm ']]: isSm } ' msg=' small Button '/div/模板脚本导入Button from ' ./components/Button ' export default { name : ' app ',components: { Button },data () { return { isLg: true,issm : false } }/script style模块。BTN-LG { padd : 15px 30px;}.BTN-sm { padd : 5px;}/样式

这个时候编译出来的结果如下:

如上图所示,当数据中的消极因素属性值为真实的时,更大的按钮按钮的填料变了,按钮也同时变大了。除此之外,我们还可以通过小道具将班级传到子组件中。比如像下面这样使用:

!-按钮。vue-template Button : class='[$ style。BTN,初级课程]' { { msg } }/按钮/模板脚本导出默认{ name: 'Button ',props: { msg: String,primary class : ' ' }/脚本样式模块btn { border: 1px固体# cccborder-radius : 3px;padding: 5px 15px背景技术# fefemargin : 5px }/style!-app。vue-template div id=' app ' Button msg=' Default Button '/Button : class=' {[$ style[' BTN-LG ']]: isLg } ' msg=' bigger Button '/Button : class=' {[$ style[' BTN-sm ']]: isSm } ' msg=' small Button '/Button msg=' Primary Button ' 3360 Primary class=' $ style[' BTN-Primary ']' '/组件/Button '导出默认值{ 0模块BTN-LG { padd : 15px 30px;} .BTN-sm { padd : 5px;} .BTN-小学{背景: RGB(54,152,244);边框颜色: rgb(32,108,221);color: # fff}/样式

编译出来的效果如下图所示:

如果我们想要在Java脚本语言里面将独立的半铸钢钢性铸铁(铸造半钢)文件作为半铸钢钢性铸铁(铸造半钢)模块来加载的话,需要在。钢性铸铁文件名前添加。组件前缀,比如:

脚本从""导入barStyle ./src/style/bar。模块。CSS '/脚本如果你是在项目中引入的是处理器文件也是如此,比如。半导体色敏传感器文件:

脚本从""导入fooSassStyle ./src/scss/foo。模块。scss “/脚本如果你觉得这样比较麻烦,可以在vue.config.js文件中css.modules设为真:

//vue。配置。js模块。导出={ CSS : { modules : true } }注意,上面的示例创建的项目是使用Vue-cli 3创建的。如果是使用Webpack的话,需要根据Webpack的相关机制进行配制。

从上面的例子我们可以看出。使用模块和限定作用域的区别在于,所有创建的类都可以通过$style对象获得。因此,如果要将类应用于元素,就必须通过:class绑定对象$style。它的优点是,当我们在HTML中查看这个元素时,我们可以立即知道它属于哪个组件。如果足够小心,您可以看到编译后的类名以组件名作为前缀,例如:

除了这个好处,还有一个好处,就是一切都变得显而易见,我们有完全的控制权。

摘要

无论是CSS Modules还是范围内的CSS,这两种方案都非常简单易用。一定程度上解决了同样的痛点(CSS痛点)。那么你应该选择哪一个呢?

使用限定范围的风格不需要额外的知识,给人一种舒适的感觉。它的局限性正是它易于使用的原因。它可用于支持中小型网络应用程序。在更大的网络应用程序或更复杂的场景中,我们更喜欢CSS显式,并且有更多的控制。例如,当您的样式可以在多个组件中重用时,作用域的限制变得更加明显。相反,CSS Modules的出现恰恰解决了这些问题,但也要付出一定的代价,那就是需要$style来引用。虽然在模板中大量使用$style会让人看起来很痛苦,但它会让你的风格更安全、更灵活、更容易控制。CSS Modules的另一个优点是我们可以获得一些由JavaScript定义的变量,所以我们不需要手动在多个文件中保持它们的同步。

最后,CSS没有最好的解决方案,只有最适合的!我们应该根据自己的项目、场景和团队来选择。当然,无论你选择哪种方案,都是为了帮助我们更好地控制风格,解决原生CSS中的痛点。最后,希望这篇文章对大家有所帮助。

版权声明:Vue中CSS和CSS模块的区别是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。