• 利用css var函数让你的组件样式输出规范样式API,可定制性更高;


    我们平时在使用Elementui Antdesing这些UI库时,难免会碰到使用deep强行侵入式去修改组件内部样式的情况;
     
    比如下列代码,我们需要把ant的分页样式进行高度自定义,就得使用deep去修改;
     
    这种实现方式确实能够达到我们的目的,但在开发时确总觉得不太合适:
    1、他属于强行入侵组件内部去修改,虽然不会有大问题,但总觉得这种取巧方式有点不可取。
    2、每次写deep时需要手动检查DOM元素进行编辑,UI文档中并不会有相关API文档;
     
    为了解决心中的这两个结症,趁最近写组件的机会探索了下CSS 的var函数,发现他可以很好的解决以上问题。
     
    利用var函数我们可以具体解决组件开发的以下问题:
     
    1、组件样式自定义可以更加个性化
     
    2、现在很多组件库实现一些样式控制还是依靠props传参的形式,这种var函数结合Style可完全避免props传参的情况,把样式跟props区分开;
     
    3、在组件文档中可明确定制样式属性API;使组件样式可以跟Props属性一样以传参概念去进行高度定制,在使用组件样式时不需要像使用deep一样打开f12去一层一层的找
     
    4、不会侵入式的改动组件内部样式
     
    5、这个方案与deep互不排斥,如果开放的样式API不够用还是可以继续使用deep;
     
    看下面需求,是如何利用css var函数实现一个可自定义大小,颜色,以及子元素样式的卡片
     上代码
    复制代码
    //Card.vue
    <template>
        <div class="card">
            <img class="card-img" :src="img" />
            <p class="card-desc">{{ desc }}p>
        div>
    template>
    <style lang="scss" scoped>
        .card {
            // 这些以"--"开头的变量就是我们开放可自定义的样式属性了,可以在组件使用文档中明确开放
            //卡片根元素样式
            --width: 150px;
            --height: auto;
            --border-size: 1px;
            --border-color: #ccc;
            --border-radius: 5px;
            --bg: #eee;
            // 图片可定样式
            --img-width: 130px;
            --img-height: 130px;
            --img-radius: 50%;
            // 卡片描述样式
            --desc-size: 16px;
            --desc-line-height: 32px;
            --desc-color: #333;
    
            height: var(--height);
            width: var(--width);
            border: var(--border-size) solid var(--border-color);
            border-radius: var(--border-radius);
            background: var(--bg);
            padding: 10px;
            &-img {
                width: var(--img-width);
                height: var(--img-height);
                border-radius: var(--img-radius);
                overflow: hidden;
            }
            &-desc {
                font-size: var(--desc-size);
                color: var(--desc-color);
                line-height: var(--desc-line-height);
                text-align: center;
            }
        }
    style>
    复制代码

     

    这时候我们在API文档则可明确规定样式定制属性了:
    组件使用方式:
    复制代码
    //demo.vue
    <template>
        <div >
            <Card desc="我是默认的样式我是默认的样式我是默认的样式" :img="img" />
            <Card class="card_1" desc="自定义样式,子元素图片变小了" :img="img" />
            <Card class="card_2" desc="自定义样式,圆角没了,描述字变小了,高度高了" :img="img" />
        div>
    template>
    <script>...script>
    <style lang="scss" scoped>
        .card_1 {
            --width: 100px;
            --height: 200px;
            --border-radius: 20px;
            --img-width: 80px;
            --img-height: 50px;
            --img-radius: 10px;
            --desc-color: #f00;
            --desc-size: 12px;
            --desc-line-height: 21px;
        }
    
        .card_2 {
            --height: 300px;
            --border-radius: 0px;
            --bg: #fff;
            --img-radius: 50px;
            --desc-size: 14px;
            --desc-line-height: 21px;
        }
    style>
    复制代码

     

    以上就是一个基本的组件实现;
    还种情况我们在使用UI库时也会碰到需要使用Props传过来计算的参数,比如下列代码:

     这种我们也可以把这些全提出来使用style属性。让样式与js参数彻底隔离

    复制代码
    //demo.vue
      <template>
            <card
                desc="我是默认的样式我是默认的样式"
                :img="img"
                :style="hoverStyle"
                @mouseout="hoverStyle = {}"
                @mouseover="handleHover"
            />
    template>
    <script setup>
        let hoverStyle = ref({});
        const handleHover = () => {
            hoverStyle.value = { '--bg': '#f0f', '--width': '180px' };
        };
    script>
    复制代码

     

    我们在组件内

    JS可以使用props.style获取到设置的值,
    css中可以使用calc变量与var结合去计算你想要的值
    复制代码
    //card.vue
    <template>
        <div class="card" :style="style">
            {{ width }}
            <img class="card-img" :src="img" />
            <p class="card-desc">{{ desc }}p>
        div>
    template>
    <script setup>
        const $props = defineProps({
            img: {
                type: String,
                default: '',
            },
            desc: {
                type: String,
                default: '',
            },
            style: {
                type: Object,
                default: () => ({}),
            },
        });
        //假如你在js中需要用到宽度
        let width = computed(() => {
            return parseInt($props.style['--width'] || 150);
        });
    script>
    <style lang="scss" scoped>
    .card{
        ...
        //假如你有个子级元素需要基于宽度计算
        .item{
            width: calc(var(--width) - 100)
        }
        ...
    }
    style>
    复制代码

     

    但是这种实现有命名空间的问题
    所以需要稍微注意下变量命名,最好加独有的命名规则。防止变量覆盖;
    //比如这样
    .ch-card{
        --ch-card-width:100px;
        --ch-card-height:100px;
    }

     

    总结下这种方案的优缺点:
    优点
    1、组件样式自定义可以更加个性化
    2、现在很多组件库实现一些样式控制还是依靠props传参的形式,这种var函数结合Style可完全避免props传参的情况,把样式跟props区分开;
    3、在组件文档中可明确定制样式属性API;使组件样式可以跟Props属性一样以传参概念去进行高度定制,在使用组件样式时不需要像使用deep一样打开f12去一层一层的找
    4、不会侵入式的改动组件内部样式
    5、这个方案与deep互不排斥,如果开放的样式API不够用还是可以继续使用deep;
     
    缺点:
    1、开发组件时会工作量会增大,但是磨刀不误砍柴功
    2、命名空间问题导致命名会有点长。
     
    欢迎分享更好的解决方案。
  • 相关阅读:
    pyinstaller 错误排查的验证史
    大数据开发集群搭建
    RIAC-V架构开发——CSR指令访问控制与状态寄存器的两种方式(寄存器名字、寄存器编号)
    数据结构:AVL树
    NuGet包使用方法
    深入理解Java虚拟机-垃圾收集器与内存分配策略
    色彩空间介绍
    webpack简单配置(基于vue3配置)
    [C语言] 自制的贪吃蛇游戏
    给电热水器瘦个身,让它好看更好用,云米电热水器Air2 Mini体验
  • 原文地址:https://www.cnblogs.com/hrw3c/p/17387649.html