[ Element plus源码笔记四(button组件3) | 青训营笔记]

365 阅读1分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 七 天

一、use-botton.ts解析(packages\components\button\src\button.ts)

1.use-button.ts内容主要是对button组件全局提供方法和其对应的ts类型约束等等的一个汇总集合。 其中第一个会用到的就是uesButton方法。该方法主要是对button进行一个初始化,利用useDeprecated方法传入信息并且监听props.type属性是否为text,为text则报错

import { Text, computed, inject, ref, useSlots } from 'vue'
import {
  useDeprecated,
  useDisabled,
  useFormItem,
  useGlobalConfig,
  useSize,
} from '@element-plus/hooks'
import { buttonGroupContextKey } from '@element-plus/tokens'

import type { SetupContext } from 'vue'
import type { ButtonEmits, ButtonProps } from './button'

export const useButton = (
  props: ButtonProps,
  emit: SetupContext<ButtonEmits>['emit']
) => {
  useDeprecated(
    {
      from: 'type.text',
      replacement: 'link',
      version: '3.0.0',
      scope: 'props',
      ref: 'https://element-plus.org/en-US/component/button.html#button-attributes',
    },
    computed(() => props.type === 'text')
  )

  const buttonGroupContext = inject(buttonGroupContextKey, undefined)
  const globalConfig = useGlobalConfig('button')
  const { form } = useFormItem()
  const _size = useSize(computed(() => buttonGroupContext?.size))
  const _disabled = useDisabled()
  const _ref = ref<HTMLButtonElement>()
  const slots = useSlots()

  const _type = computed(() => props.type || buttonGroupContext?.type || '')
  const autoInsertSpace = computed(
    () => props.autoInsertSpace ?? globalConfig.value?.autoInsertSpace ?? false
  )

  // add space between two characters in Chinese
  const shouldAddSpace = computed(() => {
    const defaultSlot = slots.default?.()
    if (autoInsertSpace.value && defaultSlot?.length === 1) {
      const slot = defaultSlot[0]
      if (slot?.type === Text) {
        const text = slot.children as string
        return /^\p{Unified_Ideograph}{2}$/u.test(text.trim())
      }
    }
    return false
  })

  const handleClick = (evt: MouseEvent) => {
    if (props.nativeType === 'reset') {
      form?.resetFields()
    }
    emit('click', evt)
  }

  return {
    _disabled,
    _size,
    _type,
    _ref,
    shouldAddSpace,
    handleClick,
  }
}

2.useButton里面的useDeprecated方法要把我气死,看老半天想说他这样做的目的是什么,后来才看出他的存在的意义是为了提醒button组件的text属性已经被弃用了,现在是用link方法,真的服了。

捕获.JPG 同样的也可以在Selet组件suffix-transition属性可以看到,被弃用的属性就会用这种方式去提示用户。因为他也存在在button源码里面,我就也浅浅介绍一下。

首先我们可以看到在useDeprecated方法里面传递的第二个参数是计算属性,计算属性他会返回一个变量,这个变量会根据你里面的式子的某个属性(在这边是props.type)而自己计算变化。在这个里面呢,他因为这个等式一直是处在false的,当属性变化时,他因为还是不等于text就还是fales,知道type等于text了,他的值是true了,useDeprecated里的watch被触发,val的值改变了,变为true了,所以就会执行下面的debugwarn方法,去获取到前面传递的组件信息去告诉用户该属性被弃用的信息。

export const useDeprecated = (
  { from, replacement, scope, version, ref, type = 'API' }: DeprecationParam,
  condition: MaybeRef<boolean>
) => {
  watch(
    () => unref(condition),
    (val) => {
      if (val) {
        debugWarn(
          scope,
          `[${type}] ${from} is about to be deprecated in version ${version}, please use ${replacement} instead.
For more detail, please visit: ${ref}
`
        )
      }
    },
    {
      immediate: true,
    }
  )
}