element-plus 第二期 钩子函数

833 阅读2分钟

2022/08/18

element-plus 第二期 钩子函数

概述

  • hooks/use-global-config
  • hooks/use-namespace
  • hooks/use-prop
  • hooks/use-common-props
  • hooks/use-locale
  • hooks/use-focus
  • hooks/use-attrs
  • hooks/use-delayed-toggle
  • hooks/use-deprecated
  • hooks/use-escape-keydown
  • hooks/use-floating
  • hooks/use-form-item
  • hooks/use-forward-ref
  • hooks/use-id
  • hooks/use-intermediate-render
  • hooks/use-lockscreen
  • hooks/use-modal
  • hooks/use-model-toggle
  • hooks/use-popper-container
  • hooks/use-prevent-global
  • hooks/use-restore-active
  • hooks/use-same-target
  • hooks/use-teleport
  • hooks/use-throttle-render
  • hooks/use-timeout
  • hooks/use-transition-fallthrough
  • hooks/use-z-index

Config Provider 全局配置

Element-plus 提供了配置全局选项的组件 ConfigProvider

  • locale 配置语言
  • size 全局组件大小
  • button 按钮全局配置
  • message 提示配置,例如:配置可同时显示的消息最大数量
  • namespace 配置命名空间,默认是 el

重新定义全局命名空间为 lsx

<!-- App.vue -->
<template>
  <el-config-provider namespace="lsx">
      <router-view />
  </el-config-provider>
</template>

use-global-config

由使用者定义全局配置选项,主要是两个方法provideGlobalConfiguseGlobalConfig

hooks/use-global-config/index.ts

方法说明参数
useGlobalConfig获取全局配置数据,类似于 injectuseGlobalConfig(key?:keyof ConfigProviderContext, defaultValue = undefined)
provideGlobalConfig生成全局配置数据, 类似于 provideprovideGlobalConfig(config: MaybeRef, app?:App, globacl = false)

其中 ConfigProviderContext

export type ConfigProviderContext = Partial<
  ExtractPropTypes<typeof configProviderProps>
>

configProviderPropsconfig-provider 组件接收的props

expamle

const globalConfig = useGlobalConfig('button') // 获取全局button的配置

use-namespace

规范化CSS命名方式,使用BEM风格(优化自己项目开发中的CSS命名规范,使其规范化)

/**
 * 生成CSS命名
 * @param block 块名称 
 * @returns
 */
export const useNamespace = (block: string) => {
  const globalConfig = useGlobalConfig('namespace')
  const namespace = computed(() => globalConfig.value || defaultNamespace)
  // block
  const b = (blockSuffix = '') =>
    _bem(unref(namespace), block, blockSuffix, '', '')
  // block+element -> element
  const e = (element?: string) =>
    element ? _bem(unref(namespace), block, '', element, '') : ''
  // block+modifier -> modifier
  const m = (modifier?: string) =>
    modifier ? _bem(unref(namespace), block, '', '', modifier) : ''
  // block+blockSuffix+element -> element
  const be = (blockSuffix?: string, element?: string) =>
    blockSuffix && element
      ? _bem(unref(namespace), block, blockSuffix, element, '')
      : ''
  // block+element+modifier -> modifier
  const em = (element?: string, modifier?: string) =>
    element && modifier
      ? _bem(unref(namespace), block, '', element, modifier)
      : ''
  // block+blockSuffix+modifier -> modifier
  const bm = (blockSuffix?: string, modifier?: string) =>
    blockSuffix && modifier
      ? _bem(unref(namespace), block, blockSuffix, '', modifier)
      : ''
  // block+blockSuffix+element+modifier -> modifier
  const bem = (blockSuffix?: string, element?: string, modifier?: string) =>
    blockSuffix && element && modifier
      ? _bem(unref(namespace), block, blockSuffix, element, modifier)
      : ''
  // 是非状态修饰
  const is: {
    (name: string, state: boolean | undefined): string
    (name: string): string
  } = (name: string, ...args: [boolean | undefined] | []) => {
    const state = args.length >= 1 ? args[0]! : true
    return name && state ? `${statePrefix}${name}` : ''
  }
  return {
    namespace,
    b,
    e,
    m,
    be,
    em,
    bm,
    bem,
    is,
  }
}

其中关键代码_bem方法,具体如下:

// 生成class命名
const _bem = (
  namespace: string, // 命名空间
  block: string, // 块名称
  blockSuffix: string, // 块名称后缀
  element: string, // 元素
  modifier: string // 修饰符
) => {
  let cls = `${namespace}-${block}` // 通过"-"连接块
  if (blockSuffix) {
    cls += `-${blockSuffix}` // 通过"-"连接块后缀
  }
  if (element) {
    cls += `__${element}` // 通过"__"连接元素
  }
  if (modifier) {
    cls += `--${modifier}` // // 通过"--"连接块修饰符
  }
  return cls
}

expamle

<template>
    <button
        ref="_ref"
        :class="[
          ns.b(), // lsx-button
          ns.m(_type), // lsx-button--primary
          ns.m(_size), // lsx-button--small
          ns.is('disabled', _disabled), // _disabled ? is-disabled: ""
          ns.is('loading', loading), // loading ? is-loading : ""
          ns.is('plain', plain), // plain ? is-plain : ""
          ns.is('round', round), // round ? is-round : ""
          ns.is('circle', circle), // circle ? is-circle : ""
        ]"
      >
       <-- -->
    </button>
</template>

<script setup>
const ns = useNamespace("button");//定义了button组件的命名空间,得到生成相应子元素命名的方法    
</script>

假设是非判断中只有 _disabledtrue ,其他为 false,则该button的class值为

<button class="lsx-button lsx-button--primary lsx-button--small is-disabled">...</button>

use-prop

提供一个函数 useProp,通过 vue 函数 getCurrentInstance 来获取当前组件实例接收到的 props 对应的值。

import { computed, getCurrentInstance } from 'vue'
import type { ComputedRef } from 'vue'

/**
 * 根据指定的 name 获取当前组件上 props 对应的 name 值
 * 能获取到当前组件实例上的 props(getCurrentInstance())
 * @param name string
 * @returns
 */
export const useProp = <T>(name: string): ComputedRef<T | undefined> => {
  const vm = getCurrentInstance()!
  return computed(() => vm.proxy?.$props[name] ?? undefined)
} 

examplae

const disabled = useProp<boolean>('disabled') // 组件自身的disabled

use-common-props

存放公共配置属性,useSizePropsuseSizeuseDisabled

  • useSizeProp:定义 size 的 prop;
  • useSize:获取当前组件的 size,其权重:自身size > 组件group的size -> formItem.size > form.size > 全局配置的size;返回一个计算属性,其值为 boolean;
  • useDisabled:获取组件的 disabled,其权重:组件自身的 disabled > 指定的外部的 diabled > form.disabled;

use-locale

  • useLocale:获取全局配置的语言

use-focus

  • useFocus 输入框聚焦