我正在尝试编写一个可识别语言环境的custom element。要格式化其输出,它会在自身及其父元素上查找lang
属性,然后回退到浏览器navigator.language
UI本地化。
format (d, m, s) {
const lang = (this.closest('[lang]') || document.querySelector('html')).lang;
let list = navigator.languages;
try {
list = Intl.getCanonicalLocales(lang);
} catch (e) {}
const format = new Intl.NumberFormat(list, {
maximumFractionDigits: 2
}).format;
return `${d}° ${m}′ ${format(Math.round(s * 100) / 100)}″`;
}
每次组件更改其值时,它将为我提供最佳信息。但是,它不包括在运行时更改lang
属性的情况。如果在组件本身上更改了属性,则可以观察到它的更改:
static get observedAttributes() { return ['lang']; }
attributeChangedCallback (name, oldValue, newValue) {
if (name === 'lang') // trigger re-rendering
}
但是如果更改发生在父元素甚至是继承设置的浏览器UI上,我将如何进行检测?
A MutationObserver
似乎是一个尴尬的选择:我必须将其附加到父链中的every元素,但不能假定该列表保持静态-我必须重新附加观察组件的每个adopted
或connected
事件。
一种可能的解决方案是,将元素添加到页面时,它递归搜索具有lang
属性的first父级/祖先,向其添加MutationObserver
并响应对此的更改特定的父元素。
IMO试图观察所有父母的变化是一种低效的设计选择,而且听起来像是一种过大的功能。
我没有亲自尝试过,但是要检测浏览器语言的更改,请查看languagechange
事件。