前言
Vue.js 自带的 scoped 特性可以让我们在一个组件中使用 CSS 样式时限制其作用域仅在该组件内生效,而不污染全局样式。这个特性的使用非常简单,但是会涉及一些细节问题,本文将详细介绍 Vue.js 中 scoped 特性的使用方法、效果分析及常见问题解决方法。
scoped 特性的基本语法
在 Vue.js 中使用 scoped 特性非常简单,只需要在组件的 <style> 标签上添加该特性即可:
// www.javascriptcn.com code example
<template>
<div class="example">这是一个示例</div>
</template>
<style scoped>
.example {
color: red;
}
</style>在上面的代码中,<style> 标签上添加了 scoped 特性,这意味着 example 类的样式只会在当前组件内生效,而不会影响到全局的 example 类样式。
scoped 特性的效果分析
scoped 特性的作用域并不是通过添加随机字符串后缀实现的(SASS 和 LESS 等 CSS 预处理器会通过添加随机字符串实现样式隔离)。Vue.js 的 scoped 特性是在编译时将样式的选择器转为更加具体的选择器,从而实现样式隔离。
例如,在下面的代码中,example 类的样式在组件内部实际上变成了 div[data-v-f3f3eg9] .example {}:
// www.javascriptcn.com code example
<template>
<div class="example">这是一个示例</div>
</template>
<style scoped>
.example {
color: red;
}
</style>由此可以看出,Vue.js 的 scoped 特性的本质是在样式选择器前添加一个属性选择器,从而让样式只作用于该属性选择器所匹配的元素。
scoped 特性的常见问题及解决方法
问题一:选择器样式失效
当我们在使用 scoped 特性时,有时候选择器样式会失效:
// www.javascriptcn.com code example
<template>
<div class="example">
<p class="text">这是一段文字</p>
</div>
</template>
<style scoped>
.example .text {
color: red;
}
</style>在上面的代码中,我们希望 .text 类的样式只在当前组件内生效,但是实际上样式并没有生效。这是因为在 Vue.js 的 scoped 特性中,子组件的样式只会在父组件的根元素下生效,而不会在子组件内生效。
这个问题的解决方法比较简单,只需要为子组件的根元素添加一个属性即可。例如,在下面的代码中,我们为子组件 Child 的根元素添加了 data-v-f3f3eg9 属性:
// www.javascriptcn.com code example
<template>
<div class="example">
<child></child>
</div>
</template>
<style scoped>
.example .text {
color: red;
}
</style>
<script>
export default {
components: {
Child: {
template: `
<div class="text" data-v-f3f3eg9>
这是一段文字
</div>
`
}
}
}
</script>问题二:全局样式污染
在 Vue.js 的应用中,我们往往需要引入一些全局样式(例如 reset.css),这些全局样式往往会污染组件内部的样式,导致组件的样式无法预期。
解决这个问题的方法是使用 ::v-deep 伪类选择器,它的作用是穿透 scoped 特性,从而使得样式可以影响子组件的 DOM 元素。
例如,在下面的代码中,我们为 .example 类添加了一个字体样式,它通过 ::v-deep 伪类选择器穿透了 scoped 特性,从而影响了子组件的 .text 类:
// www.javascriptcn.com code example
<template>
<div class="example">
<child></child>
</div>
</template>
<style scoped>
.example {
font-size: 18px;
}
.example ::v-deep .text {
color: red;
}
</style>
<script>
export default {
components: {
Child: {
template: `
<div class="text">
这是一段文字
</div>
`
}
}
}
</script>结语
在 Vue.js 中使用 scoped 特性可以很好地实现组件样式的隔离,但在使用过程中需要注意一些细节问题。本文介绍了 scoped 特性的基本语法、效果分析及常见问题解决方法,希望能够对广大前端工程师有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d66cdca941bf7134c2fbcf