Vue·修改第三方组件样式

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

Vue·修改第三方组件样式

1. scoped属性简介

在Vue组件中,若在style标签上添加scoped属性,则表明style标签中的样式只作用于此Vue组件。


2. 组件互相引用下的样式变化情况

2.1 情况分析

情况 父组件 子组件
情况一 添加 添加
情况二 不添加 不添加
情况三 添加 不添加
情况四 不添加 添加
  • 案例代码(默认App.vue与Box.vue均未添加scoped属性)

App.vue

<template>
  <div id="app">
    <div class="box">父组件</div>
    <box></box>
  </div>
</template>

<script>
import box from "@/components/Box";

export default {
  name: 'App',
  components: {
    box
  }
}
</script>

<style>
  .box {
    width: 200px;
    height: 200px;
    background: green;
    line-height: 200px;
    color: white;
    margin: 20px;
    text-align: center;
  }
</style>
复制代码

Box.vue

<template>
  <div>
    <div class="box">子组件</div>
  </div>
</template>

<script>
export default {
  name: "Box"
}
</script>

<style scoped>
  .box {
    width: 100px;
    height: 100px;
    background: darkred;
    line-height: 100px;
    color: white;
    margin: 20px;
    text-align: center;
  }
</style>
复制代码

2.2 情况一

  • 效果

pic-1.jpg

  • 浏览器DOM节点

pic-2.jpg

2.3 情况二

  • 效果

pic-3.jpg

  • 浏览器DOM节点

pic-4.jpg

2.4 情况三

  • 效果

pic-5.jpg

  • 浏览器DOM节点

pic-6.jpg

2.5 情况四

  • 效果

pic-7.jpg

  • 浏览器DOM节点

pic-8.jpg


3. 了解scoped属性工作原理

若组件的样式添加了scoped属性,那么该组件所渲染出来的DOM节点会被添加一个表示当前组件的形式如data-v-hash的值,用于表示该DOM节点属于哪个组件。

除了组件所渲染的DOM节点被添加了诸如形式如data-v-hash的值,组件的样式也被添加了形式如data-v-hash的值。用来表示该样式应用于哪个组件。

pic-9.jpg

pic-10.jpg


4. 了解scoped属性的特点

当父组件与子组件的样式均添加了scoped属性之后,父组件的样式并不会对子组件的样式进行影响。但是要注意,子组件的HTML根节点会受到父组件的样式的影响,之所以这样设计,是为了让父组件可以对子组件进行布局上的调整。因此我们可以看到子组件的HTML根节点上有两个刑如data-v-hash的值,分别为父组件以及子组件所对应的data-v-hash的值。

pic-11.jpg


5. 使用深度作用选择器修改父组件中子组件的样式

我们可以通过深度作用选择器使得在父组件编写的样式应用在子组件中,我们可以使用>>>操作符来进行操作,若某些预处理器如Sass无法正确解析>>>操作符,则我们可以使用/deep/或::v-deep操作符来代替,二者都是>>>的别名。

  • 步骤
  1. 在父组件中,为父组件所引用的子组件添加选择器。
  2. 在父组件的样式中,编写使用格式形如父组件中子组件选择器 >>> 子组件中选择器的样式。
  • 案例

App.vue

<template>
  <div>
    <div class="box">父组件元素</div>
    <box class="subBox"></box>
  </div>
</template>

<script>
import box from "@/components/Box";

export default {
  name: 'App',
  components: {
    box
  }
}
</script>

<style scoped>
  .box {
    width: 200px;
    height: 200px;
    background: green;
    line-height: 200px;
    color: white;
    margin: 20px;
    text-align: center;
  }

  .subBox >>> .box {
    background: black;
  }
</style>
复制代码

Box.vue

<template>
  <div>
    <div class="box">子组件元素</div>
  </div>
</template>

<script>
export default {
  name: "Box"
}
</script>

<style scoped>
  .box {
    width: 100px;
    height: 100px;
    background: darkred;
    line-height: 100px;
    color: white;
    margin: 20px;
    text-align: center;
  }
</style>
复制代码
  • 效果

pic-12.jpg


6. 正确运用不加scoped属性的组件样式

当我们想通过父组件修改子组件样式时,尤其是将第三方组件作为子组件时,可能会出现无法通过深度选择器修改父组件中子组件的样式的情况。这种原因一般是所要对样式进行修改的子组件并不存在于父组件中。

  • 案例

App.vue

<template>
  <div>
    <dropdown class="dropdown"></dropdown>
  </div>
</template>

<script>
import dropdown from "@/components/Dropdown";

export default {
  name: 'App',
  components: {
    dropdown
  }
}
</script>

<style scoped>
  .dropdown >>> .el-dropdown-menu {
    width: 200px;
  }
</style>
复制代码

Dropdown.vue

<template>
  <div>
    <el-dropdown>
      <span class="el-dropdown-link">
        下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>黄金糕</el-dropdown-item>
        <el-dropdown-item>狮子头</el-dropdown-item>
        <el-dropdown-item>螺蛳粉</el-dropdown-item>
        <el-dropdown-item disabled>双皮奶</el-dropdown-item>
        <el-dropdown-item divided>蚵仔煎</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
export default {
  name: "Dropdown"
}
</script>

<style scoped>
  .el-dropdown-link {
    cursor: pointer;
    color: #409EFF;
  }

  .el-icon-arrow-down {
    font-size: 12px;
  }
</style>
复制代码
  • 效果

pic-13.jpg

  • 浏览器DOM节点

pic-14.jpg

从上面我们可以看见无法通过深度选择器修改父组件中子组件的样式,这是因为我们所要修改的子组件的元素并不存在于父组件之中,导致无法在父组件中通过深度选择器修改子组件中的样式,此时我们则必须使用不添加scoped属性的style标签来进行样式的全局覆盖。Vue组件允许添加scoped属性的style标签与不添加scoped属性的style标签同时存在。

经过修改的App.vue

<template>
  <div>
    <dropdown class="dropdown"></dropdown>
  </div>
</template>

<script>
import dropdown from "@/components/Dropdown";

export default {
  name: 'App',
  components: {
    dropdown
  }
}
</script>

<style scoped>

</style>

<style>
  .el-dropdown-menu {
    width: 200px;
  }
</style>
复制代码
  • 效果

pic-15.jpg

  • 浏览器DOM节点

pic-16.jpg


7. Vue组件样式编写注意点

  1. 所有组件在进行样式编写时都添加scoped属性。
  2. 不建议在组件根元素使用样式,因为子组件的HTML根节点会受到父组件的样式的影响。
  3. 由于element.style样式为常为内联样式或是在JavaScript代码中进行编写的样式,即若想修改其样式,可通过!important关键字提升样式的优先级进行覆盖。

作者:通雄

版权声明:本文为原创文章,未经本人允许不得转载。

猜你喜欢

转载自juejin.im/post/7081973561895682085