首页 web前端 js教程 在vue中有关如何使用style的scoped属性

在vue中有关如何使用style的scoped属性

Jun 23, 2018 pm 05:55 PM
style vue

本篇文章主要介绍了浅谈vue中慎用style的scoped属性,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

在vue组件中,为了使样式私有化(模块化),不对全局造成污染,可以在style标签上添加scoped属性以表示它的只属于当下的模块,这是一个非常好的举措,但是为什么要慎用呢?因为在我们需要修改公共组件(三方库或者项目定制的组件)的样式的时候,scoped往往会造成更多的困难,需要增加额外的复杂度。

scoped实现私有化样式的原理

为什么会说,会增加复杂度?那么我们先从的实现模块的原理说起。为了方便称呼,我们假设把这种组件叫做模块私有组件,其他的未加scoped的叫做模块一般组件。

通过查看DOM结构发现:vue通过在DOM结构以及css样式上加唯一不重复的标记,以保证唯一,达到样式私有化模块化的目的。具体的渲染结果是怎样的,通过一个例子来说明。

公共组件button组件

一个公共组件button,为了样式模块化,给其加上scoped属性,

//button.vue
<template>
  <p class="button-warp">
    <button class="button">text</button>
  </p>
</template>
...
<style scoped>
  .button-warp{
    display:inline-block;
  }
  .button{
    padding: 5px 10px;
    font-size: 12px;
    border-radus: 2px;
  }
</style>
登录后复制

浏览器渲染button组件

button组件在浏览器渲染出的html部分和css部分分别为:

<p data-v-2311c06a class="button-warp">
  <button data-v-2311c06a class="button">text</button>
</p>
登录后复制
.button-warp[data-v-2311c06a]{
  display:inline-block;
}
.button[data-v-2311c06a]{
  padding: 5px 10px;
  font-size: 12px;
  border-radus: 2px;
}
登录后复制

从上面的字可以看出,添加了scoped属性的组件,为了达到组件样式模块化,做了两个处理:

  1. 给HTML的DOM节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性

  2. 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式

大家都知道css样式有一个优先级的说法,scoped的这一操作,虽然达到了组件样式模块化的目的,但是会造成一种后果:每个样式的权重加重了:理论上我们要去修改这个样式,需要更高的权重去覆盖这个样式。这是增加复杂度的其中一个维度。

其他组件引用button组件

上面分析了单个组件渲染后的结果,那么组件互相调用之后会出现什么样的结果呢?,具体分两种情况:模块一般组件引用模块私有组件(本质和模块私有组件引用模块一般组件一样);模块私有组件引用模块私有组件。

举个例子:在组件content.vue中使用了button组件,那么content.vue组件是否添加scoped属性渲染出来的结果有什么区别呢?

//content.vue
<template>
  <p class="content">
    <p class="title"></p>
    <!-- v-button假设是上面定义的组件 -->
    <v-button></v-button>
  </p>
</template>
...
<style>
  .content{
    width: 1200px;
    margin: 0 auto;
  }
  .content .button{
    border-raduis: 5px;
  }
</style>
登录后复制

模块一般组件(未添加scoped)引用模块私有组件

如果style上没有加scoped属性,那么渲染出来html和css分别就是:

<p class="content">
  <p class="title"></p>
  <!-- v-button假设是上面定义的组件 -->
  <p data-v-2311c06a class="button-warp">
    <button data-v-2311c06a class="button">text</button>
  </p>
</p>
登录后复制
/*button.vue渲染出来的css*/
.button-warp[data-v-2311c06a]{
  display:inline-block;
}
.button[data-v-2311c06a]{
  padding: 5px 10px;
  font-size: 12px;
  border-radus: 2px;
}
/*content.vue渲染出来的css*/
.content{
  width: 1200px;
  margin: 0 auto;
}
.content .button{
  border-raduis: 5px;
}
登录后复制

可以看出,虽然在content组件中,修改了button的border-raduis属性,但是由于权重关系,生效的依然是组件内部的样式(此时是外部的样式被覆盖)。所以如果要达到修改样式的目的,就必须加重我们要修改样式的权重(增加选择器层级,ID选择器,并列选择器,impotant等)

模块私有组件(添加scoped)引用模块私有组件

如果加了scoped属性呢?按照开始分析出来的规则(事实也是这么的):

首先是在所有的DOM节点加上data属性

然后在css选择器尾部加上data属性选择器

那么渲染出来html和css分别就是:

<p data-v-57bc25a0 class="content">
  <p data-v-57bc25a0 class="title"></p>
  <!-- v-button假设是上面定义的组件 -->
  <p data-v-57bc25a0 data-v-2311c06a class="button-warp">
    <button data-v-2311c06a class="button">text</button>
  </p>
</p>
登录后复制
/*button.vue渲染出来的css*/
.button-warp[data-v-2311c06a]{
  display:inline-block;
}
.button[data-v-2311c06a]{
  padding: 5px 10px;
  font-size: 12px;
  border-radus: 2px;
}
/*content.vue渲染出来的css*/
.content[data-v-57bc25a0]{
  width: 1200px;
  margin: 0 auto;
}
.content .button[data-v-57bc25a0]{
  border-raduis: 5px;
}
登录后复制

对于上面的两种情况,可以明显看出来渲染后的结果大不相同。

虽然我们在content添加了想要修改button组件的样式的代码,但是仔细看,由于.content .button这句在末尾加的是content组件的scoped标记,最后这句其实根本作用不到我们想要的DOM节点上,所以这种情况我们在content内部写的任何样式都不会影响到button.vue组件,所以这就尴尬了。。。。

当然这个问题也是可以解决的,就是直接加全局样式可以修改到,但这势必会影响全部地方的组件;所以需要另外一种方法在content.vue组件内再加一个不带scoped属性的style标签,也就意味着要加两个style,一个用于私有样式,一个用于共有样式。这肯定是有点shit的,并且这两种解决方案都回避不了一个问题:权重!!!

//content.vue
<template>
  <p class="content">
    <p class="title"></p>
    <!-- v-button假设是上面定义的组件 -->
    <v-button></v-button>
  </p>
</template>
...
<style scoped>
  .content{
    width: 1200px;
    margin: 0 auto;
  }
</style>
<style>
  .content .button{
    border-raduis: 5px;
  }
</style>
登录后复制

这样符合规范么?貌似没看到不能这么写,并且这么写也确实生效了。。。但这样确实增加了思维的复杂度,有点苦恼啊。

总结scoped的渲染规则

总结一下scoped三条渲染规则

  1. 给HTML的DOM节点加一个不重复data属性(形如:data-v-2311c06a)来表示他的唯一性

  2. 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-2311c06a])来私有化样式

  3. 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性

解决方案

对于引用的三方库,如果对方使用了scoped,我们无力改变什么,如果确实需要修改他的样式最能在不加scoped的组件中修改样式,或者全局样式直接修改,这很粗暴!

对于自己维护的组件,一定要想清楚,组件的样式能否满足所有的情况。如果确实需要加,无疑会增加使用这个组件的开发同学的工作!

当然对于这个问题,如果诸君有更好的解决方案,请诸君TELL ME一下下!

趣事

在使用scoped一定要谨慎scoped的这个特性,本人以为这是一个BUG,就去提了issue ,结果尤大很霸气的回复
scoped设计的初衷就是不能让当前组件的样式修改其他任何地方的样式,因为设计如此。所以理所当然的这个issue已被干掉

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在Nodejs中有关crypto模块安全知识(详细教程)

在Angular中如何实现下拉框模糊查询功能

在js中如何实现登录需要滑动验证

以上是在vue中有关如何使用style的scoped属性的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

vue怎么给按钮添加函数 vue怎么给按钮添加函数 Apr 08, 2025 am 08:51 AM

可以通过以下步骤为 Vue 按钮添加函数:将 HTML 模板中的按钮绑定到一个方法。在 Vue 实例中定义该方法并编写函数逻辑。

vue中怎么用bootstrap vue中怎么用bootstrap Apr 07, 2025 pm 11:33 PM

在 Vue.js 中使用 Bootstrap 分为五个步骤:安装 Bootstrap。在 main.js 中导入 Bootstrap。直接在模板中使用 Bootstrap 组件。可选:自定义样式。可选:使用插件。

vue.js怎么引用js文件 vue.js怎么引用js文件 Apr 07, 2025 pm 11:27 PM

在 Vue.js 中引用 JS 文件的方法有三种:直接使用 &lt;script&gt; 标签指定路径;利用 mounted() 生命周期钩子动态导入;通过 Vuex 状态管理库进行导入。

vue中的watch怎么用 vue中的watch怎么用 Apr 07, 2025 pm 11:36 PM

Vue.js 中的 watch 选项允许开发者监听特定数据的变化。当数据发生变化时,watch 会触发一个回调函数,用于执行更新视图或其他任务。其配置选项包括 immediate,用于指定是否立即执行回调,以及 deep,用于指定是否递归监听对象或数组的更改。

vue返回上一页的方法 vue返回上一页的方法 Apr 07, 2025 pm 11:30 PM

Vue.js 返回上一页有四种方法:$router.go(-1)$router.back()使用 &lt;router-link to=&quot;/&quot;&gt; 组件window.history.back(),方法选择取决于场景。

vue多页面开发是啥意思 vue多页面开发是啥意思 Apr 07, 2025 pm 11:57 PM

Vue 多页面开发是一种使用 Vue.js 框架构建应用程序的方法,其中应用程序被划分为独立的页面:代码维护性:将应用程序拆分为多个页面可以使代码更易于管理和维护。模块化:每个页面都可以作为独立的模块,便于重用和替换。路由简单:页面之间的导航可以通过简单的路由配置来管理。SEO 优化:每个页面都有自己的 URL,这有助于搜索引擎优化。

怎样查询vue的版本 怎样查询vue的版本 Apr 07, 2025 pm 11:24 PM

可以通过以下方法查询 Vue 版本:使用 Vue Devtools 在浏览器的控制台中查看“Vue”选项卡。使用 npm 运行“npm list -g vue”命令。在 package.json 文件的“dependencies”对象中查找 Vue 项。对于 Vue CLI 项目,运行“vue --version”命令。检查 HTML 文件中引用 Vue 文件的 &lt;script&gt; 标签中的版本信息。

vue怎么用函数截流 vue怎么用函数截流 Apr 08, 2025 am 06:51 AM

Vue 中的函数截流是一种技术,用于限制函数在指定时间段内被调用的次数,防止性能问题。实现方法为:导入 lodash 库:import { debounce } from 'lodash';使用 debounce 函数创建截流函数:const debouncedFunction = debounce(() =&gt; { / 逻辑 / }, 500);调用截流函数,控制函数在 500 毫秒内最多被调用一次。

See all articles