.content{.title-wrap{字体大小:20px;红色;}}一个web应用离不开html、css和js,其中css充斥在整个web项目中。css它有特定的,它是全局的。这样的特性带来的结果是,一旦你在不同的地方定义了相同的css名称,它们的样式就会相互覆盖,最终导致样式混乱,影响整个网页布局。这种css样式覆盖相信每个前端开发者都遇到过。幸运的是,这些问题的前辈们已经给出了解决方案。在Vue中,我们使用Scoped和Module来解决。下面我将分别讲解scoped和module方案,最后分析一下它们的优缺点和选择。如果你没有使用过或者对它们之间的优缺点和选择有疑问,相信这篇文章可以帮你理清疑惑。Scoped假设我们有以下代码:index.vueIamred.content{.title-wrap{字体大小:20px;红色;}}GreenTitle.vue我是绿色的.content{.title-wrap{字体大小:20px;颜色:绿色;}}最后在屏幕上显示两行红色文字,表示父组件和子组件都定义了title-wrap的样式,导致子组件的样式被替换为覆盖的父组件。在这种情况下,您可以将scoped属性添加到样式标签.content{.title-wrap{font-size:20px;红色;}}scoped防止上层的css样式传递给下层,限制当前css的作用范围,使其只对当前组件生效。了解了它的功能,我们再深入看看它的实现。前者是没有scoped的源码,后者是加了scoped的源码。我们一一对比,发现前两个div标签使用了title-wrap样式,自然导致样式被覆盖;而前两个div标签添加了data-v-67e6b31f的前缀,这是parentscoped效果添加到组的样式中,与第二个div中的title-wrap样式不同。scoped的实现是借助PostCSS实现的。添加scoped后,它会将之前覆盖的样式转换为以下样式20px;红色;}}通过这种转换方式,间接改变了原来的css命名方式。防止上层组件样式覆盖下层组件样式。细心的读者可能会发现上面源码图中第二个div的内容里也有data-v-67e6b31f,可能会疑惑,第二个内容不就是子组件中的css吗?子组件没有加scoped,为什么要加data-v-67e6b31f前缀?这是作用域的一个特性。使用scoped后,父组件的样式不会渗透到子组件中。但是,子组件的根节点将同时受到其父组件的作用域CSS和子组件的作用域CSS的影响。这种设计是为了让父组件从布局的角度来调整其子组件的根元素的样式。所以如果我们修改子组件如下>-->由于父组件的scoped特性,会影响到子组件的title-wrap,也会加上前缀data-v-67e6b31f。那么还有一个问题,添加scoped是不是一定不能通过底层组件呢?毕竟,我们可能有将个别样式传递给下层的需求。别着急,继续往下看,这个也可以轻松解决。深度效果如果你想让scoped中的样式作用更深并影响子组件,你可以使用>>>运算符.content>>>.title-wrap{font-size:20px;color:red;}注意我去掉了style中的lang="scss",因为加预处理器后无法正确解析>>>,此时可以用/deep/代替,本质是>>>的别名.content{/deep/{.title-wrap{font-size:20px;红色;}}}会被编译成.content[data-v-67e6b31f].title-wrap{font-size:20px;color:red;}通过v-html创建的DOM内容不受范围内样式的影响,但你仍然可以通过deep-action选择器设置它们StyleModule对于上面的覆盖问题,也可以通过设置module我是红色的.content{.title-wrap{字体大小:20px;红色;}}module的使用也很简单,只要在style中添加module属性即可。不同的是它在布局中的引用需要加上$style前缀。因为模块作用的样式都保存在$style对象中。我可以通过控制台查看它的具体引用名称。mounted(){console.log(this.$style)console.log(this.$style['title-wrap'])}通过观察,发现引用名称有一定规律。它们都以索引开头,然后是样式中定义的名称,最后是后缀。这里的index是父组件的文件名index.vue。因此,通过模块的样式会更名为:文件名_原始样式名_不定后缀。这样的命名有什么好处呢?我们再来看看显示的效果。当我们在浏览控制台中查看Elements时,优势是显而易见的。与scoped方法相比,module方法可以一眼就知道元素属于哪个文件组件。在大型项目中,它可以帮助我们快速定位到我们要找的组件。除了上面的快速定位之外,由于模块会将所有样式都放到$style中,我们可以灵活地将任意父组件样式传递给任意深层子组件。例如,通过props将父组件中的title-wrap传递给子组件我是红色的我是绿色的多了一个模块这个功能很好,可以导出定义的变量,把变量放到$style中,例如:我是红色的{{$style.titleColor}}
$title-color:red;:export{titleColor:$title-color}.content{.title-wrap{字体大小:20px;颜色:$标题颜色;}}变化多模块相关操作可以点击查看汇总scoped和module都非常简单易用,那么如何选择呢?通过上面的使用对比,发现scoped不需要额外的知识,只要在style中定义scoped属性即可,非常好用,但它的局限性在于适用于中小型项目。因为scopedfunction的样式对我们来说不直观,module更适合快速搜索定位。同时,模块对样式向下传递的控制也非常灵活;此外,还有变量导出等方便的功能。所以如果你是在低成本的小项目中使用它,scoped更合适;而且对于大型项目模块更适合。虽然有一点学习成本,但对于更好的控制、可观察性和定位速度来说并不是必须的。值得一提。公众号感觉不错可以关注,扫描下方二维码,关注公众号:怪谈时间,及时获取最新知识技能和网络新动态。