前端学习笔记(四)自定义组件控制自己的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>
相关推荐
mCell21 小时前
GSAP ScrollTrigger 详解
前端·javascript·动效
gnip21 小时前
Node.js 子进程:child_process
前端·javascript
excel1 天前
为什么在 Three.js 中平面能产生“起伏效果”?
前端
excel1 天前
Node.js 断言与测试框架示例对比
前端
天蓝色的鱼鱼1 天前
前端开发者的组件设计之痛:为什么我的组件总是难以维护?
前端·react.js
codingandsleeping1 天前
使用orval自动拉取swagger文档并生成ts接口
前端·javascript
石金龙1 天前
[译] Composition in CSS
前端·css
白水清风1 天前
微前端学习记录(qiankun、wujie、micro-app)
前端·javascript·前端工程化
Ticnix1 天前
函数封装实现Echarts多表渲染/叠加渲染
前端·echarts
用户22152044278001 天前
new、原型和原型链浅析
前端·javascript