持续进步的同学都关注了“1024译站”第77篇文章

  js选择器_移动端js城市选择插件_js定义对象属性访问器

  持续进步的同学都关注了“1024译站”

  这是1024译站的第 77篇文章

  随着代码规模的增长,前端项目中的 CSS 管理成了问题,其中之一就是 CSS 规则冲突。多人协作开发的项目,通过命名约定的方式有时候可能也无法完全避免。对此,不同的前端框架有不同的解决方案。Vue.js 提供了一种样式作用域(Scoped)的机制来防止组件之间的样式规则冲突。

  但是如果单纯用scoped属性,在覆盖子组件元素样式的时候会碰到麻烦。因此,Vue 还提供了deep选择器来解决这个问题。通过本文我们来认识下deep选择器,了解它的原理和用法。

  原理

  首先要搞明白scoped的原理。在 Vue 单文件组件(.vue文件)中给style标签加上scoped属性,然后里面定义的样式规则就会只作用于当前组件,不会影响到其他组件。这是怎么做到的呢?

  每次面试我基本上都会问这个问题,不少初学者都表示不清楚。其实,了解某项功能的原理会帮助你更好地使用它,碰到问题时才知道根源在哪。原理也很简单,加上scoped属性后,在浏览器查看开发工具你会发现,组件模板里的每个 DOM 元素多了一个属性data-v-xxx,CSS 规则也有对应的属性选择器。这些属性名就是组件的唯一 ID,每个组件都不一样。配合 CSS 属性选择器,样式规则就只应用到对应的组件了,这样就能防止互相干扰了。

  js定义对象属性访问器_移动端js城市选择插件_js选择器

  image.png

  但是这样有个问题,组件只会给自己模板里的元素加上属性data-v-xxx,而不会给子组件里的元素加这个属性。同时,生成的 CSS 属性选择器也是只到自己的 DOM 元素,无法应用到子组件内部的元素。当我们需要覆盖子组件内部元素的样式时,在父组件的style里写的规则就无能为力了。在引入第三方组件库的时候经常碰到这种情况。

  还好,我们有deep选择器。deep的原理就是将属性选择器里的属性移到上层,这样就能作用到所有子元素了。

  举例

  为了更好地演示deep选择器的用法,我们来写个简单的示例。示例应用有一些组件,组件自身不会设置样式,而是由它所在的父组件来设置。

  只是简单包装了下 HTML。这里额外用了个

  做容器,原因后面再讲。

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />          <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  这里的按钮没有设置样式,但是要注意的是js选择器,它依然会受到全局 CSS 规则的影响,比如在全局样式表里有个规则button { background-color: 'blue'; }。

  下一步是创建包含该按钮组件的两个父组件。为了演示,我们在每个父组件里用v-for循环渲染三个按钮。

  第一个是BlueParent:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        I is blue<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        {{ i }}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    import BaseButton from "./BaseButton";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    export default {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      components: { BaseButton }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    };<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  第二个是RedParent:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        I is red<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        {{ i }}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /><br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    import BaseButton from "./BaseButton";<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    export default {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      components: { BaseButton }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    };<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  在BlueParent里加上如下的 CSS 代码:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    div >>> button {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      background-color: lightblue;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  这里的三个大于号>>>就是所谓的deep选择器。这里选择器的作用是,对div底下的所有button应用样式规则,即使是子组件内部渲染的button。

  最终效果就是所有的按钮背景色变成蓝色了。

  我们再来做个试验,在BlueParent里面再加一个简单的:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        I is blue<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        {{ i }}<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        Blue<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  你会看到,这个新的Blue元素也用上了这个样式。

  最后一个测试,把样式代码改成这样:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    .blue > button {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      background-color: lightblue;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  没有了deep选择器,只是一个简单的>选择器js选择器,样式就不会再应用到里面的元素了。

  再来看:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    div /deep/ button {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      background-color: red;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  这里用了deep选择器另外一种写法,>>>跟/deep/的作用是一样的。之所以还有这种写法,是因为有些预编译器,比如 SASS,无法识别>>>这种语法,会导致编译失败。这种情况下改用/deep/就好了。

  同样,效果就是所有按钮的背景色变成红色了。

  还记得前面给加的额外的套套

  吗?当你在选择器里能选中组件的根元素时,就可以不用这种deep选择器了,因为这个根元素也是父组件里直接渲染的元素。眼见为实,我们给的那个

  加一个class="buttonWrapper":

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />          <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />        <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    <br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  在父组件里写上下面的 CSS:

  <pre style="box-sizing: border-box;font-size: 16px;color: rgb(62, 62, 62);line-height: inherit;text-align: start;background-color: rgb(255, 255, 255);">    div > .buttonWrapper {<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />      background-color: yellow;<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" />    }<br style="box-sizing: border-box;font-size: inherit;color: inherit;line-height: inherit;overflow-wrap: inherit !important;word-break: inherit !important;" /></pre>

  效果就是div的背景变成黄色。

  总结

  deep选择器不会经常用,但是能在特定的情况下解决特定问题。另外值得一提的是,deep选择器会应用到所有子组件里的元素,包括嵌套子元素。因此需要自己考虑影响范围,采取适当措施。

文章由官网发布,如若转载,请注明出处:https://www.veimoz.com/1752
0 评论
673

发表评论

!