【问题标题】:Determine a locale change inherited from a parent element确定从父元素继承的语言环境更改
【发布时间】:2020-05-29 14:17:26
【问题描述】:

我正在尝试编写可识别语言环境的 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 上,我将如何检测更改?

MutationObserver 似乎是一个尴尬的选择:我必须将它附加到父链中的 每个 元素,但不能假设该列表保持静态 - 我必须在组件的每个adoptedconnected 事件上重新附加观察者。

【问题讨论】:

  • A MutationObserver 是观察元素 Y 上属性 X 变化的唯一合理方法。请注意,您不必必须在每个元素上设置 MO,您可以添加document 级别的 MO
  • 这并不能解决尴尬。1。根级别的 MO 将报告属性更改on all elements,即使它们不在父链中。 2. 如果该组件在一个网站中被重复使用十次,最终会在同一个元素上出现十个 MO,观察相同的属性 - 或者,在组件之间共享它时,会破坏组件的原子性。
  • 1.正确(我通常通过在控制台中输入 .1+.2 来结束任何尴尬的辩论,以解释 Web 世界并不完美) 2. 在添加了你的 MO 的 body 标记上添加标记/属性.
  • 1.当然,shadowDOM 内部的突变不会被捕获:stackoverflow.com/questions/46995421/…

标签: javascript html dom localization web-component


【解决方案1】:

一种可能的解决方案是,当元素被添加到页面时,它会递归搜索具有lang 属性的 first 父/祖先,向其添加MutationObserver 并响应更改该特定父元素。

IMO 试图观察所有父母的变化是一种低效的设计选择,而且听起来像是一种矫枉过正的功能。

我没有亲自尝试过,但要检测浏览器语言的变化,请查看languagechange 事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    相关资源
    最近更新 更多