Web 用户体验设计提升实践

本文首发于微信公众号“ Shopee技术团队”。

前言

本文是基于 Shopee 供应链团队内部 WMS(Warehouse Management System,仓库管理系统) 项目的整体重构,总结而出的一份 Web 用户体验设计提升指南。

因为是对已经存在的项目进行完全的推翻重构,所以在整个过程中,我们一直在思考如何尽可能地站在用户的角度,通过前端设计去提升改进用户的体验与感受,真正达到重构的目的及意义。

一个 Web 页面或是一个 App,想让别人用得爽,获得良好的用户体验,可能需要包括但不限于:

  • 急速的打开速度
  • 令人眼前一亮的 UI 设计
  • 酷炫的动画效果
  • 丰富的个性化设置
  • 易用、友好的便捷操作
  • 贴心的细节
  • 关注残障人士,良好的可访问性
  • ……

所谓的用户体验设计,是秉承着以用户为中心的思想的一种设计手段,以用户需求为目标而进行的设计。设计过程注重以用户为中心,用户体验的概念从开发的最早期就开始进入整个流程,并贯穿始终。

良好的用户体验设计,是团队在产品开发中每一个环节共同努力的结果。

本文将主要从页面呈现、交互细节、可访问性三个方面入手,分享一些在实际开发过程中积攒的有益经验。通过这篇文章,你将能:

  • 了解到一些细节是如何影响用户体验的;
  • 了解到如何在尽量小的开发改动下,提升页面的用户体验;
  • 了解到一些优秀的交互设计细节;
  • 了解基本的无障碍功能及页面可访问性的含义;
  • 了解基本的提升页面可访问性的方法。

1. 页面呈现

就整个页面的展示和页面内容的呈现而言,不同的展示方式,所得到的效果截然不同。

这其中有非常多值得注意的细节。接下来分为几个要点进行阐述:

  • 自适应的布局
  • 重点内容的排布设计
  • 兼容不同场景与异常回退
  • 图片的呈现及异常处理
  • 适当的过渡与动画

1.1 自适应的布局

先来看一些布局相关的问题。

布局,是前端在重构页面过程中需要提前进行规划思考的,一般应该考虑清楚以下几个问题:

  • 对于 PC 端,项目是全屏布局还是定宽布局?用户是否还在使用 IE?
  • 对于全屏布局,需要适配的最小宽度是多少?
  • 对于移动端布局,你知道用户设备的分布吗?最少兼容到 Android 什么版本?iOS 什么版本?
  • 内容应该以什么样的方式呈现?

到今天,各种设备浩如烟海,移动端屏幕尺寸纷繁复杂(下图仅仅是到 2019 年各种安卓设备屏幕尺寸图的分布):
Web 用户体验设计提升实践_第1张图片

不过,我们的重构项目整体是以 PC 为主的 ToB 项目,所以这里主要以 PC 端为例进行讲解。

对于大部分 PC 端的项目,首先需要考虑的肯定是最外面的一层包裹。假设就是 .g-app-wrapper

首先,对于 .g-app-wrapper,有几点是我们在项目开发前必须弄清楚的:

  • 项目是全屏布局还是定宽布局?
  • 对于全屏布局,需要适配的最小的宽度是多少?

对于定宽布局,就比较方便了,假设定宽为 1200px,那么:

.g-app-wrapper {
    width: 1200px;
    margin: 0 auto;
}

利用 margin: 0 auto 实现布局的水平居中。在屏幕宽度大于 1200px 时,两侧留白;屏幕宽度小于 1200px 时,则出现滚动条,保证内部内容不乱。

Web 用户体验设计提升实践_第2张图片

现代布局更多的是全屏布局。其实现在也更提倡这种布局,即可随用户设备的尺寸和能力而变化的自适应布局。

自适应布局通常有左右两栏,左侧定宽,右侧自适应剩余宽度。另外还会有一个最小宽度。那么,它的布局应该是这样:

.g-app-wrapper {
    display: flex;
    min-width: 1200px;
}
.g-sidebar {
    flex-basis: 250px;
    margin-right: 10px;
}
.g-main {
    flex-grow: 1;
}

Web 用户体验设计提升实践_第3张图片

这里利用了 flex 布局下的 flex-grow: 1,让 .main 进行伸缩,占满剩余空间,利用 min-width 保证了整个容器的最小宽度。

这是最基本的自适应布局。对于现代布局,我们应该尽可能考虑到更多的场景。做到:

Web 用户体验设计提升实践_第4张图片

底部 footer

下面一种情形也非常常见:

页面存在一个 footer(页脚)部分,如果整个页面的内容高度小于视窗的高度,则 footer 固定在视窗底部,如果整个页面的内容高度大于视窗的高度,则 footer 正常流排布(也就是需要滚动到底部才能看到 footer)。

看看效果:

Web 用户体验设计提升实践_第5张图片

这个需求如果能够使用 flex 的话,用 justify-content: space-between 可以很好地解决。同理,使用 margin-top: auto 也非常容易完成:

...
.g-container {
    height: 100vh;
    display: flex;
    flex-direction: column;
}

.g-footer {
    margin-top: auto;
    flex-shrink: 0;
    height: 30px;
    background: deeppink;
}

Codepen Demo - sticky footer by flex margin auto

当然,实现它的方法有很多,这里仅给出一种推荐的解法。

1.2 重点内容的排布设计

下面这一块关于重点内容的展示。

1.2.1 重要内容及功能的展示

让吸引用户注意力的元素前置。如果我们的页面存在需要让用户了解、处理的核心信息或者表单,尽可能将其位置放在上方,让用户更容易获取这部分信息。

Web 用户体验设计提升实践_第6张图片

将用户需要的信息、重要的功能展示出来而不是藏起来。

Web 用户体验设计提升实践_第7张图片

类似于导航、搜索等高频操作,一定不要让用户多次点击才能用到。

1.2.2 处理动态内容:文本超长

对于所有接收后端接口字段的文本展示类的界面,都需要考虑全面。正常情况如下,是没有问题的:

Web 用户体验设计提升实践_第8张图片

但是我们是否考虑到了文本会超长?超长了会折行还是换行?

Web 用户体验设计提升实践_第9张图片

对于单行文本,使用单行省略:

{
    width: 200px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

Web 用户体验设计提升实践_第10张图片

当然,目前对于多行文本的超长省略,兼容性也已经非常好了:

{
    width: 200px;
    overflow : hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

Web 用户体验设计提升实践_第11张图片

1.2.3 处理动态内容:保护边界

对于一些动态内容,我们经常使用 min/max-widthmin/max-height 对容器的高宽限度进行合理的控制。

在使用它们的时候,也有一些细节需要考虑到。
譬如经常会使用 min-width 控制按钮的最小宽度:

.btn {
    ...
    min-width: 120px;
}

当内容比较少的时候是没问题的,但是如果内容比较长,就容易出现问题。下图就是使用了 min-width 却没考虑到按钮的过长的情况:

这里就需要配合 padding 一起:

.btn {
    ...
    min-width: 88px;
    padding: 0 16px
}

借用 Min and Max Width/Height in CSS 中一张非常好的图,作为释义:

Web 用户体验设计提升实践_第12张图片

1.3 兼容不同场景与异常回退:空数据内容展示

这个模块是兼容不同场景与异常回退,是一个常常被忽略的地方。

页面经常会有列表搜索、列表展示。那么,既然存在数据的正常情况,当然也会存在搜索不到结果或者列表无内容可展示的情形。

对于这种情况,一定要注意空数据结果页面的设计;同时要知道,这也是引导用户的好地方。对于空数据结果页面,分清楚:

(1)数据为空

  • 用户无权限——要告知用户无权限访问的原因和解决方案
  • 搜索无结果——告知用户搜索无数据的结果,如有必要可推荐相关内容
  • 筛选无结果——一般直接告知筛选无结果
  • 页面无数据——文案设计有几个方向:

    • 告诉用户这里将会存放什么数据
    • 给用户一个主动创造数据的理由,比如通过话术引起用户心理共鸣
    • 若页面无数据会给用户造成困惑,则可以说明原因打消用户的困惑

(2)异常状态

  • 网络异常——指出当前状态为网络异常,并给出解决方案
  • 服务器异常——指出当前状态为服务器异常,并给出解决方案
  • 加载失败——加载失败主要会由网络异常或服务器异常造成
  • 不同的情况可能对应不同的空数据结果页面,附带不同的操作引导

例如网络异常,可以引导用户刷新页面:

Web 用户体验设计提升实践_第13张图片

或者确实是零结果,譬如没有订单信息,可以引导用户去进行订单的创建(引导消费):

Web 用户体验设计提升实践_第14张图片

小小总结一下,上述篇幅一直都在阐述一个道理:开发时,不能仅仅关注正常现象,要多考虑各种异常情况,思考全面,做好各种可能情况的处理

1.4 图片的呈现及异常处理

图片在我们的业务中非常常见。但是要完美处理图片,并不轻松。

1.4.1 给图片同时设置高宽

有的时候产品和设计会商定,只能使用固定尺寸大小的图片,我们的布局可能是这样:

Web 用户体验设计提升实践_第15张图片

对应的布局:

  • 图片描述

ul li img {
    width: 150px;
}

假设后端接口出现一张非正常大小的图片,上述不加保护的布局就会出问题:

Web 用户体验设计提升实践_第16张图片

所以对于图片,我们总是建议同时写上高和宽,避免因为图片尺寸错误带来的布局问题。

ul li img {
    width: 150px;
    height: 100px;
}

另外,给 标签同时写上高宽,可以在图片加载之前提前占住位置,避免图片从未加载状态到渲染完成状态高宽变化引起的重排问题。

1.4.2 object-fit

限制高宽也可能会出现问题,比如图片被拉伸了,非常难看:

Web 用户体验设计提升实践_第17张图片

这个时候我们可以借助 object-fit,它能够指定可替换元素的内容(也就是图片)该如何适应它的父容器的高宽。

ul li img {
    width: 150px;
    height: 100px;
    object-fit: cover;
}

利用 object-fit: cover,使图片内容在保持宽高比的同时填充元素的整个内容框。

Web 用户体验设计提升实践_第18张图片

object-fit 还有一个配套属性 object-position,它可以控制图片在其内容框中的位置(类似于 background-position),m 默认是 object-position: 50% 50%。如果你不希望图片居中展示,可以使用它去改变图片实际展示的位置。

ul li img {
    width: 150px;
    height: 100px;
    object-fit: cover;
    object-position: 50% 100%;
}

Web 用户体验设计提升实践_第19张图片

像是这样,object-position: 100% 50% 指明从底部开始展示图片。

这里有一个很好的 Demo 可以帮助你理解 object-position

CodePen Demo - Object position

1.4.3 考虑屏幕 dpr:响应式图片

正常情况下,图片的展示应该没有什么问题了,但我们还可以做得更好。

在移动端或者一些高清的 PC 屏幕(例如苹果的 Mac Book),屏幕的 dpr 可能大于 1。这种时候,我们可能还需要考虑利用多倍图去适配不同 dpr 的屏幕。

正好, 标签提供了相应的属性 srcset 供我们操作。

不过,这是比较旧的写法,srcset 增加了新的 w 宽度描述符,需要配合 sizes 一起使用,所以更好的写法是:

利用 srcset,我们可以给不同 dpr 的屏幕提供最适合的图片。

1.4.4 图片丢失

好了,当图片链接没问题时,已经处理好了。接下来还需要考虑,当图片链接挂了,应该如何处理。

处理的方式有很多种。最好的处理方式,是我在张鑫旭老师《图片加载失败后 CSS 样式处理最佳实践》这篇文章中看到的。这里简单讲讲:

  • 利用图片加载失败,触发 元素的 onerror 事件,给加载失败的 元素新增一个样式类;
  • 利用新增的样式类,配合 元素的伪元素,展示默认兜底图的同时,还能一起展示 元素的 alt 信息。
图片描述
img.error {
    position: relative;
    display: inline-block;
}

img.error::before {
    content: "";
    /** 定位代码 **/
    background: url(error-default.png);
}
 
img.error::after {
    content: attr(alt);
    /** 定位代码 **/
}

我们利用伪元素 before ,加载默认错误兜底图,利用伪元素 after,展示图片的 alt 信息:

Web 用户体验设计提升实践_第20张图片

到此,完整的对图片的处理就算完成了,完整的 Demo 你可以戳这里看看:CodePen Demo - 图片处理

1.5 适当的过渡与动画

好的页面呈现需要适当的过渡与动画,让整体交互体验更加流畅。适当增加过渡与动画,能够很好地让用户感知到页面的变化,它们有如下作用:

  • 减少认知负荷
  • 防止变化视盲
  • 空间上营造更好的印象
  • 让用户界面鲜活起来

这一块内容也可以放在交互设计优化,读者朋友们了解就好。

1.5.1 loading 等待动画

页面上随处可见的 loading 效果,其实就是这样一种作用,让用户感知页面正在加载,或者正在处理某些事务。

1.5.2 骨架屏动画

骨架屏的布局与页面的视觉呈现保持一致,能引导用户将关注点聚焦到感兴趣的位置,并且能避免过长时间的等待。

1.5.3 滚动平滑:使用 scroll-behavior: smooth 让滚动丝滑

使用 scroll-behavior: smooth,可以让滚动框实现平稳地滚动,而不是突兀地跳动。看看效果,假设如下结构:

First section
Second section
Third section

不使用 scroll-behavior: smooth,就是突兀地跳动切换:

Web 用户体验设计提升实践_第21张图片

要改善这种现象,可以给可滚动容器添加 scroll-behavior: smooth,实现平滑滚动:

{
    scroll-behavior: smooth;
}

Web 用户体验设计提升实践_第22张图片

1.5.4 粘性滚动:使用 scroll-snap-type 优化滚动效果

sroll-snap-type 可能算得上是新的滚动规范里面最核心的一个属性样式。

scroll-snap-type:属性定义在滚动容器中的一个临时点(snap point)如何被严格地执行。

光看定义有点难理解,简单而言,这个属性规定了一个容器是否对内部滚动动作进行捕捉,并且规定了如何去处理滚动结束状态。让滚动操作结束后,元素停止在适合的位置。

看个简单示例:

Web 用户体验设计提升实践_第23张图片

当然,scroll-snap-type 用法非常多,可控制优化的点很多,限于篇幅无法一一展开。

1.5.5 控制滚动层级,避免页面大量重排

这个优化可能稍微有一点难理解。需要了解 CSS 渲染优化的相关知识。

先说结论,控制滚动层级的意思是尽量让需要进行 CSS 动画(可以是元素的动画,也可以是容器的滚动)的元素的 z-index 保持在页面最上方,避免浏览器创建不必要的图形层(GraphicsLayer),能够很好地提升渲染性能

这一点怎么理解呢?一个元素触发创建一个 Graphics Layer 层的其中一个因素是:

  • 元素有一个 z-index 较低且包含一个复合层的兄弟元素。

根据上述这点,我们对滚动性能进行优化的时候,需要注意两点:

  • 通过生成独立的 GraphicsLayer,利用 GPU 加速,提升滚动的性能;
  • 如果本身滚动没有性能问题,不需要独立的 GraphicsLayer,也要注意滚动容器的层级,避免因为层级过高而被其他创建了 GraphicsLayer 的元素合并,被动地生成一个 GraphicsLayer ,影响页面整体的渲染性能。

1.5.6 转场动画

从一个模块跳转到另外一个模块的时候,转场动画就派上了用场。它的作用在于:在合适的时机,将视线引导到适当的位置。

看下面的例子:

在点击按钮弹出弹窗的过程中,弹窗不是突兀地出现,而是从点击的地方放大至视窗中间,这个引导的过程让体验更加丝滑。

1.5.7 操作动画

这个和 loading 有点类似,遇到一些耗时操作,比如下载时,我们可以通过定制一个特殊的动画,减缓用户等待的烦躁、焦虑感。

Web 用户体验设计提升实践_第24张图片

上述动画的代码,你可以猛击:

CodePen Demo - Download interaction By Milan Raring

当然,除了下载等待,我们也可以在一些重要的操作交互上,例如点赞、关注等,定制特殊的动画,让过程更加生动有趣。下面这个是某网站的点赞动画:

Web 用户体验设计提升实践_第25张图片

上述点赞动画的代码,你可以猛击:

CodePen Demo - Twitter 点赞动画

1.5.8 使用过渡与动画的误区

合理使用动画能让页面增色不少,但同时要避免踩入下面的一些坑:

  • 动画没有关联性
  • 为了动画而动画,没有目的性
  • 过于缓慢,阻碍交互
  • 不够明确

简单解释一下。譬如动画关联性,关联性背后的逻辑能帮助用户在界面布局中理解刚发生的变化,是什么导致了变化。

下图中,左边是关联性差的,右边是关联性好的:

Web 用户体验设计提升实践_第26张图片

还有一点,大部分动画不宜过久,要足够迅速。

缓慢的动画产生了不必要的停顿。过渡动画应该保持简短,因为用户会频繁看到它们。让动画持续时间保持在 300ms 或更短。

看下图演示,同一个转场动画会被频繁触发,所以尽可能地让每次的动画不要持续过久,能够帮助用户节省更多时间。

总而言之,动画和过渡要用得恰当好处,避免为了动画而动画非常重要

2. 交互设计优化

接下来一个大环节是一些关于交互的细节。

什么是交互设计?交互设计(Interaction Design, IXD)是定义、设计人造系统的行为的设计领域,它定义了两个或多个互动的个体之间交流的内容和结构,使之互相配合,共同达成某种目的

2.1 Web 端交互方式

Web 端交互围绕计算机为中心,主要涉及键盘、鼠标两类设备的交互。

Web 用户体验设计提升实践_第27张图片

关于交互设计,一些比较通用的准则有:

  • Don’t make me think
  • 符合用户的习惯与预期
  • 操作便利
  • 做适当的提醒
  • 不强迫用户

Web 用户体验设计提升实践_第28张图片

2.2 Don’t make me think

有一本书就叫 Don’t make me think,它所想表述的核心是,尽可能让产品做到高可用性,让用户无须思考也能明确无误地使用产品中的各项功能。

那么,我们的页面如何尽可能做到高可用性呢?

2.2.1 使用习惯用法

使用习惯用法。当我们设计一个新的页面时,页面位置、功能设置、视觉元素应当和惯常用法相差无几,这样才能让用户有舒适感。

这里并不是要扼杀大家的想象力,让所有页面都一成不变。根据产品的形态及受众,大部分页面是不适用于各种天马行空的想象的。

例如下面这样一个 PC 端页面结构,这种布局已经非常常见。遇到这种页面,用户能够非常快速地在指定区域找到想要的元素及信息:

Web 用户体验设计提升实践_第29张图片

可以再和我们的 WMS 重构后的页面作比较,整体是非常类似的:

Web 用户体验设计提升实践_第30张图片

采用习惯用法的设置能够让人快速上手新的陌生的页面或者功能。

2.2.2 降低视觉噪声

另外一种做法是降低视觉噪声,让用户快速聚焦。

譬如弹窗背后的阴影、虚化,就是非常好的降低视觉噪声的手段。

Web 用户体验设计提升实践_第31张图片

这一点还是非常好理解的,也属于常见设计手段之一,在我们内部的相关组件、自研组件库已经沉淀得很好了。

2.3 符合用户的习惯与预期

接下来是符合用户的习惯与预期,它的意义在于减少用户的思考,符合用户的习惯,让用户的体验更加舒适。

下面这几种弹窗,哪一个是更好的选择?

Web 用户体验设计提升实践_第32张图片

三个弹窗可供操作的按钮分别是:

  • 右下角的取消和确认,同时右上角的 X 可以关闭弹窗;
  • 只有右下角的取消和确认;
  • 只有确认按钮。

更好的选择应该是第一个:同时有取消和确认按钮,右上角的 X 可以关闭弹窗。因为这样最符合用户的习惯预期。

看看这个 Windows 下的弹窗:

Web 用户体验设计提升实践_第33张图片

大部分 Windows 的弹窗,都是有取消、确认加上右上角的 X 按钮的。这种弹窗的好处在于:

  • 视觉原因,元素平衡;
  • 符合用户习惯,大多数用户都是 Windows 操作系统过来的;
  • 交互一致性,降低用户学习成本;
  • 提升页面的可访问性和无障碍访问性。

2.3.1 优化手势:不同场景应用不同 cursor

对于不同的内容,最好给与不同的 cursor 样式,CSS 原生提供了非常多种常用的手势。

在不同的场景使用不同的鼠标手势,符合用户的习惯与预期,可以很好地提升用户的交互体验。

首先对于按钮,就至少会有三种不同的 cursor,分别是可点击、不可点击、等待中:

{
    cursor: pointer;    // 可点击
    cursor: not-allowed;    // 不可点击
    cursor: wait;    // loading
}

Web 用户体验设计提升实践_第34张图片

除此之外,还有一些常见用法:对于一些可输入的 Input 框,使用 cursor: text;对于提示 Tips 类,使用 cursor: help;放大缩小图片 zoom-inzoom-out 等等:

Web 用户体验设计提升实践_第35张图片

一些常用的简单列一列:

  • 按钮可点击: cursor: pointer
  • 按钮禁止点击:cursor: not-allowed
  • 等待 Loading 状态:cursor: wait
  • 输入框:cursor: text
  • 图片查看器可放大可缩小:cursor: zoom-in/ zoom-out
  • 提示:cursor: help

当然,实际 cursor 还支持非常多种,可以在 MDN 或者下面这个 CodePen Demo 中查看完整列表:
CodePen Demo - Cursor Demo

2.3.2 点击区域优化:伪元素扩大点击区域

按钮是我们网页设计中十分重要的一环,而按钮的设计也与用户体验息息相关。

考虑这样一个场景:在摇晃的车厢上或者是单手操作着屏幕,有的时候一个按钮死活也点不到。

让用户更容易点击到按钮无疑能很好地提升用户体验,并提升页面的访问性。尤其是在移动端,按钮通常都很小,但是受限于设计稿或者整体 UI 风格,我们不能直接去改变按钮元素的高宽。

那么,有什么办法在不改变按钮原本大小的情况下增加点击热区呢?

借助伪元素可以轻松实现。伪元素也是可以代表其宿主元素来响应鼠标交互事件的。我们可以这样写:

.btn::before{
  content:"";
  position:absolute;
  top:-10px;
  right:-10px;
  bottom:-10px;
  left:-10px;
}

当然,在 PC 端下这样子看起来有点奇怪,但是合理地用在点击区域较小的移动端则能取得十分好的效果:

Web 用户体验设计提升实践_第36张图片

2.4 操作便利

好的系统,操作起来应该是流畅的。同时,它能够通过一些小细节打动用户。

2.4.1 快速选择优化:user-select: all

操作系统或者浏览器通常会提供一些快速选取文本的功能。看看下面的示意图:

Web 用户体验设计提升实践_第37张图片

快速单击两次,可以选中单个单词;快速单击三次,可以选中一整行内容。但如果核心内容被分隔符分割,或者成为潜藏在一整行中的一部分,这个时候选取起来就比较麻烦。

利用 user-select: all,可以将需要一次选中的内容进行包裹,用户只需要点击一次,就可以选中该段信息:

.g-select-all {
    user-select: all
}

给需要一次选中的信息加上这个样式,该细节作用在一些需要复制粘贴的场景时,非常好用。

在我们 WMS 的很多操作页面,需要频繁从表格中复制一些基础信息,例如下述的 Location IDCell Name,由于完整的字段使用了分隔符 -,所以一次点击是无法选中整段信息的,而利用 user-select: all 可以很好地解决这个痛点:

Web 用户体验设计提升实践_第38张图片

别看只是减少一次点击鼠标的次数,但正是这些细节的累积,才更能让用户感受到开发者的用心。

CodePen - user-select: all 示例

2.4.2 选中样式优化:::selection

CSS 还提供了一个 ::selection 伪类,可以控制选中的文本样式(只能控制 colorbackgroundtext-shadow),进一步加深效果。

Web 用户体验设计提升实践_第39张图片

CodePen - user-select: all && ::selection 控制选中样式

2.4.3 添加禁止选择:user-select: none

有快速选择,也就会有它的对立面——禁止选择。

对于一些可能频繁操作的按钮,可能会出现如下尴尬场景:

  • 文本按钮的快速点击,触发了浏览器的双击快速选择,导致文本被选中:
    Web 用户体验设计提升实践_第40张图片
  • 翻页按钮的快速点击,触发了浏览器的双击快速选择:

对于这种场景,我们需要把不可被选中的元素设置为不可被选中,利用 CSS 可以快速实现这一点:

{
    -webkit-user-select: none; /* Safari */
    -ms-user-select: none; /* IE 10 and IE 11 */
    user-select: none; /* Standard syntax */
}

这样,无论点击频率多快,都不会出现内容被选中的尴尬情况:
Web 用户体验设计提升实践_第41张图片

2.5 跳转优化

现阶段,单页应用(Single Page Application)的应用非常广泛,Vue 、React 等框架大行其道。但是有的常见写法也容易衍生一些小问题。

譬如,点击按钮、文本进行路由跳转,经常会出现这种代码: