【问题标题】:Announcing information to a screen reader in vue.js using aria-live使用 aria-live 在 vue.js 中向屏幕阅读器宣布信息
【发布时间】:2018-06-11 22:41:40
【问题描述】:

我正在尝试让一个 vue 组件在我的网站上发生不同事件时动态地向屏幕阅读器宣布信息。

我已经让它工作到单击按钮将用文本填充aria-live="assertive"role="alert" 的范围。这在第一次时运行良好,但是,单击具有类似行为的其他按钮会导致 NVDA 在读取新文本之前读取之前的文本两次。这似乎发生在 vue 中,但没有使用 jquery 进行类似的设置,所以我猜这与 vue 呈现给 DOM 的方式有关。

我希望有某种方法可以解决此问题,或者可能是一种更好的方法来向没有此问题的用户阅读文本。非常感谢任何帮助。

Here is a simple component我在一个工作代码沙箱中设置以显示我遇到的问题(导航到 components/HelloWorld.vue 以获取代码)-注意:此沙箱已根据以下答案进行了更改强>。该组件的完整代码如下:

export default {
  name: "HelloWorld",
  data() {
    return {
      ariaText: ""
    };
  },
  methods: {
    button1() {
      this.ariaText = "This is a bunch of cool text to read to screen readers.";
    },
    button2() {
      this.ariaText = "This is more cool text to read to screen readers.";
    },
    button3() {
      this.ariaText = "This text is not cool.";
    }
  }
};
<template>
  <div>
    <button @click="button1">1</button>
    <button @click="button2">2</button>
    <button @click="button3">3</button><br/>
    <span role="alert" aria-live="assertive">{{ariaText}}</span>
  </div>
</template>

【问题讨论】:

    标签: javascript vue.js accessibility wai-aria nvda


    【解决方案1】:

    好的,所以我发现的工作方式更一致,而不是用新文本替换元素中的文本,而是将新元素添加到具有要读取的新文本的父容器中。我没有将文本存储为单个字符串,而是将其存储在一个字符串数组中,该数组将v-for 放到aria-live 容器内的页面上。

    我已经构建了一个完整的组件,它将以各种方式执行此操作,作为任何希望这样做的人的示例:

    export default {
        props: {
            value: String,
            ariaLive: {
                type: String,
                default: "assertive",
                validator: value => {
                    return ['assertive', 'polite', 'off'].indexOf(value) !== -1;
                }
            }
        },
        data() {
            return {
                textToRead: []
            }
        },
        methods: {
            say(text) {
                if(text) {
                    this.textToRead.push(text);
                }
            }
        },
        mounted() {
            this.say(this.value);
        },
        watch: {
            value(val) {
                this.say(val);
            }
        }
    }
    .assistive-text {
        position: absolute;
        margin: -1px;
        border: 0;
        padding: 0;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip: rect(0 0 0 0);
    }
    <template>
        <div class="assistive-text" :aria-live="ariaLive" aria-relevant="additions">
            <slot></slot>
            <div v-for="(text, index) in textToRead" :key="index">{{text}}</div>
        </div>
    </template>

    这可以通过将父级上的变量设置为组件的v-model 来使用,并且对该变量的任何更改都将被读取到屏幕阅读器一次(以及任何时候父容器变为以选项卡为中心) )。

    它也可以被this.$refs.component.say(textToSay); 触发——注意如果父容器变成tab-focused 也会再次触发。可以通过将元素放在不会获得焦点的容器中来避免这种行为。

    它还包括一个插槽,因此可以像这样添加文本:&lt;assistive-text&gt;Text to speak&lt;/assistive-text&gt; 但是,这不应该是动态/小胡子变量,否则当文本更改时您会在原始问题中遇到问题。

    我还更新了the sandbox posted in the question,提供了该组件的工作示例。

    【讨论】:

      猜你喜欢
      • 2018-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      • 2013-08-01
      • 2019-01-11
      • 1970-01-01
      相关资源
      最近更新 更多