mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-30 11:16:12 +08:00
refactor(utils): dom and add test (#3950)
* refactor(utils): getAttribute replace className * test: add dom test * fix(utils): update trimArr and test * chore: includes replace indexOf * chore: modify judge
This commit is contained in:
parent
21e37b1900
commit
bccca92dfd
@ -5,15 +5,8 @@ import type { CSSProperties } from 'vue'
|
||||
import type { Nullable } from './types'
|
||||
|
||||
/* istanbul ignore next */
|
||||
const trimArr = function (s: string | SVGAnimatedString) {
|
||||
if (typeof s !== 'string') {
|
||||
if (s.baseVal) {
|
||||
return s.baseVal.split(' ').map((item) => item.trim())
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
return (s || '').split(' ').map((item) => item.trim())
|
||||
const trimArr = function (s: string) {
|
||||
return (s || '').split(' ').filter((item) => !!item.trim())
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
@ -56,21 +49,23 @@ export const once = function (
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function hasClass(el: HTMLElement, cls: string): boolean {
|
||||
export function hasClass(el: HTMLElement | Element, cls: string): boolean {
|
||||
if (!el || !cls) return false
|
||||
if (cls.indexOf(' ') !== -1)
|
||||
throw new Error('className should not contain space.')
|
||||
if (el.classList) {
|
||||
return el.classList.contains(cls)
|
||||
} else {
|
||||
return ` ${el.className} `.indexOf(` ${cls} `) > -1
|
||||
const className = el.getAttribute('class') || ''
|
||||
return className.split(' ').includes(cls)
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function addClass(el: HTMLElement, cls: string): void {
|
||||
export function addClass(el: HTMLElement | Element, cls: string): void {
|
||||
if (!el) return
|
||||
const curClass = trimArr(el.className)
|
||||
let className = el.getAttribute('class') || ''
|
||||
const curClass = trimArr(className)
|
||||
const classes = (cls || '')
|
||||
.split(' ')
|
||||
.filter((item) => !curClass.includes(item) && !!item.trim())
|
||||
@ -78,39 +73,25 @@ export function addClass(el: HTMLElement, cls: string): void {
|
||||
if (el.classList) {
|
||||
el.classList.add(...classes)
|
||||
} else {
|
||||
let className = el.className
|
||||
if (typeof className === 'string') {
|
||||
className += ` ${classes.join(' ')}`
|
||||
} else {
|
||||
className = `${(className as SVGAnimatedString).baseVal} ${classes.join(
|
||||
' '
|
||||
)}`
|
||||
}
|
||||
className += ` ${classes.join(' ')}`
|
||||
el.setAttribute('class', className)
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function removeClass(el: HTMLElement, cls: string): void {
|
||||
export function removeClass(el: HTMLElement | Element, cls: string): void {
|
||||
if (!el || !cls) return
|
||||
const classes = trimArr(cls)
|
||||
let curClass = el.className as string | SVGAnimatedString
|
||||
if (typeof curClass === 'string') {
|
||||
curClass = ` ${curClass} `
|
||||
} else {
|
||||
curClass = ` ${curClass.baseVal} `
|
||||
}
|
||||
let curClass = el.getAttribute('class') || ''
|
||||
|
||||
if (el.classList) {
|
||||
el.classList.remove(...classes)
|
||||
return
|
||||
}
|
||||
classes.forEach((item) => {
|
||||
curClass = (curClass as string).replace(` ${item} `, ' ')
|
||||
curClass = curClass.replace(` ${item} `, ' ')
|
||||
})
|
||||
const className = trimArr(curClass)
|
||||
.filter((item) => !!item)
|
||||
.join(' ')
|
||||
const className = trimArr(curClass).join(' ')
|
||||
el.setAttribute('class', className)
|
||||
}
|
||||
|
||||
|
183
packages/utils/tests/dom.spec.ts
Normal file
183
packages/utils/tests/dom.spec.ts
Normal file
@ -0,0 +1,183 @@
|
||||
import { hasClass, addClass, removeClass } from '../dom'
|
||||
|
||||
const getClass = (el: Element) => {
|
||||
if (!el) {
|
||||
return ''
|
||||
}
|
||||
return el.getAttribute('class')
|
||||
}
|
||||
|
||||
describe('Dom Utils', () => {
|
||||
describe('hasClass', () => {
|
||||
it('Judge whether a Element has a class', () => {
|
||||
const div = document.createElement('div')
|
||||
div.className = 'a b cc'
|
||||
expect(hasClass(div, 'a')).toBe(true)
|
||||
expect(hasClass(div, 'ab')).toBe(false)
|
||||
try {
|
||||
expect(hasClass(div, 'a b'))
|
||||
} catch (error: any) {
|
||||
expect(error.message).toEqual('className should not contain space.')
|
||||
}
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.className = 'canvas-a canvas-b cc'
|
||||
expect(hasClass(canvas, 'a')).toBe(false)
|
||||
expect(hasClass(canvas, 'canvas-a')).toBe(true)
|
||||
// remove classList
|
||||
canvas.setAttribute('classList', '')
|
||||
expect(hasClass(canvas, 'b')).toBe(false)
|
||||
expect(hasClass(canvas, 'canvas-b')).toBe(true)
|
||||
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
svg.setAttribute('class', 'svg-a svg-b')
|
||||
expect(hasClass(svg, 'a')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-a')).toBe(true)
|
||||
// remove classList
|
||||
svg.setAttribute('classList', '')
|
||||
expect(hasClass(svg, 'b')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-b')).toBe(true)
|
||||
|
||||
const path = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'path'
|
||||
)
|
||||
path.setAttribute('class', 'path-a path-b')
|
||||
expect(hasClass(path, 'a')).toBe(false)
|
||||
expect(hasClass(path, 'path-a')).toBe(true)
|
||||
// remove classList
|
||||
path.setAttribute('classList', '')
|
||||
expect(hasClass(path, 'b')).toBe(false)
|
||||
expect(hasClass(path, 'path-b')).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('addClass', () => {
|
||||
it('Add class to element', () => {
|
||||
const div = document.createElement('div')
|
||||
addClass(div, 'div-abc abc')
|
||||
expect(hasClass(div, 'abc')).toBe(true)
|
||||
expect(hasClass(div, 'div-abc')).toBe(true)
|
||||
expect(hasClass(div, 'div')).toBe(false)
|
||||
addClass(div, 'abc')
|
||||
expect(getClass(div)).toEqual('div-abc abc')
|
||||
// remove classList
|
||||
div.setAttribute('classList', '')
|
||||
addClass(div, 'div-box con')
|
||||
expect(hasClass(div, 'con')).toBe(true)
|
||||
expect(hasClass(div, 'div-box')).toBe(true)
|
||||
expect(hasClass(div, 'box')).toBe(false)
|
||||
addClass(div, 'con')
|
||||
expect(getClass(div)).toEqual('div-abc abc div-box con')
|
||||
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
addClass(svg, 'svg-abc svg')
|
||||
expect(hasClass(svg, 'svg')).toBe(true)
|
||||
expect(hasClass(svg, 'svg-abc')).toBe(true)
|
||||
expect(hasClass(svg, 'abc')).toBe(false)
|
||||
expect(hasClass(svg, 'sv')).toBe(false)
|
||||
addClass(svg, 'svg')
|
||||
expect(getClass(svg)).toEqual('svg-abc svg')
|
||||
addClass(svg, 'svg-aa space')
|
||||
expect(getClass(svg)).toEqual('svg-abc svg svg-aa space')
|
||||
// remove classList
|
||||
svg.setAttribute('classList', '')
|
||||
addClass(svg, 'svg-abc-a svg-b')
|
||||
expect(hasClass(svg, 'svg')).toBe(true)
|
||||
expect(hasClass(svg, 'svg-abc')).toBe(true)
|
||||
expect(hasClass(svg, 'abc')).toBe(false)
|
||||
expect(hasClass(svg, 'sv')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-abc-a')).toBe(true)
|
||||
expect(hasClass(svg, 'svg-b')).toBe(true)
|
||||
expect(hasClass(svg, 'a')).toBe(false)
|
||||
|
||||
const path = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'path'
|
||||
)
|
||||
addClass(path, 'path-abc path')
|
||||
expect(hasClass(path, 'path')).toBe(true)
|
||||
expect(hasClass(path, 'path-abc')).toBe(true)
|
||||
expect(hasClass(path, 'abc')).toBe(false)
|
||||
expect(hasClass(path, 'pa')).toBe(false)
|
||||
addClass(path, 'path')
|
||||
expect(getClass(path)).toEqual('path-abc path')
|
||||
// remove classList
|
||||
path.setAttribute('classList', '')
|
||||
expect(hasClass(path, 'path')).toBe(true)
|
||||
expect(hasClass(path, 'path-abc')).toBe(true)
|
||||
expect(hasClass(path, 'abc')).toBe(false)
|
||||
expect(hasClass(path, 'pa')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeClass', () => {
|
||||
it('Remove class on element', () => {
|
||||
const div = document.createElement('div')
|
||||
addClass(div, 'div-abc abc ab bb cc')
|
||||
|
||||
removeClass(div, 'abc')
|
||||
expect(hasClass(div, 'abc')).toBe(false)
|
||||
|
||||
expect(hasClass(div, 'bb')).toBe(true)
|
||||
expect(hasClass(div, 'cc')).toBe(true)
|
||||
|
||||
removeClass(div, 'bb cc')
|
||||
expect(hasClass(div, 'bb')).toBe(false)
|
||||
expect(hasClass(div, 'cc')).toBe(false)
|
||||
expect(getClass(div)).toEqual('div-abc ab')
|
||||
|
||||
// remove classList
|
||||
div.setAttribute('classList', '')
|
||||
addClass(div, 'div-box con')
|
||||
removeClass(div, 'div-box con')
|
||||
expect(hasClass(div, 'con')).toBe(false)
|
||||
expect(hasClass(div, 'div-box')).toBe(false)
|
||||
expect(getClass(div)).toBe('div-abc ab')
|
||||
|
||||
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
|
||||
addClass(svg, 'svg-abc svg')
|
||||
removeClass(svg, 'svg-abc svg')
|
||||
expect(hasClass(svg, 'svg-abc')).toBe(false)
|
||||
expect(hasClass(svg, 'abc')).toBe(false)
|
||||
expect(getClass(svg)).toEqual('')
|
||||
// remove classList
|
||||
svg.setAttribute('classList', '')
|
||||
addClass(svg, 'svg-abc-a svg-b')
|
||||
expect(hasClass(svg, 'svg')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-abc')).toBe(false)
|
||||
expect(hasClass(svg, 'abc')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-abc-a')).toBe(true)
|
||||
expect(hasClass(svg, 'svg-b')).toBe(true)
|
||||
removeClass(svg, 'svg')
|
||||
expect(getClass(svg)).toEqual('svg-abc-a svg-b')
|
||||
removeClass(svg, 'svg-abc-a')
|
||||
expect(hasClass(svg, 'svg-abc-a')).toBe(false)
|
||||
expect(hasClass(svg, 'svg-b')).toBe(true)
|
||||
|
||||
const path = document.createElementNS(
|
||||
'http://www.w3.org/2000/svg',
|
||||
'path'
|
||||
)
|
||||
addClass(path, 'path-abc path')
|
||||
expect(hasClass(path, 'path')).toBe(true)
|
||||
expect(hasClass(path, 'path-abc')).toBe(true)
|
||||
expect(hasClass(path, 'abc')).toBe(false)
|
||||
expect(hasClass(path, 'pa')).toBe(false)
|
||||
removeClass(path, 'path')
|
||||
expect(hasClass(path, 'path')).toBe(false)
|
||||
expect(hasClass(path, 'path-abc')).toBe(true)
|
||||
// remove classList
|
||||
path.setAttribute('classList', '')
|
||||
addClass(path, 'path path-1 path2')
|
||||
expect(hasClass(path, 'path')).toBe(true)
|
||||
expect(hasClass(path, 'path-1')).toBe(true)
|
||||
expect(getClass(path)).toEqual('path-abc path path-1 path2')
|
||||
removeClass(path, 'path')
|
||||
expect(hasClass(path, 'path')).toBe(false)
|
||||
expect(getClass(path)).toEqual('path-abc path-1 path2')
|
||||
removeClass(path, 'path-abc path-1 path2')
|
||||
expect(getClass(path)).toEqual('')
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user