浏览器插件开发必备概念——体验优化

826 阅读9分钟

系列文章可以查看《浏览器扩展程序开发笔记》专栏


Options Pages

设置页面允许用户定制扩展程序,以更符合自己的使用习惯。

如果要为扩展程序添加设置页面,需要先在配置清单 manifest.json 的中进行声明注册,有两种类型的设置页面:

  • Full page options 整页的设置页面,需要打开一个标签页。

    在配置清单的选项 options_page 中声明注册作为设置页面的 HTML 文档的路径

    {
      // ...
      "options_page": "options.html",
    }
    

    然后用户可以在浏览器工具栏的扩展程序图标右键点击选择「选项」打开设置页面

    打开设置页面-1

    或者在扩展程序的「详情」页面中选择「扩展程序选项」打开设置页面 打开设置页面-2

  • Embedded Options 内嵌的设置页面,以模态框的形式展示设置页面。

    💡 模态框的大小会根据页面内容自动调整,但有时候可能并不奏效,此时可以为设置页面先提供一个最小的尺寸,以保证布局正常显示。

    在配置清单的选项 options_ui.page 中指向相应的 HTML 文档路径,并设置属性 option_ui.open_in_tabfalse,表示采用内嵌设置页(如果设置为 true 就会打开新的标签页来展示设置页面)。

    {
      // ...
      "options_ui": {
        "page": "options.html",
        "open_in_tab": false
      },
    }
    

    然后用户就可以在在浏览器工具栏的扩展程序图标右键点击选择「选项」,会跳转到相应扩展程序的详情页,同时打开模态框展示设置页面;或者在扩展程序的「详情」页面中选择「扩展程序选项」,打开模态框展示设置页面。

    打开设置页

    💡 在扩展程序的页面中可以通过方法 chrome.runtime.openOptionsPage() 打开设置页面

<button id="go-to-options">Go to options</button>
document.querySelector('#go-to-options').addEventListener('click', function() {
  // 先判断浏览器是否支持该方法
  if (chrome.runtime.openOptionsPage) {
    chrome.runtime.openOptionsPage();
  } else {
    // 如果不支持就手动基于页面路径打开设置页面
    window.open(chrome.runtime.getURL('options.html'));
  }
});

虽然两种方式都可以供用户设置参数,但是有一些不同:

💡 为了可以让用户的设置数据持久化及跨设备同步,可以使用 Chrome 提供的 storage.sync API,记得先在配置清单 manifest.json 中声明注册 strage 权限

Accessibility

可及性,又称为 a11y,是指一系列的设计指南,以便残障人士更易于使用扩展程序,例如快捷键命令可以让视觉障碍人士更方便地使用扩展程序,字幕和翻译功能对视觉障碍人士和外语者有帮助。

开发者可以遵循以下建议,以提高扩展程序的可及性 accessible:

  • 使用正确的语义化 HTML 元素搭建 UI 控件,以便保障可及性。这些控件保证了可以通过键盘(Tab 键)访问操作,且它们的语义性让屏幕阅读器更容易理解。

    语义化 HTML 元素

  • 如果需要使用非语义化的 HTML 元素或 JavaScript 构建 UI 控件时,可以通过 WAI-ARIA,Web Accessibility Initiative - Accessible Rich Internet Applications,一个由 W3C 制定的规范,它通过给 DOM 元素添加一些规定的属性,让我们的开发的网页应用更具语义化。

    💡 WAI-ARIA 属性不会对 web 页面有任何影响,只是让浏览器暴露更多的信息给无障碍 API,例如屏幕阅读器。

    该规范中三个主要的特性:

    • 声明元素的角色和功能,例如 role="navigation" 表示该元素的作用是导航
    • 为元素定义额外的属性,例如 aria-require=true 告知用户该表单是必添的
    • 设定元素的状态,例如 aria-disable="true" 表示该表单禁止输入

    💡 状态和属性的差异之处就是:属性在应用的生命周期中不会改变,而状态可以,用编程的方法改变。

    <div role="toolbar" tabindex="0" aria-activedescendant="button1">
      <img src="buttoncut.png" role="button" alt="cut" id="button1">
      <img src="buttoncopy.png" role="button" alt="copy" id="button2">
      <img src="buttonpaste.png" role="button" alt="paste" id="button3">
    </div>
    

    以上示例中,属性 tabindex="0" 让该元素可以聚焦,并且可以通过键盘来导航,其聚焦顺序由 DOM 结构决定;属性 aria-activedescendant 指定该元素聚焦时,其子代哪一个元素先进行聚焦。

  • 元素可聚焦让用户仅通过键盘也能操作扩展程序页面,应该保证按钮、菜单栏等元素可以聚焦。默认情况下,只有锚标签、按钮、表单控件可以通过键盘聚焦,但是我们可以通过为元素添加属性 tabIndex="0" 让任意元素可以聚焦;也可以通过添加属性 tabIndex="-1" 让该元素无法通过键盘聚焦(但仍可以通过 JavaScript 编程聚焦 elem.focus())。

  • 与通过 Tab 键聚焦元素相比,快捷键可以让用户更方便地操作扩展程序页面的元素,可以参考官方示例如何用快捷键进行导航。如果在扩展程序的页面内提供了快捷键,应该在设置页面 options page 中告知用户。

  • 以下设置可以完善内容的可访问性

    • 文本:选择合适的字体和字号大小以确保文本内容的可读性,而且应该考虑视觉障碍者的使用体验,他们可能需要设置更大的字体,避免将自定义的快捷键与页面缩放的快捷键相冲突。为了确保版型的稳定,应该测试缩放至 200%,查看页面是否还显示正常。应该避免将文字嵌入到图片中,这样不仅无法调整字体,还无法让屏幕阅读器识别;如果必须将文字嵌入图片中,应该在图片的可替代文字(属性 alt)中包含这些文字内容,相关指南可以参考这里

    • 颜色:背景和内容的颜色应该有足够的对比度,可以使用 Colour Contrast Check 工具检查。对于颜色丰富的图表,可以使用色弱模拟器 Coblis 来查看它在不同程度的色弱症人士眼里的效果,调整图表的配色,以使扩展程序对于这些用户更友好。可以考虑为提供不同的色彩主题,或允许自定义配色方案,以便用户有更好的体验。

    • 声音:如果扩展程序需要声音和视频传达信息,应该提供字幕和翻译功能,关于多媒体字幕的相关指南参考这里

    • 图片:为图片提供可替代文字,即属性 alt(文字内容应该用于阐明图像的目的,而不是描述图片的细节),而对于占位图和纯装饰作用的图片,应该将该属性值留空 "",或使用 CSS 来实现(而不是用 DOM)

      <img src="img.jpg" alt="The logo for the extension">
      
  • 更多相关资源:

Internationalization

参考:

国际化 I18N 是指在开发扩展程序时,可以让用户按需切换语言。

💡 关于软件多语言版本的开发

  • 国际化 Internationalization,L18N:软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化传统,使创建不同语言版本时,不需要重新设计源程序代码的软件工程方法。
  • 本地化 localization ,L10N:能够使网站、Web 应用或任何其他形式的内容适用于特定语言的范围和文化圈。

为了让扩展程序更方便地实现国际化,需要遵循以下建议:

  • 将所有用户可见的内容(文本)放在一个 messages.json 文档中,并将该文档放在 _locales/_localeCode_ 相应的目录下(其中 _localeCode_ 是一个语言编码,例如英语就应该使用 en 表示)。

    💡 如果项目中有 _locales 目录,需要在配置清单 manifest.json 的选项 default_locale 中声明默认语言,可以在这里查看具体的语言代码

    messages.json 文档中,它以键值对的形式来定义内容,每一个键都包含一个需要国际化的项(大小写敏感),值是一个对象,其中常用的属性如下:

    • 属性 message 是需要显示的内容
    • (可选)属性 description 是对该项的描述,便于告知翻译者该项的意义。
    // messages.json
    {
      "search_string": {
        "message": "hello%20world",
        "description": "The string we search for. Put %20 between words that go together."
      },
      //  ...
    }
    

    💡 键名不能以 @@ 开头,这一类的键名是保留预定义的项,常用的预定义 message 项如下:

    Message 键名解释
    @@extension_id扩展程序的 ID,对于非国际化的扩展程序该 message 项也可用,💡 但不能用于 manifest.json
    @@ui_locale当前使用的语言
    @@bidi_dir当前的文字方向,ltr 表示从左往右书写的文字,rtl 表示从右往左书写的文字

    例如在 CSS 中使用扩展程序中的静态图片作为背景

    body {
      background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');
    }
    
  • 然后就可以在项目的其他文档中,通过 message 项来使用相应的数据:

    • manifest.json 或 CSS 文档中,通过 __MEG_messagename__ 来使用 message 相应的项 messagename
    • 在扩展程序页面或 JavaScript 脚本中,通过方法 chrome.i18n.getMessage("messagename") 获取相应的项 messagename

    i18n-1.png

    💡 每次新增一种语言,就需要新增一个 message 文件到 _locales/_localeCode_ 目录里。每一种语言中,不必包含与默认语言中定义的全部 message 项。

    i18n file structure

    以上示例是支持英语、西班牙语、韩语的扩展程序项目文件结构

    💡 浏览器会基于用户的语言设置和扩展程序的 default_locale 设置来自动选择采用哪一个 messages.json 文档

Identity

扩展程序可以基于 OAuth 2.0 获取授权,访问 Chrome 用户信息,具体参考 chrome.identity API

💡 关于该授权机制的介绍可以参考这里

Management

管理已安装和正在运行的扩展程序,具体参考 chrome.management API