HTML 元素的 hidden 属性不生效的问题
HTML 中的hidden
属性用于显示和隐藏元素,如e.hidden = true
。但是当元素设置了display
样式时,不论是在元素样式属性style
中设置还是在 CSS 类中设置,则hidden
属性就会失去作用。所以,要想继续使用 hidden 属性,必须解决display
样式的问题。解决问题的代码如下:
Object.defineProperties(HTMLElement.prototype, {
'hidden': {
get() {
return $parseBoolean(this.getAttribute('hidden') ?? false);
},
set(hidden) {
if (typeof(hidden) != 'boolean') {
hidden = $parseBoolean(hidden, true, this);
}
if (hidden) {
this.setAttribute('hidden', '');
if (this.style.display != '') {
this.setAttribute('style-display', this.style.display);
this.style.display = 'none';
}
else if (window.getComputedStyle(this).display != '') {
this.setAttribute('inbox-display', '');
this.style.display = 'none';
}
}
else {
this.removeAttribute('hidden');
if (this.hasAttribute('style-display')) {
this.style.display = this.getAttribute('style-display');
this.removeAttribute('style-display');
}
else if (this.hasAttribute('inbox-display')) {
this.style.display = '';
this.removeAttribute('inbox-display');
}
}
}
}
});
以下是代码解释。
- 使用
Object.defineProperties
为所有元素HTMLElement
重新定义hidden
属性,当然使用Object.defineProperty
也可以。 - 当元素的
hidden
属性值为true
时,那么元素上会多一个空值hidden
属性,如<p hidden></p>
,这就是元素隐藏和显示的标志。可以用setAttribute('hidden', '')
进行设置隐藏,当然这个属性无论你设置成什么值元素总会隐藏,所以要用removeAttribute('hidden')
取消隐藏。 - 不能在定义逻辑中使用
this.hidden = true
或this.hidden = false
进行隐藏和显示,会造成堆栈溢出,因为会不断回调自身。 - 先说隐藏逻辑,即
hidden
要设置为true
时,如果在元素style
属性中设置了display
样式时,则通过style-display
属性暂时存储display
的值,因为不知道原本设置的什么值。如果 CSS 类内设置了display
样式,用window.getComputedStyle
方法可以获得,则设置inbox-display
属性,这个值不需要暂存,因为修改不了。 - 然后显示逻辑,如果有
style-display
属性,则把这个属性的值重新赋值给style.display
即可,需要使用完移除style-display
属性。如果有inbox-style
属性,则用style.display = ''
显示元素,然后移除inbox-display
属性。
对于页面初始化时,可以这样做,就是重新设置一遍。
$$('[hidden]').forEach(e => {
e.hidden = e.getAttribute('hidden');
});
(本文完)