css 如何在Vue Style中将变量传入类名

ztigrdn8  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(112)

正如this QA提到的,我们可以在less中将变量作为类名。
但是如何在Vue中实现呢?

<script setup>
const uuid = 'data-v-123'
</script>

<style lang="less">
@dynamicVar: xxxx; // how to pass uuid as a less variable?

.@{dynamicVar} {
  color: red;
}

// Or, how to pass a vue variable as a class name?
.[dynamicVar] { // this is the placement I want to inject
  color: red;
}
</style>

这里我有一个Popover组件,它在每个表cloumn中使用:
table-tooltip
我想在Vue3(Vite)中创建一个随机字符串作为CSS类名。
在vue中,我们可以通过Vue的API getCurrentInstance().type.__scopeId获取组件的作用域id,所以这里是共识:作用域ID是一个唯一字符串,每个组件都有一个作用域ID,并与其他组件不同。
因此,我们可以使用作用域id作为组件的唯一类名,因此我们将其应用于组件的类列表。
但有一个问题:如何为这个唯一的类名定义样式?
我们知道它是动态的,并且在Vite构建代码之前,我们不知道是否将某个字符串写入<style></style>工作表。
以下是ElementUi ElTooltip组件的演示。uuid变量是我想用作类名的东西。
你可以看到,有一种方法可以使用v-bind:uuid="''",将唯一的类名称作为html数据集属性,

<template>
<el-table :[uuid]="''">
</el-table>
</template>

<script setup>
const uuid = 'data-123'
</script >

<style scoped>
.el-table:deep { // :deep is the scopeId
  background-color: red !important
}
</style>

Vite将把这一点纳入:

<div class="el-table" data-123>
</div>

<style>
.el-table[data-v-123]{ 
  background-color: red !important
}
</style>

但是这不能用于ElTooltip,首先,你不能使用scoped作为样式,因为工具提示组件被应用到body中。
其次,在这种情况下,数据集不会应用到html数据集属性中,可能是ElementUi过滤了它。你可以在演示中看到这一点。
所以现在只剩下一个幻想,那就是让Vite把这个变量编译成一个类名。
好吧,有一种方法可以做到这一点,但不是很接近原始的想法,那就是Vue的模块CSS:

<template>
<el-table :class="[{$styles.table}]">
</el-table>
</template>

<style module>
.table{
  background-color: red !important
}
</style>

Vite将把这一点纳入:

<div class="_table_1ok_2">
</div>

<style>
._table_1ok_2{ // somethins like this, just for demo 
  background-color: red !important
}
</style>

这就是我们想要的吗好吧,坐下。当有嵌套样式时,我们需要定义:

<template>
<el-tooltip :popper-class="{$styles.table}">
  <div class="text-wrapper">
    <span class="text-inner">
    </span>
  </div>
</el-tooltip>
</template>

<style module>
.el-tooltip{
  background-color: red !important
  .text-wrapper {
    border: 1px solid yellow;
    .text-inner {
      font-size: 24px;
    }
  }
}
</style>

Vite将把这一点纳入:

<div class="_el-tooltip_1ok_2">
  <div class="_text-wrapper_mono1">
    <span class="_text-inner_mmxr">
    </span>
  </div>
</div>

<style>
._el-tooltip_1ok_2{
  background-color: red !important
}
._el-tooltip_1ok_2 ._text-wrapper_mono1 {
  border: 1px solid yellow;
}
._el-tooltip_1ok_2 ._text-wrapper_mono1 ._text-inner_mmxr {
  font-size: 24px;
}
</style>

这不是我们想要的,我们只绑定el-tooltip模块的类名,而不是孩子的,所以我们需要它被编译成这样:

<style>
._el-tooltip_1ok_2{
  background-color: red !important
}
._el-tooltip_1ok_2 .text-wrapper {
  border: 1px solid yellow;
}
._el-tooltip_1ok_2 .text-wrapper .text-inner {
  font-size: 24px;
}
</style>

好吧,Vue允许我们这样做,如果我们使用:global() commant:

<style module>
.el-tooltip{
  background-color: red !important
  :global(.text-wrapper) {
    border: 1px solid yellow;
    :global(.text-inner) {
      font-size: 24px;
    }
    :global(.Another-Child-Class-Name) {
      // your code
    }
  }
}
</style>

你看,我们需要用:global逗号来 Package 类名。但是我们不能只 Package 一个父类名称,而是将所有类名称都 Package 在父类名称中。如果我们不把全局命令 Package 起来,Vite就不会把这些子类的名字当作全局样式。
你不觉得这很无聊吗?
现在我们又回到了之前讨论的主题。我们如何才能做到这一点?

toe95027

toe950271#

如果只想在模板(文件)中使用类,
考虑使用'scoped'属性

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

https://vuejs.org/api/sfc-css-features.html#scoped-css
否则,如果你想保持类的名称,简单地不要使用模块属性,它会改变你的类的名称以保持它们的唯一性。
https://vuejs.org/api/sfc-css-features.html#css-modules

相关问题