在阅读文章之前,我曾经默认你曾经把握了Vue3.0
的根本应用,文章中次要剖析其中组件开发过程中的思路以及一些Api
的解说。心愿这篇文章能帮忙你更加的理解Element3
和Vue3.0
的应用和组件的开发能带来一些帮忙。
Template
废话也就不多赘述了,首先在下面所说的Element3
Git地址上拉取最新源码,之后在package
文件夹中找到button
文件夹下的Button.vue
,这个组件就是介绍第一个组件<el-button/>
。对于tempalte
方面就不多赘述了大略内容如下:
<template> <button class="el-button" :class="classes" :type="nativeType" :disabled="buttonDisabled || loading"> <i class="el-icon-loading" v-if="loading"></i> <i :class="icon" v-else-if="icon"></i> <span v-if="$slots.default"> <slot></slot> </span> </button></template>
上述构造中的loading
就不必多说了这里也是蛮艰深的,这个中央优先展现的是loading
,其次才是icon
图标,在Button
组件中还应用了$slots.default
该值指向的是插入以后组件的默认slot
,也就是常说的匿名slot
。这里用了一个很奇妙的手法就是,如果匿名组件存在的下才会应用slot
而不是间接吧slot
挂载组件中。这就很Nice~
props
button
动静绑定了calss、type、disabled
这个中央稍后再说,先标记一下,首先看下组件的入参(即:props
):
export default { props: { // 管制按钮大小 size: { type: String, validator(val) { if (val === '') return true return ['medium', 'small', 'mini'].indexOf(val) !== -1 } }, // 管制按钮类型 type: { type: String, validator(val) { return ( ['primary', 'success', 'warning', 'danger', 'info', 'text'] .indexOf(val) !== -1 ) } }, // 原生类型 nativeType: { type: String, default: 'button' }, // 是否奢侈按钮 plain: Boolean, // 是否圆角按钮 round: Boolean, // 是否圆形circle circle: Boolean, // 是否loading loading: Boolean, // 是否禁用 disabled: Boolean, // 图标类名 icon: String }};
通过下面的源码中能够看出size
和type
参数应用了自定义校验器(validator
),如果没有仔细阅读过Vue
文档的同学可能对validator
会有些许的生疏,validator
能够在办法能够更加准确的标准参数的值,如size
中只能传入medium,small,mini
。validator
办法返回的是一个boolean
值,当没有传入规定的值,则会抛出谬误有效的道具
。也就时说validator
会依据如果返回的值为true
则标识验证通过,返回谬误即验证失败。
仔细的小伙伴或者曾经发现了,其中蕴含属性native-type
原生属性也挂载了下来,然而这个值并没有应用validator
进行值的校验,可能在Element3
开发人员可能为了不便当前的拓展吧,如果原声中native-type
增加其余的值依赖组件库的我的项目即能够间接应用,无需更改组件库局部,同时也不心愿组件库去影响原生的某些属性。
笔者也看了一下文档在Element3
中Button
的文档中,提供autofocus
属性,然而在组件中却没有接管这个这个属性,咱们这个时候再次看下HTML
局部,在tempalte
就间接是button
标签了,所以当咱们在<el-button autofocus>
的时候autofocus
就曾经被挂载下来了。
逻辑解决
介绍完参数局部之后接下来咱们持续向下看一下setup
,通过Vue3.0
的改良setup
曾经承载了页面中大部分的逻辑,所以el-button
也是天然。
import { useGlobalOptions } from '../../src/use/globalConfig';import { toRefs, inject, computed } from 'vue'export default { setup(props) { const { size, disabled } = toRefs(props) const buttonSize = useButtonSize(size) const buttonDisabled = useButtonDisabled(disabled) const classes = useClasses({ props, size: buttonSize, disabled: buttonDisabled }) return { buttonDisabled, classes } }}
因为在setup
中是没有this
所以setup
的第一个参数即是props
传入的参数属性参数,但获取到的对象是一个一般对象无奈实现双向绑定,通过toRefs
转换成了绑定对象。
buttonSize
在setup
对class
进行了对立的解决,那么咱们就看下这部分的内容,办法中首先解决的是buttonSize
,具体代码如下。
const useButtonSize = (size) => { // 获取以后组件实例 const globalConfig = useGlobalOptions() return computed(() => { const elFormItem = inject('elFormItem', {}) return size?.value || elFormItem.elFormItemSize || globalConfig.size })}
src/use/globalConfig
export function useGlobalOptions() { // 获取以后组件实例 const instance = getCurrentInstance() if (!instance) { console.ware('useGlobalOptions must be call in setup function') return } return instance.appContext.config.globalProperties.$ELEMENT || {}}
在useButtonSize
办法中通过专用办法获取到以后组件的示例,如果以后组件的实例存在的话则通过全局属性,获取到以后组件的全局信息(组件全局信息切实初始化时手动配置的信息,名为$ELEMENT
),若没有会获取到全局信息,则默认返回一个空对象。之后通过inject
接管父级elFormItem
传递过去的数据,并传入一个空对象作为默认值。
实现上述操作之后,在useButtonSize
办法中通过计算属性,获取到size
属性值,其优先级为props > elFormItem > globalConfig
,最初将计算结果返回进来。
useButtonDisabled
解决完上述之后就解决了一下按钮的是否可用款式useButtonDisabled
,具体代码如下:
const useButtonDisabled = (disabled) => { return computed(() => { const elForm = inject('elForm', {}); return disabled?.value || elForm.disabled; });};
其实这里的解决逻辑和解决button
的size
是差不多的,这里对代码就不多赘述了,这里同样是返回了所获取到的值。这里接管的不再是elFormItem
的值,而是elForm
的值,通过这里能够得出,Element3
在elForm
传入button
会使整个表单全副都禁用。
注:对于inject所接管的值,这里就不多赘述,剖析其组件时会进行解说
useClasses
获取到所有的参数之后,则是通过useClasses
办法对立解决class
名称:
const useClasses = ({ props, size, disabled }) => { return computed(() => { return [ size.value ? `el-button--${size.value}` : '', props.type ? `el-button--${props.type}` : '', { 'is-plain': props.plain, 'is-round': props.round, 'is-circle': props.circle, 'is-loading': props.loading, 'is-disabled': disabled.value } ] })}
对于class
动静渲染这里,应用了计算属性,而不是一一对应绑定的,这样做的益处是能够对立保护其class
的款式,还有点能够说的就是,在渲染class
的时候,应用的是数组嵌套对象的模式,可能笔者比拟菜,还没有用过这种形式动静渲染class
,通过代码能够明确的看出useClasses
办法只是简略的通过计算数据对所有相干的class
名称进行了对立的解决。针不戳~
总结
上述代码曾经是整个el-button
组件的全副,尽管是一个很简略的组件,然而却能在外面学到一些货色,比方Vue3.0
的Provide/Inject
,整体代码思路清晰代码构造简略,都是咱们值得学习的中央。
哪有什么岁月静好,不过是有人替你负重前行。感激为Element3
默默付出的程序大佬们。
如果大家感兴趣的话就点击下方连贯,Star
一下吧。
Element3 Git地址
Element3 官网文档