背景介绍
透明传输是通信层面的概念,指的是通信时无论传输的业务内容是什么,只负责将传输的内容从源地址传输到目的地址,而不改变传输的内容。业务数据的内容。
其实透明转,我是第一次听上面主持人说的。从电气工程师开始,透明传输在机器通信中仍然被广泛使用。
当我听到透明转这个词时,我觉得有点熟悉。经过仔细考虑,我意识到我们的前端实际上使用的是透明传输,尤其是在基础打包的时候。
正面使用半透明转印
今天我就以Vue核心组件的封装过程为例,简单讲一下什么是透传。
相信很多前端er项目都会用到组件库,无论是ElementUI还是Ant Design,都没有关系。那么我们希望基于第三方组件库做一点定制。
例如,el-button
有一个 size
属性,用于控制按钮组件的大小。
属性 | 描述 | 类型 | 可选值 | 默认为 |
---|---|---|---|---|
尺寸 | 尺寸 | 弦 | 中号/小号/迷你 | – |
可以看到默认的尺寸比较大。然而,当设计师根据组件库提出自己的设计方案时,我们选择的默认按钮尺寸可能正好适合ElButton
的ElButton
medium或其他值。这样,如果我不插入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
中进行预定义。例如,在前面的示例中,我在中预定义了三个属性,即size
、type
、disabled
,这意味着MyButton
只接受三个prop
。
那么如果父组件传递了4个或更多prop
怎么办?考虑这个例子:
实际上,round
和autofocus
都不受组件MyButton
prop
的支持,所以HTML
反映的效果如下:
作为用户,应该希望round
和native-type="submit"
能够转移到el-button
以达到理想的效果。然而,round
和native-type="submit"
只是挂在根元素attribute
上,并没有真正发挥其作用!
PS:例如,当round
属性应用到el-button
时,button
可以产生is-round
class
,产生圆角效果!
这意味着inheritAttrs
的功能是那些props
中没有定义的属性直接以attribute
的形式作用于组件的根元素!
那么round
和 native-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
,传输属性和监控事件的用户体验完全没有改变!
总结
通过inheritAttrs
、v-bind
和v-on
的组合,我们推出了一个支持透明下载的基础组件!本文以Button
组件为例介绍透明传输。其实透传的使用范围远不止Button
组件。借助透明转印技术,我们可以做更多美丽的事情!你的代码的整洁度怎么样?
如果觉得这篇文章还不错,请点赞加关注(思南前端),衷心感谢您的支持。也欢迎您直接与我交流,我是老白夫期待与您共同进步!
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。