前端学习笔记(四)自定义组件控制自己的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>
相关推荐
cypking21 分钟前
Vue 3 + Vite + Router + Pinia + Element Plus + Monorepo + qiankun 构建企业级中后台前端框架
前端·javascript·vue.js
烤麻辣烫1 小时前
黑马程序员苍穹外卖(新手)DAY6
java·开发语言·学习·spring·intellij-idea
whale fall1 小时前
【剑雅14】笔记
笔记
雨雨雨雨雨别下啦1 小时前
【从0开始学前端】vue3简介、核心代码、生命周期
前端·vue.js·vue
simon_93491 小时前
受够了压缩和收费?我作为一个码农,手撸了一款无限容量、原图直出的瀑布流相册!
前端
e***87702 小时前
windows配置永久路由
android·前端·后端
星空的资源小屋2 小时前
跨平台下载神器ArrowDL,一网打尽所有资源
javascript·笔记·django
Xudde.3 小时前
Quick2靶机渗透
笔记·学习·安全·web安全·php
Dorcas_FE3 小时前
【tips】动态el-form-item中校验的注意点
前端·javascript·vue.js
小小前端要继续努力3 小时前
前端新人怎么更快的融入工作
前端