vue3-单文件组件css功能(:deep,:slotted,:global,useCssModule,v-bind)

css作用域选择器标准化-:deep,:slotted,:global

:deep-穿透子组件内部,:slotted-影响插槽内容,:global-定义全局样式

javascript 复制代码
<template>
  <div class="parent-container">
    <h2>Parent Component</h2>
    
    <!-- 普通子组件 -->
    <ChildComponent />
    
    <!-- 带有插槽的子组件 -->
    <ChildWithSlot>
      <p class="slotted-content">This is slotted content!</p>
    </ChildWithSlot>

    <!-- 全局样式按钮 -->
    <button class="global-button">A Global Styled Button</button>
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
import ChildWithSlot from './ChildWithSlot.vue';
</script>

<style scoped>
.parent-container {
  padding: 20px;
  background-color: #f9f9f9;
}

/* 1. :deep() - 穿透到子组件内部 */
.parent-container :deep(.child-text) {
  color: red;
  font-weight: bold;
}

/* 2. :slotted() - 影响插槽内容 */
:slotted(.slotted-content) {
  background-color: lightblue;
  padding: 5px;
  border-radius: 3px;
}

/* 3. :global() - 定义全局样式 (即使在 scoped 内) */
:global(.global-button) {
  background-color: #42b883; /* Vue Green */
  color: white;
  border: none;
  padding: 10px 15px;
  cursor: pointer;
  border-radius: 5px;
}
</style>

ChildComponent.vue

javascript 复制代码
<template>
  <div class="child-wrapper">
    <p class="child-text">This text should be red and bold.</p>
  </div>
</template>

<style scoped>
.child-wrapper {
  padding: 10px;
  border: 1px solid #ccc;
}
.child-text {
  color: initial; /* This will be overridden by parent's :deep() */
}
</style>

ChildWithSlot.vue

javascript 复制代码
<template>
  <div class="slot-wrapper">
    <h4>Child With Slot:</h4>
    <slot></slot>
  </div>
</template>

<style scoped>
.slot-wrapper {
  margin-top: 20px;
  padding: 10px;
  background-color: #eaeaea;
  border-radius: 4px;
}
</style>

Composition API 集成 (useCssModule)

通过 useCssModule API 在 setup() 和 <script setup> 中访问注入的 class。使用了自定义注入名称的 <style module> 块,useCssModule 接收一个匹配的 module attribute 值作为第一个参数

javascript 复制代码
import { useCssModule } from 'vue'

// 在 setup() 作用域中...
// 默认情况下,返回 <style module> 的 class
useCssModule()

// 具名情况下,返回 <style module="classes"> 的 class
useCssModule('classes')
javascript 复制代码
<script setup lang="ts">
import { useCssModule } from 'vue'

const classes = useCssModule()
</script>

<template>
  <p :class="classes.red">red</p>
</template>

<style module>
.red {
  color: red;
}
</style>
Module默认情况-动态切换类

useCssModule结合computed,动态地根据状态(如 theme 是 light 还是 dark)来应用不同的CSS Modules类

javascript 复制代码
<template>
  <div :class="dynamicContainerClass">
    <h1 :class="styles.title">{{ title }}</h1>
    <p :class="styles.content">{{ content }}</p>
    <button @click="toggleTheme">Switch to {{ currentTheme === 'light' ? 'Dark' : 'Light' }} Theme</button>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';
import { useCssModule } from 'vue';

const title = ref('Themed Component');
const content = ref('This content changes its appearance based on the theme.');
const currentTheme = ref('light'); // 'light' or 'dark'

const styles = useCssModule(); // 获取 CSS Modules 对象

const toggleTheme = () => {
    currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light';
};

// 计算属性,根据当前主题返回相应的类名数组
const dynamicContainerClass = computed(() => [
    styles.container,
    currentTheme.value === 'light' ? styles.lightTheme : styles.darkTheme
]);
</script>

<style module>
.container {
    padding: 2rem;
    border-radius: 8px;
    transition: background-color 0.3s ease, color 0.3s ease; /* 平滑过渡 */
}

.lightTheme {
    background-color: #ffffff;
    color: #333333;
}

.darkTheme {
    background-color: #2d2d2d;
    color: #eeeeee;
}

.title {
    font-size: 1.8rem;
    margin-bottom: 1rem;
}

.content {
    font-size: 1rem;
    line-height: 1.6;
    margin-bottom: 1.5rem;
}
</style>
Module具名情况-分离样式

在复杂的组件中,将基础样式,布局样式,主题样式等多种独立的样式分离到不同的css modules中便于管理

javascript 复制代码
<template>
  <div :class="[base.container, layout.grid, theme.cardTheme]">
    <h2 :class="typography.heading">Card Title</h2>
    <p :class="typography.bodyText">Card Content</p>
  </div>
</template>

<script setup>
import { useCssModule } from 'vue';

// 分别获取不同功能的样式对象
const base = useCssModule('base');
const layout = useCssModule('layout');
const typography = useCssModule('typography');
const theme = useCssModule('theme');
</script>

<style module="base">
.container {
    box-sizing: border-box;
    /* Reset or base styles */
}
</style>

<style module="layout">
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1rem;
}
</style>

<style module="typography">
.heading {
    font-size: 1.5rem;
    font-weight: bold;
    margin-bottom: 0.5rem;
}
.bodyText {
    font-size: 1rem;
    line-height: 1.5;
}
</style>

<style module="theme">
.cardTheme {
    background-color: #f8f9fa;
    border: 1px solid #dee2e6;
    border-radius: 0.375rem;
    padding: 1.5rem;
}
</style>

v-bind动态绑定CSS变量

实际应用-对于按钮、进度条、滑块等控件,根据其状态(如加载进度、激活状态、悬停效果等)动态调整样式。

javascript 复制代码
<script setup>
import { ref, reactive } from 'vue';

const progressState = reactive({
    percentage: 30, // 当前进度百分比
    color: '#42b883'
});

// 模拟进度更新
setInterval(() => {
    progressState.percentage = (progressState.percentage + 1) % 101;
    if (progressState.percentage > 75) {
        progressState.color = '#e74c3c'; // 进度高时变红
    } else {
        progressState.color = '#42b883'; // 否则保持绿色
    }
}, 100);
</script>

<template>
  <div class="progress-container">
    <div class="progress-bar-bg">
      <div 
          class="progress-bar-fill" 
          :style="{ width: progressState.percentage + '%' }"
      ></div>
    </div>
    <p>Progress: {{ progressState.percentage }}%</p>
  </div>
</template>

<style scoped>
.progress-container {
    width: 100%;
    max-width: 400px;
    margin: 20px auto;
}

.progress-bar-bg {
    width: 100%;
    height: 20px;
    background-color: #eee;
    border-radius: 10px;
    overflow: hidden;
}

.progress-bar-fill {
    height: 100%;
    background-color: v-bind('progressState.color'); /* 动态颜色 */
    transition: width 0.3s ease, background-color 0.3s ease; /* 平滑过渡 */
    border-radius: inherit; /* 继承背景的圆角 */
}

p {
    text-align: center;
    margin-top: 10px;
}
</style>
相关推荐
是罐装可乐2 小时前
深入理解“句柄(Handle)“:从浏览器安全到文件系统访问
前端·javascript·安全
华科易迅2 小时前
Vue如何集成封装Axios
前端·javascript·vue.js
康一夏2 小时前
Next.js 13变化有多大?
前端·react·nextjs
糖炒栗子03262 小时前
前端项目标准环境搭建与启动
前端
不是az2 小时前
CSS知识点记录
前端·javascript·css
爱分享的阿Q2 小时前
GPT6-Spud-AGI前夜的豪赌
前端·easyui·agi
昵称暂无13 小时前
.NET 高级开发 | i18n 原理、实现一个 i18n 框架
javascript·c#·.net
西西小飞龙3 小时前
Less/Sass Mixins vs. Extend
前端·less·sass
syjy23 小时前
(含下载)BeTheme WordPress主题使用教程
前端·wordpress·wordpress建站