element-plus 架构 - Config Provider 全局设置

[复制链接]
发表于 2026-2-11 12:27:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
官方文档:Config Provider 全局设置
1,先容

在组件库的计划中,最常见的全局设置是 z-index 和 size


  • z-index:同一管理弹出层(dialog, message, loading)等组件的层级。
  • size:同一管理表单位素巨细。
这些都属于全局设置项,可以Config Provider 全局设置来实现。
2,使用

全局设置项有2种引入方式。但都是调用同一个全局设置函数 provideGlobalConfig 实现的,背面会具体先容。
1,完备引入
  1. import { createApp } from 'vue'
  2. import ElementPlus from 'element-plus'
  3. import App from './App.vue'
  4. const app = createApp(App)
  5. app.use(ElementPlus, { size: 'small', zIndex: 3000 })
复制代码
相当于在element-plus的install 方法中,调用了provideGlobalConfig()
  1. const install = (app, options) => {
  2.   // ...
  3.   if (options) provideGlobalConfig(options, app, true)
  4.   // ...
  5. }
复制代码
2,按需引入
  1. <template>
  2.   <el-config-provider :size="size" :z-index="zIndex">
  3.     <app />
  4.   </el-config-provider>
  5. </template>
  6. <script>
  7. import { defineComponent } from 'vue'
  8. import { ElConfigProvider } from 'element-plus'
  9. export default defineComponent({
  10.   components: {
  11.     ElConfigProvider,
  12.   },
  13.   setup() {
  14.     return {
  15.       zIndex: 3000,
  16.       size: 'small',
  17.     }
  18.   },
  19. })
  20. </script>
复制代码

  • 相当于在el-config-provider组件中,调用了provideGlobalConfig()
  • 假如将根组件作为el-config-provider的子组件传入,也相当于全局引入。
   el-config-provider组件,传入指定的设置项props,在子组件中见效
  3,全局设置的实现

如今明确了:

  • 完备引入通过 install 方法调用provideGlobalConfig(),
  • 按需引入通过 el-config-provider 组件调用provideGlobalConfig(),
install 方法没什么好说的,以是先先容下el-config-provider 组件,再来具体先容provideGlobalConfig()。
3.1,el-config-provider

   组件路径:packages\components\config-provider\src\config-provider.ts
代码稍微做了简化。
  1. import { defineComponent, renderSlot } from 'vue'
  2. import { provideGlobalConfig } from './hooks/use-global-config'
  3. const ConfigProvider = defineComponent({
  4.   name: 'ElConfigProvider',
  5.   // locale | size | zIndex | namespace | button | message 等
  6.   props: configProviderProps,
  7.   setup(props, { slots }) {
  8.     const config = provideGlobalConfig(props)
  9.     return () => renderSlot(slots, 'default', { config: config?.value })
  10.   },
  11. })
  12. export default ConfigProvider
复制代码
renderSlot

renderSlot()和h('div', xxx) 一样,会返回 VNode,但参数不同等。
   可以在 setup() 中返回渲染函数来创建组件
  1. export declare function renderSlot(
  2.         slots: Slots,
  3.         name: string,
  4.         props?: Data,
  5.         fallback?: () => VNodeArrayChildren,
  6.         noSlotted?: boolean
  7. ): VNode;
复制代码
紧张先容前3个参数:

  • slots:父组件传入的插槽内容
  • name:具名插槽的名称
   带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 slot 出口会隐式地定名为“default”
  以是 renderSlot(slots, 'default', { config: config?.value }) 界说的是默认插槽

  • props:传给父组件的 props
联合以上,Config Provider 组件假如使用 template 界说,大抵如下
  1. <template>
  2.   <div>
  3.         <slot :config="config"></slot>
  4.   </div>
  5. </template>
  6. <script lang="ts" setup>
  7. const config = provideGlobalConfig(props)
  8. </script>
复制代码
  关于传给父组件的 props 的举例:
  1. <!-- <MyComponent> 子组件 -->
  2. <div>
  3.   <slot :text="greetingMessage" :count="1"></slot>
  4. </div>
  5. <!-- 父组件 -->
  6. <MyComponent v-slot="slotProps">
  7.   {{ slotProps.text }} {{ slotProps.count }}
  8. </MyComponent>
复制代码
3.2,provideGlobalConfig

先先容依靠的变量和函数
1,界说全局设置对象globalConfig
  1. // 全局配置对象
  2. const globalConfig = ref()
  3. // 全局配置依赖注入 provide/inject 的 key
  4. const configProviderContextKey = Symbol()
复制代码
2,获取全局设置的 hook 函数


  • useGlobalConfig()直接调用,获取全局设置
  • useGlobalConfig('namespace', 'el')传参调用,获取指定的全局设置
  1. import { getCurrentInstance } from 'vue'
  2. function useGlobalConfig(key, defaultValue = undefined) {
  3.   const config = getCurrentInstance() ? inject(configProviderContextKey, globalConfig) : globalConfig
  4.   if (key) {
  5.     return computed(() => config.value?.[key] ?? defaultValue)
  6.   } else {
  7.     return config
  8.   }
  9. }
复制代码
3,归并(新旧)全局设置
  1. // 新值 b 会覆盖旧值 a
  2. const mergeConfig = (a, b) => {
  3.   const keys = [...new Set([...Object.keys(a), ...Object.keys(b)])]
  4.   const obj = {}
  5.   for (const key of keys) {
  6.     obj[key] = b[key] ?? a[key]
  7.   }
  8.   return obj
  9. }
复制代码
4,provideGlobalConfig
有3个参数,是由于有2种调用方式。


  • 按需引入,通过 el-config-provider 组件调用时,只会传入全局设置参数config
  • 完备引入,通过 install 方法(作为插件)调用时,是应用层 Provide,以是还必要应用实例参数app,此时参数 global = true,会对全局设置对象globalConfig 赋值。
  1. import { getCurrentInstance } from 'vue'
  2. const provideGlobalConfig = (config, app, global = false) => {
  3.   // 在 setup() 或 <script setup> 中 getCurrentInstance() 才有值
  4.   const inSetup = !!getCurrentInstance()
  5.   const oldConfig = inSetup ? useGlobalConfig() : undefined
  6.   // 应用层 Provide 需要使用 app.provide
  7.   const provideFn = app?.provide ?? (inSetup ? provide : undefined)
  8.   if (!provideFn) {
  9.     debugWarn('provideGlobalConfig', 'provideGlobalConfig() can only be used inside setup().')
  10.     return
  11.   }
  12.   // 合并后的全局配置
  13.   const context = computed(() => {
  14.     const cfg = unref(config)
  15.     if (!oldConfig?.value) return cfg
  16.     return mergeConfig(oldConfig.value, cfg)
  17.   })
  18.   // 最核心的代码:provide 全局配置,这样才能在 useGlobalConfig() 中获取到全局配置
  19.   provideFn(configProviderContextKey, context)
  20.   // 下面这些都是 provide 指定的全局配置
  21.   provideFn(
  22.     localeContextKey, // Symbol('localeContextKey')
  23.     computed(() => context.value.locale)
  24.   )
  25.   provideFn(
  26.     namespaceContextKey, // Symbol('namespaceContextKey')
  27.     computed(() => context.value.namespace)
  28.   )
  29.   provideFn(
  30.     zIndexContextKey, // Symbol('zIndexContextKey')
  31.     computed(() => context.value.zIndex)
  32.   )
  33.   provideFn(SIZE_INJECTION_KEY, { // Symbol('size')
  34.     size: computed(() => context.value.size || ''),
  35.   })
  36.   // install 方法中调用 || 初次赋值
  37.   if (global || !globalConfig.value) {
  38.     globalConfig.value = context.value
  39.   }
  40.   return context
  41. }
复制代码
3.3,总结


  • 在 provideGlobalConfig  中 provide 的依靠,在使用的地方inject 即可。
举例
  1. const useLocale = (localeOverrides) => {
  2.   const locale = localeOverrides || inject(localeContextKey, ref())
  3.   // ...
  4. }
复制代码

  • provideGlobalConfig  终极返回的context 会作为el-config-provider组件的默认插槽的 props 使用。
举例:
  1. <template>
  2.   <el-config-provider :size="size" :z-index="zIndex" v-slot="{ config }">
  3.     <div>{{ config.namespace }}</div>
  4.     <app />
  5.   </el-config-provider>
  6. </template>
复制代码
以上。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表