javascript - 为什么定义 computedStyle 属性的访问器描述符不起作用?

标签 javascript html

我想检测 display 上的值变化class 上的 CSS 属性更改属性,我想出了下面的代码片段。

我知道getComputedStyle返回 只读 直播CSSStyleDeclaration对象,但是当元素的样式改变时对象会自动更新,我假设它以某种方式分配了它的属性。

但它没有调用 getter 和 setter。为什么会发生这种情况,然后当它是只读的时它如何分配其属性?

let parent = document.querySelector(".parent");
let child = parent.querySelector(".child");
let style = getComputedStyle(child);

let display = Symbol("display");
style[display] = style.display;

Object.defineProperty(style, "display", {
  get() {
    console.log("getter");
    return style[display];
  },
  set(value) {
    console.log("setter", value);
    style[display] = value;
  }
});

let button = document.querySelector("button");
button.addEventListener("click", () => {
  child.classList.toggle("hide");
});
.child {
  height: 100px;
  background-color: #80a0c0;
}

.hide {
  display: none;
}
<button>Toggle</button>
<div class="parent">
  <div class="child"></div>
</div>

最佳答案

主机提供的对象不需要玩得很好。 :-) (嗯,有 some requirements 甚至在主机提供的对象上。)

尽管在 Chrome 和相关的对象上声称 display property 是一个简单的数据属性(在 Firefox 和 Legacy Edge 上,它更合理,原型(prototype)上的访问器属性):

let style = getComputedStyle(document.querySelector(".child"));
let kind = "own";
do {
    const descr = Object.getOwnPropertyDescriptor(style, "display");
    if (descr) {
        console.log(kind + " property:", descr);
        break;
    }
    if (kind === "own") {
        kind = "prototype";
    } else {
        kind += "'s prototype";
    }
    style = Object.getPrototypeOf(style);
} while (style);
.child {
  height: 100px;
  background-color: #80a0c0;
}

.hide {
  display: none;
}
<button>Toggle</button>
<div class="parent">
  <div class="child"></div>
</div>


……它在撒谎。 :-)(在 Chrome 上。)您正在成功地在对象上创建访问器属性,然后对象停止反射(reflect)对底层 display 的更改元素的属性(因为它只是更新您用符号命名的属性):

let parent = document.querySelector(".parent");
let child = parent.querySelector(".child");
let style = getComputedStyle(child);

let display = Symbol("display");
style[display] = style.display;

Object.defineProperty(style, "display", {
  get() {
    console.log("getter");
    return style[display];
  },
  set(value) {
    console.log("setter", value);
    style[display] = value;
  }
});

let button = document.querySelector("button");
button.addEventListener("click", () => {
  child.classList.toggle("hide");
  console.log("style.display: " + style.display);
});
.child {
  height: 100px;
  background-color: #80a0c0;
}

.hide {
  display: none;
}
<button>Toggle</button>
<div class="parent">
  <div class="child"></div>
</div>


您可以使用 Proxy 复制相同的行为。 :

const realStyle = {
    display: "block"
};
const style = new Proxy(realStyle, {
    get(target, propName) {
        return target[propName];
    },
    set(target, propName, value, receiver) {
        if (propName in target) {
            return;
        }
        return Reflect.set(target, propName, value, receiver);
    }
});

console.log("descriptor for `display`:");
console.log(Object.getOwnPropertyDescriptor(style, "display"));

console.log("style.display = " + style.display);
console.log("Setting it to 'none'");
style.display = "none";
console.log("style.display = " + style.display);

const d = Symbol("display");
style[d] = style.display;
Object.defineProperty(style, "display", {
    get() {
        console.log("getter");
        return style[d];
    },
    set(value) {
        console.log("setter");
        style[d] = value;
    }
});

console.log("style.display = " + style.display);
console.log("Setting it to 'none'");
style.display = "none";
console.log("style.display = " + style.display);
.as-console-wrapper {
    max-height: 100% !important;
}

关于javascript - 为什么定义 computedStyle 属性的访问器描述符不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61836327/

相关文章:

jquery - 我在使用 jQuery 显示和隐藏下拉菜单时遇到问题

HTML/CSS 图像分隔符/分隔符叠加/方法?

javascript - 加载两次 WooCommerce 谢谢页面会重复转换跟踪吗?

javascript - 运行discord bot时出现错误代码(JS)

javascript - 错误类型错误 : Cannot read property 'value' of undefined in ionic when submitting login form

javascript - 文件系统 API : Where are the files and folders located

javascript - 具有良好类分离的主干设置 - 应用程序未定义错误

html - 如何让一个元素占据其父窗口宽度内的窗口宽度?

javascript - 在jquery中获取HTML代码的子部分(匹配整个段落而不是逐行匹配)

html - 为什么我的页脚下面有元素?