马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
官方文档: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()
- const install = (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'
- export default defineComponent({
- components: {
- ElConfigProvider,
- },
- setup() {
- return {
- zIndex: 3000,
- size: 'small',
- }
- },
- })
- </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
代码稍微做了简化。
- 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
renderSlot()和h('div', xxx) 一样,会返回 VNode,但参数不同等。
可以在 setup() 中返回渲染函数来创建组件。
- export declare function renderSlot(
- slots: Slots,
- name: string,
- props?: Data,
- fallback?: () => VNodeArrayChildren,
- noSlotted?: boolean
- ): VNode;
复制代码 紧张先容前3个参数:
- slots:父组件传入的插槽内容。
- name:具名插槽的名称。
带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 slot 出口会隐式地定名为“default”
以是 renderSlot(slots, 'default', { config: config?.value }) 界说的是默认插槽。
联合以上,Config Provider 组件假如使用 template 界说,大抵如下
- <template>
- <div>
- <slot :config="config"></slot>
- </div>
- </template>
- <script lang="ts" setup>
- const config = provideGlobalConfig(props)
- </script>
复制代码 关于传给父组件的 props 的举例:
- <!-- <MyComponent> 子组件 -->
- <div>
- <slot :text="greetingMessage" :count="1"></slot>
- </div>
- <!-- 父组件 -->
- <MyComponent v-slot="slotProps">
- {{ slotProps.text }} {{ slotProps.count }}
- </MyComponent>
复制代码 3.2,provideGlobalConfig
先先容依靠的变量和函数
1,界说全局设置对象globalConfig
- // 全局配置对象
- const globalConfig = ref()
- // 全局配置依赖注入 provide/inject 的 key
- const configProviderContextKey = Symbol()
复制代码 2,获取全局设置的 hook 函数
- useGlobalConfig()直接调用,获取全局设置
- useGlobalConfig('namespace', 'el')传参调用,获取指定的全局设置
- 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种调用方式。
- 按需引入,通过 el-config-provider 组件调用时,只会传入全局设置参数config
- 完备引入,通过 install 方法(作为插件)调用时,是应用层 Provide,以是还必要应用实例参数app,此时参数 global = true,会对全局设置对象globalConfig 赋值。
- import { getCurrentInstance } from 'vue'
- const provideGlobalConfig = (config, app, global = false) => {
- // 在 setup() 或 <script setup> 中 getCurrentInstance() 才有值
- const inSetup = !!getCurrentInstance()
- const oldConfig = inSetup ? useGlobalConfig() : undefined
- // 应用层 Provide 需要使用 app.provide
- const 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
- return mergeConfig(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,总结
- 在 provideGlobalConfig 中 provide 的依靠,在使用的地方inject 即可。
举例
- const useLocale = (localeOverrides) => {
- const locale = localeOverrides || inject(localeContextKey, ref())
- // ...
- }
复制代码
- 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>
复制代码 以上。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金 |