我正在尝试编写一个区域设置感知的自定义元素。为了格式化其输出,它会查找自身及其父元素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 上,我将如何检测更改?
MutationObserver
似乎是一个尴尬的选择:我必须将其附加到父链中的每个元素,但不能假设该列表保持静态 - 我必须在组件的每个adopted
或connected
事件上重新附加观察者。
一个可能的解决方案是,当元素添加到页面时,它会递归搜索具有lang
属性的第一个父/祖先,向其添加MutationObserver
并响应对该特定父元素的更改。
IMO试图为所有父母观察变化是一个低效的设计选择,听起来也像是一个矫枉过正的功能。
我没有亲自尝试过,但要检测浏览器语言的变化,请查看languagechange
事件。