前端学习笔记(四)自定义组件控制自己的css

1、前言及背景

自己写的一个组件有至少3个页面在使用,组件中的部分文字颜色需要统一修改需要根据一个状态字段来显示不同颜色且不希望受父组件影响

注意:博主学习vue截止目前也就半年,如有知识错误之处还请指出不胜感激,祝学习开心快乐哈哈

2、deepseek查询

提问:vue3中使用插槽时如果通过子组件统一设置父组件中的插槽的class

答案:

方案有2个

一、插槽包裹层样式穿透

通过在子组件中为插槽‌添加包裹容器‌并设置class,利用CSS作用域穿透特性控制插槽内容样式

html 复制代码
<!-- 子组件 ChildComponent.vue -->
<template>
  <div class="child-wrapper">
    <div class="slot-container"> <!-- 定义插槽容器 -->
      <slot></slot>
    </div>
  </div>
</template>

<style scoped>
.slot-container :deep(div) { /* 穿透父组件插槽内容 */
  color: red;
  padding: 12px;
}
</style>

二、作用域插槽传递参数

通过‌作用域插槽‌将class参数传递给父组件,父组件动态绑定插槽元素的class

html 复制代码
<!-- 子组件 ChildComponent.vue -->
<template>
  <slot :slotClass="'custom-class'"></slot> <!-- 传递class参数 -->
</template>
html 复制代码
<!-- 父组件 ParentComponent.vue -->
<child-component>
  <template #default="{ slotClass }">
    <div :class="slotClass"> <!-- 动态绑定接收的class -->
      插槽内容
    </div>
  </template>
</child-component>

方案对比

选择方案时,若需‌完全由子组件控制样式‌,优先使用包裹层穿透方案;若需‌保留父组件样式调整灵活性‌,则采用作用域插槽传递参数。

3、具体实现方案

1)给插槽外面包装一个div

2)通过动态计算来设置slot外面div的class名字

3)不同的class里面通过deep选择到父组件可能用到的span和a并控制颜色

4、具体代码

html 复制代码
<!--代码片段-->
<template v-if="$slots.edit || $slots.view || $slots.publish">
    <div :class="classStatusColor">
      <slot v-if="!!$slots.edit" name="edit" :model="modelEdit"></slot>
    </div>
<template>
ts 复制代码
  const statusColor = ref(getStatusColor());
  const classStatusColor = computed(() => ({
    'slot-edit-container-draft': statusColor.value === STATUS_DRAFT,
    'slot-edit-container-waiting-approve': statusColor.value === STATUS_WAITING_APPROVE,
    'slot-edit-container-reject': statusColor.value === STATUS_REJECT,
    'slot-edit-container-publish': statusColor.value === STATUS_PUBLISH,
  }));
ts 复制代码
// 代码片段按照优先级设置颜色STATUS_REJECT > STATUS_DRAFT > STATUS_WAITING_APPROVE > STATUS_WAITING_APPROVE > STATUS_PUBLISH
function getStatusColor() {
    let values: DataValue[];
    //values = ............//自己处理逻辑

    // 空值处理
    if (values === undefined) {
      return STATUS_UNKNOWN;
    }
    let statusList: number[] = [];
    for (let i of values) {
      if (i.value.status === undefined) {
        statusList.push(STATUS_UNKNOWN);
      } else {
        statusList.push(i.value.status);
      }
    }

    if (statusList.includes(STATUS_REJECT)) {
      return STATUS_REJECT;
    }
    if (statusList.includes(STATUS_DRAFT)) {
      return STATUS_DRAFT;
    }
    if (statusList.includes(STATUS_WAITING_APPROVE)) {
      return STATUS_WAITING_APPROVE;
    }
    if (statusList.includes(STATUS_PUBLISH)) {
      return STATUS_PUBLISH;
    }
    return STATUS_UNKNOWN;
  }
html 复制代码
<style lang="less" scoped>
  // 红色是草稿状态
  .slot-edit-container-draft :deep(a) {
    color: rgb(238 102 102);
  }

  // 蓝色是待审核状态
  .slot-edit-container-waiting-approve :deep(a) {
    color: rgb(84 112 198);
  }

  // 橙色是驳回状态
  .slot-edit-container-reject :deep(a) {
    color: rgb(250 200 88);
  }

  // 黑色是已发布状态
  .slot-edit-container-publish :deep(a) {
    font-weight: black;
  }
</style>
相关推荐
张拭心9 分钟前
拭心 7 月日复盘|个体在 AI 时代的挑战
前端
这是个栗子19 分钟前
express-jwt报错:Error: algorithms should be set
前端·npm·node.js
Dolphin_海豚22 分钟前
vapor 的 IR 是如何被 generate 到 render 函数的
前端·vue.js·vapor
小妖66626 分钟前
Next.js 怎么使用 Chakra UI
前端·javascript·ui
胡西风_foxww32 分钟前
从数据丢失到动画流畅:React状态同步与远程数据加载全解析
前端·javascript·react.js·同步·异步·数据·状态
小一亿1 小时前
【0基础PS】Photoshop (PS) 理论知识
学习·平面·adobe·信息可视化·photoshop
阿华的代码王国2 小时前
【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
android·xml·java·前端·后端
慕y2742 小时前
Java学习第九十一部分——OkHttp
java·开发语言·学习
汪子熙2 小时前
Angular 最新的 Signals 特性详解
前端·javascript
Spider_Man2 小时前
前端路由双雄传:Hash vs. History
前端·javascript·html