官方文档:Config Provider 全局配置
在组件库的设计中,最常见的全局配置是 z-index 和 size
这些都属于全局配置项,可以Config Provider 全局配置来实现。
全局配置项有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()
const install = (app, options) => { // ... if (options) provideGlobalConfig(options, app, true) // ... }
2,按需引入
el-config-provider组件,传入指定的配置项props,在子组件中生效。
现在明确了:
install 方法没什么好说的,所以先介绍下el-config-provider 组件,再来详细介绍provideGlobalConfig()。
组件路径: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 }) }, }) export default ConfigProvider
renderSlot()和h('div', xxx) 一样,会返回 VNode,但参数不一致。
可以在 setup() 中返回渲染函数来创建组件。
export declare function renderSlot( slots: Slots, name: string, props?: Data, fallback?: () => VNodeArrayChildren, noSlotted?: boolean ): VNode;
主要介绍前3个参数:
带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 slot 出口会隐式地命名为“default”
所以 renderSlot(slots, 'default', { config: config?.value }) 定义的是默认插槽。
结合以上,Config Provider 组件如果使用 template 定义,大致如下
关于传给父组件的 props 的举例:
{{ slotProps.text }} {{ slotProps.count }}
先介绍依赖的变量和函数
1,定义全局配置对象globalConfig
// 全局配置对象 const globalConfig = ref() // 全局配置依赖注入 provide/inject 的 key const configProviderContextKey = Symbol()
2,获取全局配置的 hook 函数
import { getCurrentInstance } from 'vue' function useGlobalConfig(key, defaultValue = undefined) { const config = getCurrentInstance() ? inject(configProviderContextKey, globalConfig) : globalConfig if (key) { return computed(() => config.value?.[key] ?? defaultValue) } else { return config } }
3,合并(新旧)全局配置
// 新值 b 会覆盖旧值 a const mergeConfig = (a, b) => { const keys = [...new Set([...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种调用方式。
import { getCurrentInstance } from 'vue' const provideGlobalConfig = (config, app, global = false) => { // 在 setup() 或