0


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

Config Provider 全局配置解析

官方文档:Config Provider 全局配置

1,介绍

在组件库的设计中,最常见的全局配置是

z-index

size
  • z-index:统一管理弹出层(dialog, message, loading)等组件的层级。
  • size:统一管理表单元素大小。

这些都属于全局配置项,可以

Config Provider

全局配置来实现。

2,使用

全局配置项有2种引入方式。但都是调用同一个全局配置函数

provideGlobalConfig

实现的,后面会详细介绍。

1,完整引入

import{ createApp }from'vue'import ElementPlus from'element-plus'import App from'./App.vue'const app =createApp(App)
app.use(ElementPlus,{ size:'small', zIndex:3000})

相当于在

element-plus

install

方法中,调用了

provideGlobalConfig()
constinstall=(app, options)=>{// ...if(options)provideGlobalConfig(options, app,true)// ...}

2,按需引入

<template><el-config-provider:size="size":z-index="zIndex"><app/></el-config-provider></template><script>import{ defineComponent }from'vue'import{ ElConfigProvider }from'element-plus'exportdefaultdefineComponent({components:{
    ElConfigProvider,},setup(){return{zIndex:3000,size:'small',}},})</script>
  1. 相当于在el-config-provider组件中,调用了provideGlobalConfig()
  2. 如果将根组件作为el-config-provider的子组件传入,也相当于全局引入。
el-config-provider

组件,传入指定的配置项

props

在子组件中生效

3,全局配置的实现

现在明确了:

  1. 完整引入通过 install 方法调用provideGlobalConfig()
  2. 按需引入通过 el-config-provider 组件调用provideGlobalConfig()
install

方法没什么好说的,所以先介绍下

el-config-provider

组件,再来详细介绍

provideGlobalConfig()

3.1,el-config-provider

组件路径:

packages\components\config-provider\src\config-provider.ts

代码稍微做了简化。

import{ defineComponent, renderSlot }from'vue'import{ provideGlobalConfig }from'./hooks/use-global-config'const ConfigProvider =defineComponent({name:'ElConfigProvider',// locale | size | zIndex | namespace | button | message 等props: configProviderProps,setup(props,{ slots }){const config =provideGlobalConfig(props)return()=>renderSlot(slots,'default',{config: config?.value })},})exportdefault ConfigProvider

renderSlot

renderSlot()

h('div', xxx)

一样,会返回 VNode,但参数不一致。

**可以在

setup()

中返回渲染函数来创建组件**。

exportdeclarefunctionrenderSlot(
    slots: Slots, 
    name:string, 
    props?: Data, 
    fallback?:()=> VNodeArrayChildren, 
    noSlotted?:boolean): VNode;

主要介绍前3个参数:

  1. slots:父组件传入的插槽内容
  2. name:具名插槽的名称

带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 slot 出口会隐式地命名为“default”

所以

renderSlot(slots, 'default', { config: config?.value })

定义的是默认插槽

  1. props:传给父组件的 props

结合以上,

Config Provider

组件如果使用 template 定义,大致如下

<template><div><slot:config="config"></slot></div></template><scriptlang="ts"setup>const config =provideGlobalConfig(props)</script>

关于传给父组件的 props 的举例:

<!-- <MyComponent> 子组件 --><div><slot:text="greetingMessage":count="1"></slot></div><!-- 父组件 --><MyComponentv-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>

3.2,provideGlobalConfig

先介绍依赖的变量和函数

1,定义全局配置对象

globalConfig 
// 全局配置对象const globalConfig =ref()// 全局配置依赖注入 provide/inject 的 keyconst configProviderContextKey =Symbol()

2,获取全局配置的 hook 函数

  • useGlobalConfig()直接调用,获取全局配置
  • useGlobalConfig('namespace', 'el')传参调用,获取指定的全局配置
import{ getCurrentInstance }from'vue'functionuseGlobalConfig(key, defaultValue =undefined){const config =getCurrentInstance()?inject(configProviderContextKey, globalConfig): globalConfig
  if(key){returncomputed(()=> config.value?.[key]?? defaultValue)}else{return config
  }}

3,合并(新旧)全局配置

// 新值 b 会覆盖旧值 aconstmergeConfig=(a, b)=>{const keys =[...newSet([...Object.keys(a),...Object.keys(b)])]const obj ={}for(const key of keys){
    obj[key]= b[key]?? a[key]}return obj
}

4,provideGlobalConfig

有3个参数,是因为有2种调用方式。

  • 按需引入,通过 el-config-provider 组件调用时,只会传入全局配置参数config
  • 完整引入,通过 install 方法(作为插件)调用时,是应用层 Provide,所以还需要应用实例参数app,此时参数 global = true,会对全局配置对象globalConfig 赋值。
import{ getCurrentInstance }from'vue'constprovideGlobalConfig=(config, app, global =false)=>{// 在 setup() 或 <script setup> 中 getCurrentInstance() 才有值const inSetup =!!getCurrentInstance()const oldConfig = inSetup ?useGlobalConfig():undefined// 应用层 Provide 需要使用 app.provideconst provideFn = app?.provide ??(inSetup ? provide :undefined)if(!provideFn){debugWarn('provideGlobalConfig','provideGlobalConfig() can only be used inside setup().')return}// 合并后的全局配置const context =computed(()=>{const cfg =unref(config)if(!oldConfig?.value)return cfg
    returnmergeConfig(oldConfig.value, cfg)})// 最核心的代码:provide 全局配置,这样才能在 useGlobalConfig() 中获取到全局配置provideFn(configProviderContextKey, context)// 下面这些都是 provide 指定的全局配置provideFn(
    localeContextKey,// Symbol('localeContextKey')computed(()=> context.value.locale))provideFn(
    namespaceContextKey,// Symbol('namespaceContextKey')computed(()=> context.value.namespace))provideFn(
    zIndexContextKey,// Symbol('zIndexContextKey')computed(()=> context.value.zIndex))provideFn(SIZE_INJECTION_KEY,{// Symbol('size')size:computed(()=> context.value.size ||''),})// install 方法中调用 || 初次赋值if(global ||!globalConfig.value){
    globalConfig.value = context.value
  }return context
}

3.3,总结

  1. provideGlobalConfig provide 的依赖,在使用的地方inject 即可。

举例

constuseLocale=(localeOverrides)=>{const locale = localeOverrides ||inject(localeContextKey,ref())// ...}
  1. provideGlobalConfig 最终返回的context 会作为el-config-provider组件的默认插槽的 props 使用。

举例:

<template><el-config-provider:size="size":z-index="zIndex"v-slot="{ config }"><div>{{ config.namespace }}</div><app/></el-config-provider></template>

以上。


本文转载自: https://blog.csdn.net/qq_40147756/article/details/131652796
版权归原作者 下雪天的夏风 所有, 如有侵权,请联系我们删除。

“element-plus 架构 - Config Provider 全局配置”的评论:

还没有评论