Stream-web/components_study

element plus css架构之useNamespace

Opened this issue · 0 comments

useNamespace 是 Element Plus 中用于定义命名空间和 BEM 规范的 CSS 类名的组合式 API。它主要用于在组件中使用命名空间和 BEM 规范的 CSS 类名,以避免 CSS 类名冲突和提高代码可读性。

useNamespace 函数接受两个参数:block 和 namespaceOverrides。其中,block 表示块名,namespaceOverrides 表示命名空间的覆盖值。如果传入了命名空间的覆盖值,则使用覆盖值作为命名空间;否则,如果当前组件存在,则从组件中获取命名空间;否则,使用默认的命名空间。

useNamespace 函数返回一个对象,包含了命名空间、一系列生成 CSS 类名的函数、生成 CSS 变量名的函数以及一个类型别名 UseNamespaceReturn,用于表示 useNamespace 函数的返回值类型。

在 Element Plus 中,useNamespace 函数被广泛用于定义组件的 CSS 类名,以确保组件的样式不会与其他组件的样式冲突。
具体代码如下:
`import { computed, getCurrentInstance, inject, ref, unref } from 'vue'

import type { InjectionKey, Ref } from 'vue'

export const defaultNamespace = 'el'
const statePrefix = 'is-'

const _bem = (
namespace: string,
block: string,
blockSuffix: string,
element: string,
modifier: string
) => {
let cls = ${namespace}-${block}
if (blockSuffix) {
cls += -${blockSuffix}
}
if (element) {
cls += __${element}
}
if (modifier) {
cls += --${modifier}
}
return cls
}

export const namespaceContextKey: InjectionKey<Ref<string | undefined>> =
Symbol('namespaceContextKey')

export const useGetDerivedNamespace = (
namespaceOverrides?: Ref<string | undefined>
) => {
const derivedNamespace =
namespaceOverrides ||
(getCurrentInstance()
? inject(namespaceContextKey, ref(defaultNamespace))
: ref(defaultNamespace))
const namespace = computed(() => {
return unref(derivedNamespace) || defaultNamespace
})
return namespace
}

export const useNamespace = (
block: string,
namespaceOverrides?: Ref<string | undefined>
) => {
const namespace = useGetDerivedNamespace(namespaceOverrides)
const b = (blockSuffix = '') =>
_bem(namespace.value, block, blockSuffix, '', '')
const e = (element?: string) =>
element ? _bem(namespace.value, block, '', element, '') : ''
const m = (modifier?: string) =>
modifier ? _bem(namespace.value, block, '', '', modifier) : ''
const be = (blockSuffix?: string, element?: string) =>
blockSuffix && element
? _bem(namespace.value, block, blockSuffix, element, '')
: ''
const em = (element?: string, modifier?: string) =>
element && modifier
? _bem(namespace.value, block, '', element, modifier)
: ''
const bm = (blockSuffix?: string, modifier?: string) =>
blockSuffix && modifier
? _bem(namespace.value, block, blockSuffix, '', modifier)
: ''
const bem = (blockSuffix?: string, element?: string, modifier?: string) =>
blockSuffix && element && modifier
? _bem(namespace.value, block, blockSuffix, element, modifier)
: ''
const is: {
(name: string, state: boolean | undefined): string
(name: string): string
} = (name: string, ...args: [boolean | undefined] | []) => {
const state = args.length >= 1 ? args[0]! : true
return name && state ? ${statePrefix}${name} : ''
}

// for css var
// --el-xxx: value;
const cssVar = (object: Record<string, string>) => {
const styles: Record<string, string> = {}
for (const key in object) {
if (object[key]) {
styles[--${namespace.value}-${key}] = object[key]
}
}
return styles
}
// with block
const cssVarBlock = (object: Record<string, string>) => {
const styles: Record<string, string> = {}
for (const key in object) {
if (object[key]) {
styles[--${namespace.value}-${block}-${key}] = object[key]
}
}
return styles
}

const cssVarName = (name: string) => --${namespace.value}-${name}
const cssVarBlockName = (name: string) =>
--${namespace.value}-${block}-${name}

return {
namespace,
b,
e,
m,
be,
em,
bm,
bem,
is,
// css
cssVar,
cssVarName,
cssVarBlock,
cssVarBlockName,
}
}

export type UseNamespaceReturn = ReturnType
`
下列函数分别用于生成符合 BEM 规范的 CSS 类名,具体含义如下:

b(blockSuffix?: string): string:生成块名的 CSS 类名,可选参数 blockSuffix 用于生成带有块后缀的 CSS 类名。

e(element?: string): string:生成元素名的 CSS 类名,可选参数 element 用于生成带有元素名的 CSS 类名。

m(modifier?: string): string:生成修饰符的 CSS 类名,可选参数 modifier 用于生成带有修饰符的 CSS 类名。

be(blockSuffix?: string, element?: string): string:生成块名和元素名的组合 CSS 类名,可选参数 blockSuffix 用于生成带有块后缀的 CSS 类名,可选参数 element 用于生成带有元素名的 CSS 类名。

em(element?: string, modifier?: string): string:生成元素名和修饰符的组合 CSS 类名,可选参数 element 用于生成带有元素名的 CSS 类名,可选参数 modifier 用于生成带有修饰符的 CSS 类名。

bm(blockSuffix?: string, modifier?: string): string:生成块名和修饰符的组合 CSS 类名,可选参数 blockSuffix 用于生成带有块后缀的 CSS 类名,可选参数 modifier 用于生成带有修饰符的 CSS 类名。

bem(blockSuffix?: string, element?: string, modifier?: string): string:生成块名、元素名和修饰符的组合 CSS 类名,可选参数 blockSuffix 用于生成带有块后缀的 CSS 类名,可选参数 element 用于生成带有元素名的 CSS 类名,可选参数 modifier 用于生成带有修饰符的 CSS 类名。

is(name: string, state?: boolean): string:用于生成状态类名,接受两个参数,name 表示状态名称,state 表示状态值,如果 state 为 true,则返回以 is- 为前缀的状态类名,否则返回空字符串。

cssVar(object: Record<string, string>): Record<string, string>:用于生成 CSS 变量名,接受一个对象参数 object,该对象的键表示变量名,值表示变量值,返回一个对象,其中键为以命名空间、变量名和前缀 -- 组成的字符串,值为变量值。

cssVarName(name: string): string:用于生成 CSS 变量名,接受一个字符串参数 name,返回以命名空间、name 参数和前缀 -- 组成的字符串,用于在 CSS 中定义变量。

cssVarBlock(object: Record<string, string>): Record<string, string>:用于生成带有块名的 CSS 变量名,接受一个对象参数 object,该对象的键表示变量名,值表示变量值,返回一个对象,其中键为以命名空间、块名、变量名和前缀 -- 组成的字符串,值为变量值。

cssVarBlockName(name: string): string:用于生成带有块名的 CSS 变量名,接受一个字符串参数 name,返回以命名空间、块名、name 参数和前缀 -- 组成的字符串,用于在 CSS 中定义带有块名的变量。