vue组件的scope 以及 如何样式穿透

个人复习!!!

有什么用

让当前组件的样式不会修改到其它地方的样式,使用了data-v-hash的方式来使css有了它对应模块的标识

实现原理

1、给HTML的dom节点添加一个不重复的data属性(例如: data-v-5558831a)来唯一标识这个dom 元素
2、在每句css选择器的末尾(编译后生成的css语句)加一个当前组件的data属性选择器(例如:[data-v-5558831a])来私有化样式

比如现在有一个这样的组件

<template>
  <el-container class="wrap">
    <el-header>
      <LayoutHeader class="a">LayoutHeader>
    el-header>
    <el-container>
      <el-aside width="auto" height="100%">
        <LayoutSidebar class="b">LayoutSidebar>
      el-aside>
      <el-main>
        <LayoutNavtag>LayoutNavtag>
        <div class="main_view">
          <router-view>router-view>
        div>
      el-main>
    el-container>
  el-container>
template>

按照第一条规则:给组件当中的元素添加一个唯一标识着当前组件的data属性

vue组件的scope 以及 如何样式穿透_第1张图片

其中红色框分别对应的是编译后的组件
编译后后结果:
可以看到当前除了组件以外的元素都被加上一个data-v-7feca419

其中的组件有下面几种情况:
1、组件如果有根元素,则根元素被加上data-v-7feca419
2、如果被引入的组件有自己的scoped 那么 该组件的所有元素都会被加上自己的data-xxxx

按照这个思路分析:
其中LayoutHeader 没有根元素也没有自己的scoped,所以没有加上data-v-7feca419 以及自己的data-xxx
LayoutSidebar 存在aside 根元素,素以加上了,但是没有自己的scoped
LayoutNavtag 有根元素,而且有自己的scoped 所以带了两个data-xxx
router-view 也有根元素,所以使用了data-v-7feca419

上面会出现什么问题?

当前组件中 style定义的任何类名 选中当前任何标签都是可以作用到的

但是如果选中某个组件里边的某个元素(除了根元素)就没法操作,因为该元素不存在当前样式的data-xxx

比如我们写了一个这样的样式

.wrap {
  color: pink;
  .el-header {
    .title {
      color: blue;
    }
  }
}

选中自定义组件LayoutHeader 里边的 div.title 标签
在没有使用scoped 之前,我们是可以正常选中的,但是现在scoped 会给选择器末尾加上data-xx
vue组件的scope 以及 如何样式穿透_第2张图片
而div.title 不属于 当前组件的标签,也并非LayoutHeader 的唯一根标签,所以并没有data-v-7feca419 进而无法选中,无法使用对应样式

如果div.title为组件的唯一跟标签,那它也会被加上data-v-7feca419,是可以被选中

如何处理

有时候我们使用到类似elementui 的组件库,我们自己封装组件时候,但是被引入的组件有些样式想修改怎么办?

假如LayoutHeader 为被引入的组件,我们想修改 里边的div.title的宽度怎么办?
方法1:是直接修改LayoutHeader ,这样子还好,但是如果是el-button 呢?,那所有用到的el-button都被改了
方法2:就是去掉当前的scoped,但是会可能污染其他的组件 所以不建议

另外就是采用样式穿透;

样式穿透

原理:改变编译后选择器的data-v-xxx位置

比如上面编译后的

.wrap .el-header .title[data-v-7feca419] {
  color: blue;
}

我们知道.el-header 标签是存在data-v-7feca419
我们能不能不在.title 上添加data-xxx ?

.wrap {
  color: pink;
  .el-header {
    ::v-deep .title {
      color: blue;
    }
  }
}

编译后
这样子,.title上就不会存在 data-xxx 了而是在前一个上面添加
这个时候它的前一个类名是存在data-xx 这样就就可以修改.title 了

.wrap .el-header[data-v-7feca419] .title {
  color: blue;
}

注意一个问题:如果.title 里边有一个.mini_tilte 类名,
如果我们想修改.mini_title
那么穿透应该怎么写呢?
使用写法1 还是写法2呢?
我们知道穿透后,data-xx 会移到前一个类名上,但是.title 自身是没有data-xx的,所有应该采用写法2 才能选中到.mini_title

.wrap {
  color: pink;

  .el-header {
  	1、写法1
    //.title {
    //  ::v-deep .mini_title {
    //    font-size: 30px;
    //  }
    //}
    1、写法2
    //::v-deep .title {
    //  .mini_title {
    //    font-size: 30px;
    //  }
    //}
  }
}

最后总结:
建议使用scoped,修改某个被引入的组件时候,首先得清楚应该如何选中组件内的某个元素
然后就是样式穿透应该写在哪里?

你可能感兴趣的:(vue.js,前端,javascript)