element-plus源码学习-config-provider组件

671 阅读1分钟

使用

el-config-provider是给element-plus提供各种全局配置的组件,比如element-plus默认是英文,想要改为中文,通过下面配置

<template>
  <el-config-provider :locale="zhCn">
    <el-table mb-1 :data="[]" />
    <el-pagination :total="100" />
  </el-config-provider>
</template>

<script lang="ts" setup>
import { computed, ref } from 'vue'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
</script>

源码

源码

结构如下:

src
├── config-provider-props.ts   // 定义组件的props结构
├── config-provider.ts         // 组件的定义,这个组件不用vue单文件开发
├── constants.ts               // 定义组件的常量
└── hooks
    └── use-global-config.ts   // 核心hooks

代码解读:

// config-provider.ts 部分代码
const ConfigProvider = defineComponent({
  name: 'ElConfigProvider',
  props: configProviderProps,
  setup(props, { slots }) {
    const config = provideGlobalConfig(props) // 调用hooks
    return () => renderSlot(slots, 'default', { config: config?.value }) // 渲染default插槽
  },
})

因为config-provider组件并不需要渲染成什么DOM节点,所以这里主要使用setup函数里面返回一个箭头函数。

渲染插槽使用到的api:renderSlot(),该函数接受4个参数:

  • slots:一个包含所有插槽的对象。
  • name:要渲染的插槽的名称。
  • props:传递给插槽的 props。
  • fallback:当指定的插槽不存在时要渲染的备用内容。

hooks解读:

// hooks/use-global-config.ts 部分代码
export const provideGlobalConfig = (
  config: MaybeRef<ConfigProviderContext>, // config-provider组件接收到的props
) => {
  const provideFn = app?.provide ?? (inSetup ? provide : undefined); // provider函数

  const context = computed(() => {
    const cfg = unref(config)
    return cfg
  })
  
  // 提供配置上下文,key=Symbol()
  provideFn(configProviderContextKey, context)
  // 提供 locale 上下文,key=Symbol('localeContextKey')
  provideFn(localeContextKey, computed(() => context.value.locale));
  // 提供 namespace 上下文,key=Symbol('namespaceContextKey')
  provideFn(namespaceContextKey, computed(() => context.value.namespace))
  // 提供 zIndex 上下文,key=Symbol('zIndexContextKey')
  provideFn(zIndexContextKey,computed(() => context.value.zIndex))
  // 提供 size 上下文,key=Symbol('size')
  provideFn(SIZE_INJECTION_KEY, {size: computed(() => context.value.size || ''),})

  globalConfig.value = context.value
  return context
}

在这里就是提供各种provide(),在需要的地方再inject()

比如el-button中使用到如下代码

const globalConfig = useGlobalConfig('button');

useGlobalConfig()就是下面的代码

const config = getCurrentInstance()
    ? inject(configProviderContextKey, globalConfig)
    : globalConfig