scoped 属性的作用是避免父元件的 CSS 样式会污染到子元件的 CSS 样式。Deep selector 的作用是相反,即使在父元件设定了 scoped css,仍然容许让父元件的 CSS 样式穿透到子元件的 CSS 样式。
以下会详细讨论答案的内容。
在 .vue
档案里,在 style
里加上 scoped
属性的作用是避免目前元件的 style 会污染到子元件的 style。开发时,大多情况都建议加上 scoped
。
scoped
的效果会经由 vue-loader
来处理。vue-loader
是一个 Webpack 的 loader,它负责解析文件,如有需要会再引用其他 loader 来解析文件内容。最後把所有解析好的资源输出为一个 ES Module,并预设以物件型别滙出。
回到重点,要实现 scoped
,我们只需在 style 里加上 scoped
:
<style lang="scss" scoped>
</style>
举例说,现在有一个 Home
元件,里面再包一个 Message
元件。
我们在 Home
元件里的 style 使用 scoped
,并且设定 span 的颜色为红色。结果是只在 Home
里的 span 会变成红色。
Home:
<template>
<div>
<span> 首页的文字 </span>
<Message />
</div>
</template>
<script>
import Message from "@/components/Message";
export default {
components: {
Message,
},
};
</script>
<style lang="scss" scoped>
span {
color: red;
}
</style>
Message:
<template>
<div>
<span>
Message 外层文字
<span> Message 内层文字 </span>
</span>
</div>
</template>
<script>
export default {};
</script>
<style lang="scss">
</style>
结果:
看看目前的 HTML 结构:
Vue loader 编释後,加上 data attribute 来指定只有 Home 元件才会套上 color: red;
这个样式。因此只有「首页的文字」才会变成红色。
在父元件加上 scoped
,看似就不会污染到子元件。但其实会污染到子元件的根部。
重用以上例子,如果把 Message
里最外层的 div
删走,结果是「外层 Message」和「内层 Message」都会受影响。以下示范把 Message
最外层的 div
拿走:
<template>
<span>
Message 外层文字
<span> Message 内层文字 </span>
</span>
</template>
<script>
export default {};
</script>
<style lang="scss">
</style>
结果:
因为没有了 div,而 span 是行内元素,所以这三段文字都排在同一行。而重点是,现在 Message 元件里的所有文字都变成红色。
HTML 结构:
在前一个示范,本来 data-fae5bece
这个属性是套用在 div
上,现在因为把 div
删掉,所以直接套在 span
上,以致整个 Message
元件里的 span
都是红色。
这就是官方文件提及的意思:
使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
重用以上例子,如果在 Message
加上 scoped,并设定 span { color: blue; }
。那麽目前 Message
元件就会同时受父元件和它自己的 scoped 影响,换言之,它会有两个 data attribute。
以下示范在 Message
元件加上它自己的 span 样式,颜色是蓝色。
Message.vue:
<template>
<span> Message 外层文字
<span> Message 内层文字 </span>
</span>
</template>
<script>
export default {}
</script>
<style lang="scss" scoped>
span {
color: blue;
}
</style>
结果:
HTML 结构:
最外层的 span
被加上两个 data attribute,但 Home 的 data attribute 被划掉,因此可见父元件的 scoped CSS 是优先於子元件的 scoped CSS。
https://codesandbox.io/s/scoped-css-lbc9z
deep selector 就是做相反的事。意思是无视 scoped 的限制,即使设定了 scoped,还是可以把父元件的样式穿透到子元件。
deep selector 的写法有几种:
.home >>> .message {
color: red;
}
.home:deep .message {
color: red;
}
.home /deep/ .message {
color: red;
}
.home::v-deep .message {
color: red;
}
另外也可以把前面的父元件省略:
:deep .message {
color: red;
}
/deep/ .message {
color: red;
}
::v-deep .message {
color: red;
}
注意:
>>>
不能被编释。:deep
代替 ::v-deep
。修改之前的例子,在 Home 最外层加上 home
class,在 Message 的外层加上 message
class。最後,在 Home.vue 档案使用 deep selector:
Home.vue:
<template>
<div class="home">
...
</div>
</template>
<script>
...
</script>
<style scoped lang="scss">
span {
color: red;
}
.home:deep .message {
color: red;
}
</style>
Message.vue:
<template>
<div class="message">
...
</div>
</template>
<script>
export default {}
</script>
<style lang="scss" scoped></style>
结果:
HTML 结构:
因为我的例子是使用 scss 来写 CSS,所以不能使用 >>>
的写法。另外,如果我们在子元件设定 span 样式,像以下做法:
Message.vue:
<template>
<div class="message">
<span> Message 外层文字
<span> Message 内层文字 </span>
</span>
</div>
</template>
<script>
export default {
}
</script>
<style lang="scss" scoped>
span {
color: blue;
}
</style>
结果是子元件的文字会变成蓝色,优先於父元件设定的红色:
HTML 结构:
https://codesandbox.io/s/scoped-css-deep-selector-k9111?file=/src/components/Message.vue
当我们以元件的方式来载入第三方套件,并且想修改它的样式,就有机会要用 deep selector。例如我曾经在专案中以元件方式载入 CKEditor,但找不到在哪里可以修改 CKEditor 输入框的高度,於是我使用 deep selector 的方式来处理:
引入 ckeditor 元件来载入 CKEditor:
<ckeditor v-model="editorData" :editor="editor" :config="editorConfig"></ckeditor>
我当时在 style ,针对 CKEditor 里某个 class 的设定:
:deep .ck-editor__editable {
height: 400px;
}
.vue
档案,以及透过 data attribute 的方法,实现 scoped CSS。>>>
、::v-deep
(不建议使用)、 :deep
、/deep/
。 但sass 或 scss 无法编释 >>>
。/deep/ 是什麽? — 聊聊 Vue 里的 scoped css
Vue Loader - Deep Selectors
<<: 爬虫怎麽爬 从零开始的爬虫自学 DAY3 开发环境-2 安装Visual Studio Code
今天来谈谈 SOLID 当中的里氏替换原则,同样的先来看一下例子。 延续先前的例子,公司持续拓展,满...
今天我们来测试看看 JavaScript 框架库 – jQuery,当我们引用 jQuery如果需要...
随机决策树为随机生成许多决策树, 利用取袋法来取出选中的决策树, 而每棵树的都具有执行结果, 每棵树...
前一篇,我们完成了需求一: 当使用者在关键字搜寻这个 input 输入文字时,要在输入框的正下方显示...
前一天提到说 CTC 提出了一个新的概念: 空白(blank),但在最开始的 CTC 设计中是没有使...