refactor(utils)!: remove global config (#5093)

This commit is contained in:
三咲智子 2022-01-01 13:43:08 +08:00 committed by GitHub
parent f3b0e95f42
commit bd0a634069
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 28 deletions

View File

@ -1,9 +1,10 @@
import { provide, defineComponent, watch } from 'vue'
import { defineComponent, renderSlot } from 'vue'
import { buildProps, definePropType } from '@element-plus/utils/props'
import { useLocaleProps, provideLocale } from '@element-plus/hooks'
import { configProviderContextKey } from '@element-plus/tokens'
import { PopupManager } from '@element-plus/utils/popup-manager'
import { isNumber } from '@element-plus/utils/util'
import {
useLocaleProps,
provideLocale,
provideGlobalConfig,
} from '@element-plus/hooks'
import type { ButtonConfigContext } from '@element-plus/components/button'
export const configProviderProps = buildProps({
@ -29,17 +30,7 @@ export default defineComponent({
setup(props, { slots }) {
provideLocale()
provide(configProviderContextKey, props)
watch(
() => props.zIndex,
() => {
if (isNumber(props.zIndex))
PopupManager.globalInitialZIndex = props.zIndex
},
{ immediate: true }
)
return () => slots.default?.()
const config = provideGlobalConfig(props)
return () => renderSlot(slots, 'default', { config: config?.value })
},
})

View File

@ -1,14 +1,29 @@
import { watch, unref } from 'vue'
import { provideGlobalConfig } from '@element-plus/hooks'
import { isNumber } from '@element-plus/utils/util'
import { PopupManager } from '@element-plus/utils/popup-manager'
import { version } from './version'
import type { App, Plugin } from 'vue'
import type { ConfigProviderContext } from '@element-plus/tokens'
const INSTALLED_KEY = Symbol('INSTALLED_KEY')
export const makeInstaller = (components: Plugin[] = []) => {
const install = (app: App) => {
const install = (app: App, options: ConfigProviderContext = {}) => {
if (app[INSTALLED_KEY]) return
app[INSTALLED_KEY] = true
components.forEach((c) => app.use(c))
provideGlobalConfig(options, app)
watch(
() => unref(options).zIndex,
() => {
const zIndex = unref(options).zIndex
if (isNumber(zIndex)) PopupManager.globalInitialZIndex = zIndex
},
{ immediate: true }
)
}
return {

View File

@ -1,20 +1,49 @@
import { inject, ref, toRef } from 'vue'
import { inject, ref, computed, unref, provide, getCurrentInstance } from 'vue'
import { configProviderContextKey } from '@element-plus/tokens'
import { hasOwn, isObject } from '@element-plus/utils/util'
import type { Ref } from 'vue'
import { hasOwn, isObject, merge } from '@element-plus/utils/util'
import { debugWarn } from '@element-plus/utils/error'
import type { MaybeRef } from '@vueuse/core'
import type { Ref, App } from 'vue'
import type { ConfigProviderContext } from '@element-plus/tokens'
const fallback = ref<ConfigProviderContext>({})
export function useGlobalConfig<K extends keyof ConfigProviderContext>(
key: K
): Ref<ConfigProviderContext[K]>
export function useGlobalConfig(): ConfigProviderContext
export function useGlobalConfig(): Ref<ConfigProviderContext>
export function useGlobalConfig(key?: keyof ConfigProviderContext) {
const config = inject(configProviderContextKey, {})
const config = inject(configProviderContextKey, fallback)
if (key) {
return isObject(config) && hasOwn(config, key)
? toRef(config, key)
return isObject(config.value) && hasOwn(config.value, key)
? computed(() => config.value[key])
: ref(undefined)
} else {
return config
}
}
export const provideGlobalConfig = (
config: MaybeRef<ConfigProviderContext>,
app?: App
) => {
const inSetup = !!getCurrentInstance()
const oldConfig = inSetup ? useGlobalConfig() : undefined
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) return cfg
return merge(oldConfig.value, cfg)
})
provideFn(configProviderContextKey, context)
return context
}

View File

@ -1,7 +1,8 @@
import type { configProviderProps } from '@element-plus/components/config-provider'
import type { InjectionKey, ExtractPropTypes } from 'vue'
import type { InjectionKey, ExtractPropTypes, Ref } from 'vue'
export type ConfigProviderContext = ExtractPropTypes<typeof configProviderProps>
export const configProviderContextKey: InjectionKey<ConfigProviderContext> =
Symbol()
export const configProviderContextKey: InjectionKey<
Ref<ConfigProviderContext>
> = Symbol()

View File

@ -239,3 +239,14 @@ export const refAttacher = <T extends HTMLElement | ComponentPublicInstance>(
ref.value = val
}
}
export const merge = <T extends Record<string, any>>(a: T, b: T) => {
const keys = [
...new Set([...Object.keys(a), ...Object.keys(b)]),
] as (keyof T)[]
const obj = {} as T
for (const key of keys) {
obj[key] = b[key] ?? a[key]
}
return obj
}