feat: support custom namespace (#5377)

This commit is contained in:
iamkun 2022-01-15 18:12:48 +08:00 committed by GitHub
parent 62eb0f92d0
commit 9929c0fba4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 180 additions and 5 deletions

View File

@ -1,11 +1,12 @@
<template>
<div class="el-button-group">
<div :class="`${ns.b('group')}`">
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, provide, reactive, toRef } from 'vue'
import { buttonGroupContextKey } from '@element-plus/tokens'
import { useNamespace } from '@element-plus/hooks'
import { buttonGroupProps } from './button-group'
export default defineComponent({
@ -20,6 +21,10 @@ export default defineComponent({
type: toRef(props, 'type'),
})
)
const ns = useNamespace('button')
return {
ns,
}
},
})
</script>

View File

@ -2,9 +2,9 @@
<button
ref="buttonRef"
:class="[
'el-button',
buttonType ? 'el-button--' + buttonType : '',
buttonSize ? 'el-button--' + buttonSize : '',
`${ns.b()}`,
`${ns.m(buttonType)}`,
`${ns.m(buttonSize)}`,
{
'is-disabled': buttonDisabled,
'is-loading': loading,
@ -27,7 +27,7 @@
</el-icon>
<span
v-if="$slots.default"
:class="{ 'el-button__text--expand': shouldAddSpace }"
:class="[shouldAddSpace ? `${ns.em('text', 'expand')}` : '']"
>
<slot></slot>
</span>
@ -43,6 +43,7 @@ import {
useDisabled,
useFormItem,
useGlobalConfig,
useNamespace,
useSize,
} from '@element-plus/hooks'
import { buttonGroupContextKey } from '@element-plus/tokens'
@ -65,6 +66,7 @@ export default defineComponent({
const buttonRef = ref()
const buttonGroupContext = inject(buttonGroupContextKey, undefined)
const globalConfig = useGlobalConfig('button')
const ns = useNamespace('button')
const autoInsertSpace = computed(
() =>
props.autoInsertSpace ?? globalConfig.value?.autoInsertSpace ?? false
@ -156,6 +158,8 @@ export default defineComponent({
shouldAddSpace,
handleClick,
ns,
}
},
})

View File

@ -124,6 +124,37 @@ describe('config-provider', () => {
})
})
describe('namespace-config', () => {
it('reactive namespace', async () => {
const wrapper = mount({
components: {
[ConfigProvider.name]: ConfigProvider,
ElButton,
},
setup() {
const namespace = ref()
return {
namespace,
}
},
template: `
<el-config-provider :namespace="namespace">
<el-button>test str</el-button>
</el-config-provider>
`,
})
await nextTick()
expect(wrapper.find('button').classes().join('')).toBe(
'el-button' + 'el-button--default'
)
wrapper.vm.namespace = 'ep'
await nextTick()
expect(wrapper.find('button').classes().join('')).toBe(
'ep-button' + 'ep-button--default'
)
})
})
describe('message-config', () => {
it('limit the number of messages displayed at the same time', async () => {
const wrapper = mount({

View File

@ -28,6 +28,11 @@ export const configProviderProps = buildProps({
zIndex: {
type: Number,
},
namespace: {
type: String,
default: 'el',
},
} as const)
export default defineComponent({

View File

@ -0,0 +1,73 @@
import { h, nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import { useNamespace, provideGlobalConfig } from '..'
const TestComp = {
setup() {
const ns = useNamespace('table')
return () => {
return h(
'div',
{
id: 'testId',
class: [
ns.b(), // return ns + block
ns.b('body'),
ns.e('content'),
ns.m('active'),
ns.be('content', 'active'),
ns.em('content', 'active'),
ns.bem('body', 'content', 'active'),
ns.e(), // return empty string
ns.m(), // return empty string
ns.be(), // return empty string
ns.em(), // return empty string
ns.bem(), // return empty string
],
},
'text'
)
}
},
}
describe('use-locale', () => {
let wrapper
beforeEach(() => {
wrapper = mount(
{
components: {
'el-test': TestComp,
},
setup(props, { slots }) {
provideGlobalConfig({ namespace: 'ep' })
return () => slots.default()
},
},
{
slots: {
default: () => h(TestComp),
},
}
)
})
afterEach(() => {
wrapper.unmount()
})
it('should provide bem correctly', async () => {
await nextTick()
expect(wrapper.find('#testId').classes().join('~')).toBe(
[
'ep-table', // b()
'ep-table-body', // b('body')
'ep-table__content', // e('content')
'ep-table--active', // m('active')
'ep-table-content__active', // be('content', 'active')
'ep-table__content--active', // em('content', 'active')
'ep-table-body__content--active', // bem('body', 'content', 'active')
].join('~')
)
})
})

View File

@ -22,3 +22,4 @@ export * from './use-popper-container'
export * from './use-intermediate-render'
export * from './use-delayed-toggle'
export * from './use-forward-ref'
export * from './use-namespace'

View File

@ -0,0 +1,56 @@
import { unref, computed } from 'vue'
import curry from 'lodash/curry'
import { useGlobalConfig } from '../use-global-config'
const curryBem = curry(
(
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 useNamespace = (block: string) => {
const namespace = computed(() => useGlobalConfig('namespace').value || 'el')
const b = (blockSuffix = '') =>
curryBem(unref(namespace), block, blockSuffix, '', '')
const e = (element?: string) =>
element ? curryBem(unref(namespace), block, '', element, '') : ''
const m = (modifier?: string) =>
modifier ? curryBem(unref(namespace), block, '', '')(modifier) : ''
const be = (blockSuffix?: string, element?: string) =>
blockSuffix && element
? curryBem(unref(namespace), block, blockSuffix, element, '')
: ''
const em = (element?: string, modifier?: string) =>
element && modifier
? curryBem(unref(namespace), block, '')(element, modifier)
: ''
const bem = (blockSuffix?: string, element?: string, modifier?: string) =>
blockSuffix && element && modifier
? curryBem(unref(namespace), block)(blockSuffix, element, modifier)
: ''
return {
namespace,
b,
e,
m,
be,
em,
bem,
}
}