Code前端首页关于Code前端联系我们

过渡技术治愈了我严重的代码清洁问题

terry 2年前 (2023-09-08) 阅读数 143 #Vue

背景介绍

透明传输是通信层面的概念,指的是通信时无论传输的业务内容是什么,只负责将传输的内容从源地址传输到目的地址,而不改变传输的内容。业务数据的内容。

其实透明转,我是第一次听上面主持人说的。从电气工程师开始,透明传输在机器通信中仍然被广泛使用。

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

当我听到透明转这个词时,我觉得有点熟悉。经过仔细考虑,我意识到我们的前端实际上使用的是透明传输,尤其是在基础打包的时候。

正面使用半透明转印

今天我就以Vue核心组件的封装过程为例,简单讲一下什么是透传。

相信很多前端er项目都会用到组件库,无论是ElementUI还是Ant Design,都没有关系。那么我们希望基于第三方组件库做一点定制。

例如,el-button 有一个 size 属性,用于控制按钮组件的大小。

属性 描述 类型 可选值 默认为
尺寸 尺寸 中号/小号/迷你

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

可以看到默认的尺寸比较大。然而,当设计师根据组件库提出自己的设计方案时,我们选择的默认按钮尺寸可能正好适合ElButtonElButtonmedium或其他值。这样,如果我不插入el-button,那么每个使用el-button的地方都必须写一个额外的属性size,如下所示:

// pageA.vue
<el-button size="medium">按钮1</el-button>
<el-button size="medium">按钮2</el-button>

// pageB.vue
<el-button size="medium">按钮3</el-button>
<el-button size="medium">按钮4</el-button>
 

显然每次使用el-button我都要写size属性,这太烦人了!

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

是的,这确实很烦人,那么如何摆脱它呢?答案是提供一个编程接口来更改组件的默认值。考虑到这一点,组件设计者通常会提供一个接口来设置默认值,例如xxx.setDefault(options)。那么ElementUI和Ant Design提供了这样的能力吗?据我观察,似乎并非如此。其实主要原因是Vue没有方便的方法将default属性更改为prop。但如果你没有方便的方法,并不意味着没有……

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

由于本文的主题是透明传输,所以我就不讲这种做法(或方法)了,有点牵强。

网友小王说:“好吧,我们就难度一下,把组件打包吧!”

好的,现在编辑!基本思想是封装一个自定义组件,在组件中调用el-button,并强制为el-button使用默认属性size="medium"

<template>
    <el-button :size="size">
        <slot />
    </el-button>
</template>

<script>
export default {
    name: "MyButton",
    props: {
        size: {
            type: String,
            default: 'medium'
        }
    }
}
</script>
 

精明的读者第一眼就会注意到这个组件有一个重大问题。除了size属性之外,完全没有提及如何处理其他属性和事件ElButton

小王说:“没关系,你需要什么?我来搞定!”

所以这个分量最后慢慢变成:

<template>
    <el-button
        :size="size"
        :type="type"
        :disabled="disabled"
        @click="onClick"
    >
        <slot />
    </el-button>
</template>

<script>
export default {
    name: "MyButton",
    props: {
        size: {
            type: String,
            default: "medium",
        },
        type: {
            type: String,
            default: "primary",
        },
        disabled: Boolean,
    },
    methods: {
        onClick() {
            this.$emit("click");
        },
    },
};
</script>
 

看起来有点悲伤,这个组件会更加冗余和复杂,因为我这里只添加了3个道具和1个事件。对于稍微复杂一点的组件,有几十个道具和事件可用,很随意!你身材匀称吗?另外,很多人还存在代码整洁的问题,这简直让人无法忍受!

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

冷静!当然,有一种方法可以做到这一点。框架强大的设计师游小游自然想到了这个场景,所以关注Vue官网文档中的inheritAttrs。

如何理解选项inheritAttrs(默认值为true)?我们知道,如果一个组件想要接受父组件的属性,它必须在props中进行预定义。例如,在前面的示例中,我在中预定义了三个属性,即sizetypedisabled,这意味着MyButton只接受三个prop

那么如果父组件传递了4个或更多prop怎么办?考虑这个例子:

实际上,roundautofocus都不受组件MyButton prop的支持,所以HTML反映的效果如下:

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

作为用户,应该希望roundnative-type="submit"能够转移到el-button以达到理想的效果。然而,roundnative-type="submit"只是挂在根元素attribute上,并没有真正发挥其作用!

PS:例如,当round属性应用到el-button时,button可以产生is-round class,产生圆角效果!

这意味着inheritAttrs的功能是那些props中没有定义的属性直接以attribute的形式作用于组件的根元素!

那么roundnative-type="submit" 如何继承呢?

首先不能让那些props无法识别的属性直接落在根元素上,所以需要将inheritAttrs设置为false

然后获取那些未被 props 识别的属性,并将它们直接连接到el-button。正好Vue提供了attr来获取这些属性,并且v-bind可以绑定对象本身,这一点很容易被忽视!

处理完属性的透明传递后,我们需要对事件进行处理,与$attrs类似,$listeners也可以在​​父组件中获取子组件事件的所有控制权,所以我们可以使用v-on 将这些事件监听器从父组件传递到以下组件级别。

看图可能会更好理解!

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

相当于MyButton是中间商不补差价,直接发消息!直观上,组件代码量明显减少,更重要的是可扩展性和可维护性变强了!

<template>
    <el-button
        v-bind="customizedAttrs"
        v-on="$listeners"
    >
        <slot />
    </el-button>
</template>

<script>
export default {
    name: "MyButton",
    inheritAttrs: false,
    props: {
        size: {
            type: String,
            default: "medium",
        },
    },
    computed: {
        customizedAttrs() {
            return {
                size: "medium",
                // 支持传过来的size覆盖默认的size
                ...this.$attrs,
            };
        },
    },
};
</script>
 

调用者的用户体验不受影响,感觉还是直接在使用el-button,传输属性和监控事件的用户体验完全没有改变!

总结

通过inheritAttrsv-bindv-on的组合,我们推出了一个支持透明下载的基础组件!本文以Button组件为例介绍透明传输。其实透传的使用范围远不止Button组件。借助透明转印技术,我们可以做更多美丽的事情!你的代码的整洁度怎么样?

一个透传技巧,治好了我的重度代码洁癖一个透传技巧,治好了我的重度代码洁癖

如果觉得这篇文章还不错,请点赞加关注(思南前端),衷心感谢您的支持。也欢迎您直接与我交流,我是老白夫期待与您共同进步!

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门