覆盖元素.样式表.css文本

Override element.styleSheet.cssText

本文关键字:css 文本 样式 元素 覆盖      更新时间:2023-09-26

我想覆盖element.styleSheet.cssText函数

element = document.createElement("style");
element.styleSheet.cssText = ...
Object.prototype.styleSheet.cssText = function(){
    console.log('override');
}

我收到一个错误,指出样式表为空或未定义。我正在使用IE浏览器,所以我希望 stylesheet存在。

任何帮助不胜感激

据我所知,没有真正的方法可以覆盖CSSStyleDeclaration对象上的本机cssText getter。

让我们来看看为什么:

var s = document.createElement('style'),
    style = s.style;
style instanceof CSSStyleDeclaration; //true

到目前为止一切顺利,但是当我们尝试设置 cssText 属性时:

style.cssText = 'something';
style.cssText; //(empty string), the native setter did not allow setting an invalid style

如我们所见,cssText 属性实现了当我们尝试获取/设置 cssText 属性时调用的本机 getter/setter。

,好!让我们重新定义自定义CSSStyleDeclaration.prototype.cssText getter/setter。好吧,这是行不通的,因为似乎 cssText 属性不是来自原型,即使它不会,也无法使用 Object.getOwnPropertyDescriptor 获取自定义 getter/setter,因此我们将无法从我们的自定义函数调用本机 setter。

无论如何,让我们来看看:

Object.defineProperty(CSSStyleDeclaration.prototype, 'cssText', {
    get: function () { return 'overrided'; }
});
document.createElement('style').style.cssText; //(empty string)

那么有解决方案吗?好吧,可能还没有安全的解决方案来做到这一点,但最好的选择是将 style 属性替换为新创建的元素上的自定义访问器。该访问器将返回一个对象,该对象实现与CSSStyleDeclaration实例相同的接口,但所有访问器/函数都将被替换以将操作委托给原始样式对象。

返回的对象基本上充当真实样式对象的代理对象。这将是唯一的方法,因为我们无法访问本机 getter/setters 函数,否则我们可以仅在元素的本机样式对象上重新定义cssText访问器。

在下面的示例中,我通过仅代理 cssText 属性来演示这个想法。

注意:我们创建CSSStyleDeclaration.prototype实例的原因是为了确保styleProxy instanceof CSSStyleDeclaration保持真实。

实现不完整且使用不安全

document.createElement = (function (doc, nativeCreateEl) {
    return function() {
        var el = nativeCreateEl.apply(doc, arguments),
            nativeStyle = el.style,
            styleProxy = Object.create(CSSStyleDeclaration.prototype);
        Object.defineProperty(el, 'style', {
            get: function () {
                return styleProxy;
            }
        });
        Object.defineProperty(styleProxy, 'cssText', {
            set: function (styles) {
                console.log('setting cssText');
                nativeStyle.cssText = styles;
            },
            get: function () {
                return nativeStyle.cssText;
            }
        });
        return el;
    };
})(document, document.createElement);
var el = document.createElement('div'),
    s = el.style;
s.cssText = 'test'; //logs setting cssText
s.cssText; //(empty string) -> this is expected
s.cssText = 'color: red;'; //logs setting cssText
s.cssText; //color: red;