This commit is contained in:
那些花儿
2025-09-03 11:33:11 +08:00
parent 6ea2ad37b0
commit 3110ffd35e
@@ -1,17 +1,88 @@
const styleUtil = {
// 为元素及其所有子元素添加scoped属性
addScopedAttribute(el, scopedId) {
if (el && el.setAttribute) {
el.setAttribute(scopedId, '')
// 递归处理所有子元素
const children = el.children || el.childNodes
for (let i = 0; i < children.length; i++) {
styleUtil.addScopedAttribute(children[i], scopedId)
}
}
},
// 移除元素及其所有子元素的scoped属性
removeScopedAttribute(el, scopedId) {
if (el && el.removeAttribute) {
el.removeAttribute(scopedId)
// 递归处理所有子元素
const children = el.children || el.childNodes
for (let i = 0; i < children.length; i++) {
styleUtil.removeScopedAttribute(children[i], scopedId)
}
}
},
scopeCss(css, scopedId) {
// 处理CSS规则,为每个选择器添加[scopedId]
const processedCss = css.replace(/([^{]+){/g, (match, selectors) => {
return selectors.split(',')
.map(selector => {
// 处理深度选择器 >>> 和 /deep/
if (selector.includes('>>>') || selector.includes('/deep/')) {
return selector.replace(/(\s*)(>>>|\/deep\/)(\s*)/g,
`$1[${scopedId}] $3`)
}
// 普通选择器
return `${selector.trim()}[${scopedId}]`
})
.join(',') + '{'
})
return processedCss
}
}
Vue.mixin({
mounted() {
if (this.$options.style) {
const styleId = `style-${this._uid}`
const style = document.createElement("style")
style.id = styleId
// 生成唯一属性
const scopedId = `data-v-${this._uid}`
// this.$el.setAttribute(scopedId, '')
// 为组件内所有元素添加唯一属性
styleUtil.addScopedAttribute(this.$el, scopedId)
//支持函数和字符串
const css = typeof this.$options.style === "function" ? this.$options.style.call(this) : this.$options.style
let css = typeof this.$options.style === "function" ? this.$options.style.call(this) : this.$options.style
// 为每条规则添加属性选择器
css = styleUtil.scopeCss(css, scopedId)
style.textContent = css
document.head.appendChild(style)
// 保存scopedId以便销毁时使用
this._scopedId = scopedId
}
},
beforeDestroy() {
if (this._scopedId && this.$el) {
// 移除所有元素的scoped属性
styleUtil.removeScopedAttribute(this.$el, this._scopedId)
}
if (this.$options.style) {
const styleId = `style-${this._uid}`
const style = document.getElementById(styleId)