TASK: #103599 - add SlotStyleHandler
This commit is contained in:
parent
5d7ec91fa7
commit
4a46290727
|
@ -9,3 +9,4 @@
|
|||
- add indicator-page-point
|
||||
- add blur
|
||||
- add contaienr
|
||||
- add SlotStyleHandler
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
class SlotStyleHandler {
|
||||
regex: {[regStr: string]: RegExp} = {
|
||||
slottedCss: /(?:\:\:slotted\(.*\))[^{]+\{[^}]*\}/g,
|
||||
'::slotted()': /\:\:slotted\(([^\(]+)\)/g,
|
||||
keyframes: /@keyframes[^{]+\{([^{]+\{[^}]*\})*\D*\}/g,
|
||||
}
|
||||
head!: HTMLElement
|
||||
headFirstElement!: ChildNode | null
|
||||
headStyle!: HTMLElement
|
||||
shouldRefresh: boolean = false
|
||||
styles: {[styleName: string]: string} = new Proxy(
|
||||
{},
|
||||
{
|
||||
set: (
|
||||
target: {[styleName: string]: string},
|
||||
prop: string,
|
||||
value: string
|
||||
) => {
|
||||
if (!target[prop] || target[prop] !== value) {
|
||||
target[prop] = value
|
||||
this.shouldRefresh = true
|
||||
}
|
||||
return true
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
processCss(style: string, name: string) {
|
||||
let globalCss = ''
|
||||
style.replace(this.regex.keyframes, (match) => {
|
||||
console.log('=====', match)
|
||||
globalCss += match
|
||||
return ''
|
||||
})
|
||||
style = style.replace(this.regex.slottedCss, (match) => {
|
||||
globalCss += match.replace(this.regex['::slotted()'], name + ' $1')
|
||||
return ''
|
||||
})
|
||||
|
||||
return globalCss
|
||||
}
|
||||
|
||||
/**
|
||||
* 将CSS注入头部<style></style>
|
||||
*
|
||||
* @param {String} style
|
||||
* @param {String} name
|
||||
* @returns
|
||||
*/
|
||||
injectGlobalCss(
|
||||
component: HTMLElement,
|
||||
style: string,
|
||||
name: string,
|
||||
subName = ''
|
||||
) {
|
||||
if (!style) return
|
||||
|
||||
const styleName = subName ? `${name}-${subName}` : name
|
||||
let css = this.processCss(style, name)
|
||||
this.styles[styleName] = css
|
||||
|
||||
if (this.shouldRefresh) {
|
||||
if (!this.head || !this.headFirstElement) {
|
||||
this.head = document.head
|
||||
this.headFirstElement = this.head.firstChild
|
||||
}
|
||||
|
||||
if (!this.headStyle) {
|
||||
this.headStyle = document.createElement('style')
|
||||
if (this.headFirstElement) {
|
||||
this.head.insertBefore(this.headStyle, this.headFirstElement)
|
||||
} else {
|
||||
this.head.appendChild(this.headStyle)
|
||||
}
|
||||
}
|
||||
// 当父节点也是 Web Component时,防止全局注册的 Style 被父节点的
|
||||
// ShadowRoot 隔离,需要再在父节点中插入一份样式
|
||||
if (
|
||||
component.parentNode &&
|
||||
(Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('DocumentFragment') ||
|
||||
Object.prototype.toString
|
||||
.call(component.parentNode)
|
||||
.includes('ShadowRoot'))
|
||||
) {
|
||||
let scoped = document.createElement('style')
|
||||
scoped.innerHTML = css.trim()
|
||||
component.parentNode.appendChild(scoped)
|
||||
}
|
||||
|
||||
let style = ''
|
||||
for (const styleName in this.styles) {
|
||||
const content = this.styles[styleName]
|
||||
style += content
|
||||
}
|
||||
|
||||
this.headStyle.innerHTML = style
|
||||
this.shouldRefresh = false
|
||||
}
|
||||
}
|
||||
}
|
||||
export default new SlotStyleHandler()
|
Loading…
Reference in New Issue