TASK: #103599 - add SlotStyleHandler

This commit is contained in:
luojiahao 2022-08-30 10:10:42 +08:00
parent 5d7ec91fa7
commit 4a46290727
2 changed files with 104 additions and 0 deletions

View File

@ -9,3 +9,4 @@
- add indicator-page-point
- add blur
- add contaienr
- add SlotStyleHandler

View File

@ -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()