htmlxScheduler是一个类似于Google日历的JavaScript日程安排控件,日历事件通过Ajax动态加载,支持通过拖放功能调整事件日期和时间,事件可以按天,周,月三个种视图显示。
DHTMLX Scheduler官方最新版免费下载试用,历史版本下载,在线文档和帮助文件下载-慧都网
在本教程中,我们将使用两个强大的工具:DHTMLX Scheduler库和Angular框架来创建一个全面的酒店客房预订应用程序。在这篇文章中,我们的目标是创建一个看起来像这样的应用程序:
Angular酒店预订应用将能够显示酒店房间、房间类型、房间状态、特定日期的预订和预订状态,该应用程序还允许执行CRUD操作。
如果您刚开始配置DHTMLX Scheduler来预订房间或将其集成到Angular应用程序中,我们还为您提供了专门的教程:
在开始之前,请确保您已经有了Node.js和Angular CLI。
要创建应用程序,使用如下命令:
ng new room-reservation-angular
操作完成后,我们可以进入app目录并运行应用程序:
cd room-reservation-angular
ng serve
现在如果打开打开http://127.0.0.1:4200,应该看到初始页面。ng serve命令将监视源文件,并在必要时修改和重建应用程序。
让我们定义Reservation、Room、RoomType、CleaningStatus和BookingStatus模型,执行如下命令:
ng generate interface models/reservation model
ng generate interface models/room model
ng generate interface models/roomType model
ng generate interface models/cleaningStatus model
ng generate interface models/bookingStatus model
在models文件夹中新创建的reservation.model.ts文件中,我们将添加以下代码:
export interface Reservation {
id: number;
start_date: string;
end_date: string;
text: string;
room: string;
booking_status: string;
is_paid: string;
}
在room.model.ts、room-type.model.ts、cleaning-status.model.ts、booking-status.model.ts文件中,添加下面的代码行:
export interface Room {
id: number;
value: string;
label: string;
type: string;
cleaning_status: string;
}
export interface RoomType {
id: string;
value: string;
label: string;
}
export interface CleaningStatus {
id: string;
value: string;
label: string;
color: string;
}
export interface BookingStatus {
id: string;
value: string;
label: string;
}
下载DHTMLX Scheduler PRO版最新的试用版(直接戳这里>>),将下载的包解压缩到本地机器的项目根文件夹中。为了能够将Scheduler嵌入到应用程序中,您应该获得DHTMLX Scheduler代码。执行如下命令:
npm install ./scheduler_6.0.5_trial
创建一个新的组件,为此运行以下命令:
ng generate component scheduler --skip-tests
在scheduler文件夹中新创建的scheduler.component.html文件将包含调度器的模版,让我们添加下一行代码:
<div #scheduler_here class='dhx_cal_container' style='width:100%; height:100vh'>
<div class='dhx_cal_navline'>
<div style='font-size:16px;padding:4px 20px;'>
Show rooms:
<select id='room_filter' [(ngModel)]='selectedRoomType' (ngModelChange)='filterRoomsByType($event)'></select>
</div>
<div class='dhx_cal_prev_button'> </div>
<div class='dhx_cal_next_button'> </div>
<div class='dhx_cal_today_button'></div>
<div class='dhx_cal_date'></div>
</div>
<div class='dhx_cal_header'></div>
<div class='dhx_cal_data'></div>
</div>
使用ngModel和ngModelChange指令来建立组件中select元素和数据之间的交互,请将FormsModule模块添加到app.module.ts文件中。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SchedulerComponent } from './scheduler/scheduler.component';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
SchedulerComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
将在名为scheduler.component.css的单独文件中声明scheduler样式,央视可以以下面的方式呈现:
@import '~dhtmlx-scheduler/codebase/dhtmlxscheduler_flat.css';
:host {
display: block;
position: relative;
height: 100%;
width: 100%;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.dhx_cal_container #room_filter:focus {
outline: 1px solid #52daff;
}
.timeline-cell-inner {
height: 100%;
width: 100%;
table-layout: fixed;
}
.timeline-cell-inner td {
border-left: 1px solid #cecece;
}
.dhx_section_time select {
display: none;
}
.timeline_weekend {
background-color: #FFF9C4;
}
.timeline_item_cell {
width: 32%;
height: 100% !important;
font-size: 14px;
text-align: center;
line-height: 50px;
}
.cleaning_status {
position: relative;
}
.timeline_item_separator {
background-color: #CECECE;
width: 1px;
height: 100% !important;
}
.dhx_cal_event_line {
background-color: #FFB74D !important;
}
.event_1 {
background-color: #FFB74D !important;
}
.event_2 {
background-color: #9CCC65 !important;
}
.event_3 {
background-color: #40C4FF !important;
}
.event_4 {
background-color: #BDBDBD !important;
}
.booking_status,
.booking_paid {
position: absolute;
right: 5px;
}
.booking_status {
top: 2px;
}
.booking_paid {
bottom: 2px;
}
.dhx_cal_event_line:hover .booking-option {
background: none !important;
}
.dhx_cal_header .dhx_scale_bar {
line-height: 26px;
color: black;
}
.dhx_section_time select {
display: none
}
.dhx_mini_calendar .dhx_year_week,
.dhx_mini_calendar .dhx_scale_bar {
height: 30px !important;
}
.dhx_cal_light_wide .dhx_section_time {
text-align: left;
}
.dhx_cal_light_wide .dhx_section_time > input:first-child {
margin-left: 10px;
}
.dhx_cal_light_wide .dhx_section_time input {
border: 1px solid #aeaeae;
padding-left: 5px;
}
.dhx_cal_light_wide .dhx_readonly {
padding: 3px;
}
.collection_label .timeline_item_cell {
line-height: 60px;
}
.dhx_cal_radio label,
.dhx_cal_radio input {
vertical-align: middle;
}
.dhx_cal_radio input {
margin-left: 10px;
margin-right: 2px;
}
.dhx_cal_radio input:first-child {
margin-left: 5px;
}
.dhx_cal_radio {
line-height: 19px;
}
.dhtmlXTooltip.tooltip {
color: #4d4d4d;
font-size: 15px;
line-height: 140%;
}
要使scheduler容器占据主体的整个空间,您需要在src文件夹下的styles.css文件中添加以下样式:
body,
html {
width: 100%;
height: 100%;
margin: unset;
}
要继续,我们需要导入所需的模块,并将必要的代码行添加到scheduler.component.ts文件中:
请在GitHub上查看scheduler.component.ts 的完整代码。
现在让我们将新组件添加到页面中,为此打开app.component.html(位于src/app中)并在其中插入scheduler标签:
<scheduler></scheduler>
在下文中,我们将为大家继续介绍如何加载和保存数据,记得持续关注哦~
辑导语:弹窗,不只是“弹出式广告”,它是一把双刃剑,用得好能使用户更加聚焦,用得不好则可能使用户不快甚至击退潜在用户。那么,弹窗要怎么设计呢?本文作者对弹窗进行了详细的分析,一起来看一下吧。
说到弹窗,很多人对弹窗的印象还停留在“弹出式广告”: 网站为了获利,广告商为了增加点击率,那时候的广告就像枪林弹雨,用户无处可躲,进而恼羞成怒,甚至想要砸掉电脑。
广告弹窗曾经在2010年被《时代》杂志评为最糟糕的发明之一。
我们如今再熟悉不过的淘宝曾经为在电商领域存活下来,也不得已使用大量的“流氓广告”,虽然这的确使得用户恼怒,但是不得不说,淘宝也因此刷脸频繁而让大家更熟悉它。
弹窗是一把双刃剑,用的好确实使用户更加聚焦,而如果使用的不恰当,可能会使用户不快甚至击退潜在用户。在设计弹窗时,你有没有遇到过下面的困惑?
可以说,弹窗设计的好不好,可以极大的体现一个设计师的基本功扎不扎实,别看一个小小的弹窗设计起来似乎非常容易,但面对不同的用户场景、业务背景,弹窗背后的思考从未停止,今天就让我们全方位地了解弹窗。
在正式认识弹窗前,我们不妨设想以下的场景: 你正在家中做事情,但是这个时候电话铃响了, 你不得不放下手中的事情去接电话, 但是假如在智能家居环境中,你可以通过人工智能自动接电话,同时你手中的事情仍然在继续中。
如果说把前者比喻成跳转的页面,那么后者就是弹窗,它能够在吸引你当下注意力的同时,不离开当前的场景。
目前设计界对于弹窗的定义多种多样, 从外观布局上看,弹窗是页面上层弹出的容器,容器中承载着文本、按钮、选项、标签或表单等组合内容;从设计目的上看,弹窗是用户与产品间对话的一种方式,是对用户注意力的一种引导形式,根据抓取用户注意力的多少,可具体定义为Dialogue、Actionbar、Popover、Toast、Snackbar等等特定形式。
从广义上讲,弹窗其实并没有如它的定义那样框的那么死,有时候弹窗不一定有容器,比如追剧时常见的弹幕,也是一种新型弹窗; 再比方说新手引导,也是一种弹窗。不过,咱们在这里谈论的还是狭义上的大家在规范中所常见的弹窗,那些非典型的弹窗就不在今天讨论的范围之内。
弹窗的基本组成可以拆解为:
为了使用户更聚焦于弹窗,我们会在弹窗容器下方页面上方加一层遮罩, 通常这种遮罩是半透明黑色,如果遮罩颜色越深,用户越能够专注于当前页面; 遮罩颜色越浅,用户的跳出感越小,产品也更亲民。
当页面中出现多个弹窗时,也就意味着多个遮罩层,这个时候遮罩层的颜色该怎么确定呢?
根据各大规范,弹窗叠弹窗不建议超过三个,当弹窗大于等于3个时,遮罩的颜色就不再改变。这里再补充一点, 当弹窗数量过多,一个叠一个,用户容易迷失放向,这时候可以采用位置错层的方法。
弹窗主体可以拆解为标题、内容、动作按钮。
弹窗的标题和内容的书写规则,在后文中有详细描述,这里不再赘述。
弹窗的动作按钮一般不超过3个:
1个按钮: 那一定是可以关闭弹窗的操作,比如信息公告类的弹窗的“我知道了”。
2个按钮:这是最常见的情况。一个是推进任务进程的动作,一个是取消。
3个按钮:这种情况比较少见,比如“了解更多”,但这会让用户离开弹窗,导致弹窗任务未完成,所以不推荐使用。 如果有更多内容需要向用户展示,可以内嵌一个信息扩展,点击图标在弹窗下方展示更多信息,这样了解更多信息的同时,也不用离开弹窗。
至于弹窗按钮的位置摆放,有两种常见的摆放规则:等分居中摆放和某一侧摆放(右侧居多),不同平台有不同的摆法,接下来举例说明:
1)Material design中右对齐
2)IOS中等分居中摆放
3)在Fiori规范中,手机端的按钮是等分居中摆放,但是在电脑端采用右对齐
对于模态和非模态的关闭方式,从根本上说是很不同的。
对于模态弹窗,它的关闭方式只有做出选项选择后弹窗才会消失, 包括“取消”选项。 而非模态弹窗的关闭方式就很多了,总结下来有四种方式:
1)关闭按钮(叉叉)
通常是位于右上角,少数规范把关闭按钮放在左上角,只要保持一致即可。
2)取消按钮
通常和“确认”或者其他推进任务完成的动作按钮放在一起,成对出现。
3)ESC键
敲击ESC键,也可以退出非模态弹窗。 Esc键是英文单词escape的缩写, 在1960年由IBM的一位程序员创建,它的功能是“撤销”、“退出”。
尽管如今使用鼠标进行交互的人占绝大多数,但是出于无障碍设计(包容性设计)的需要, 通过键盘完成交互是必不可少的,所以ESC按钮也是必需的。
而且这类快捷键上的优化能够大大提升用户使用效率,减轻用户的操作成本。
尤其在B端产品中,调用键盘进行操作优化,是一个不可忽视的用户爽点。
4)点击遮罩区域
遮罩区域就是弹窗背后的内容区,通常为了使用户更聚焦会加上一层暗色遮罩,当用户点击遮罩区域后,非模态弹窗会自动消失,不过为了避免用户误触,如果弹窗是表单等需要用户输入的内容时,这些内容要自动保存。
对于“取消”和“关闭”按钮,这里想要再阐述更清楚一些:先举个生活中常见的例子,假设你有一个爱问十万个为什么的小孩,你正在津津有味地追剧,结果他跑过来问你问题,他还没张口呢,你就捂住耳朵不听不听,这个呢就相当于弹窗右上角的关闭按钮(叉叉),不过关闭按钮仅仅存在于非模态弹窗中,用户可以不做任何选择地关掉弹窗,而模态弹窗要求用户必须做出某种选择,不给用户逃避的机会,所以模态弹窗是没有关闭按钮的。
然后小孩问你是鸡生蛋还是蛋生鸡,你听了这个问题也不知道怎么解释,只能和小孩说,这个问题我也不知道怎么回答,这个就相当于弹窗的“取消”按钮。
虽然“取消”按钮和关闭按钮(叉叉)最终都会导致弹窗关闭,但是从逻辑上而言,是不同的。
弹窗可以分为模态弹窗和非模态弹窗两种类型, 这两个概念来源于开发人员的术语。
当打开一个模态弹窗后,它所属页面的进程被打断了,必须等用户处理完毕模态弹窗后,才能够回到刚才正在进行的页面。
举个例子,你准备删除一个重要的文件,系统弹出一个弹窗,问你确认要删除吗?这个你时候你必须下一个明确的指令,选择删除或者不删除,然后你才可以离开当前界面,我们可以简单的把模态弹窗理解为用户不得不做的选择。
再来看非模态弹窗,非模态弹窗允许用户在不打断当前页面的同时,去处理其他任务,举个例子,设计师们最熟悉不过的PS,你可以同时调用多个弹窗去更改画面参数,因为艺术创作是一个多线过程,艺术家可以想到什么参数就改变什么参数。
模态和非模态只是一个比较概括性的概念,而且不同的规范里可能对相似的某一类弹窗的称呼完全不同或者有轻微差异,接下来我分别根据 Microsoft-Fluent UI、Google- Material Design、IOS 规范中拿出一些比较有代表性的弹窗类型详细讲一讲。
1)Actionsheet
类型:模态弹窗
参考规范:IOS Design
简介:Action sheet一次展示和当前语境相关的两个或者更多的动作,非必要不要展示太多的动作选项,以及避免在动作列表中使用滚动条。
关键点:
2)Modal
类型:模态弹窗
参考规范:Microsoft-fluent UI
简介:Modals也是一种模态弹窗,它需要人们把注意力从当前页面短暂转移到弹窗上,并且需要用户的交互动作。和Dialog不同的是, Modal 更适合长文本内容,如隐私条款、知情同意书等等,抑或是要求用户进行较为复杂的操作行为如更改页面设置。
3)Dialog
类型:模态弹窗
参考规范:Microsoft-fluent UI
简介:Dialog是一种模态弹窗,它需要人们把注意力从当前页面短暂转移到弹窗上,并且需要用户的交互动作。它基本被用于较为简单的场景下,如确认信息、删除文档、做出一个选择。
分类:
使用场景:
关键点:
4)Drawer
类型:模态弹窗
参考规范:Material Design
简介:Drawer是一种容器, 它的性质和生活中的抽屉很像, 通常用来放置和某个特定窗口相关的一些信息或者选项。默认情况下, Drawer是隐藏的, 它通常是通过一个按钮或者菜单触发, 从父级界面的一侧滑出来,所以它不能够脱离父级界面而单独存在。
关键点:避免使用drawer,现在流行的软件已经很少会使用drawer了,而且也不提倡使用。如果你想展示补充性的内容的话,不妨尝试一下panel、popover、sidebars、split views。
5)Popover
类型:模态、非模态
参考规范:IOS Design
简介:当你轻触一个区域时,Popover会短暂的出现在其他内容的上层, 通常来说,一个Popover包含一个箭头,指向它弹出来的位置。当你点击屏幕中的其他区域或者Popover上的按钮时,一个非模态的popover会取消显示。而模态的popover只能通过点击它上面的cancel或者其他按钮而取消显示。
Popover更最适合大屏幕的设备, 并且可以容纳很多元素,包括导航栏、工具栏、tab栏、表格、图片、地图、传统视图等等。当Popover可见时,在它消失前,当前页面的其他交互是不能进行的。
关键点:
6)Snackbar &; Toast
类型:非模态
参考规范:Material Design
简介:此处将Snackbar和Toast放在一起讲,因为这两者十分相似但是又有所差异。
Toast属于一种轻量级的反馈,它比Snack bar的提示程度轻, 常常以小弹框的形式出现,一般出现1到2秒会自动消失, 但为了保持一致性,同个产品尽量使用同一位置。 和Snack bar有所区别的是,Toast常常被用作系统提示消息,不包含动作按钮,可以出现在屏幕上中下任意位置, 并且只有安卓中有Toast。
Snack bar被用来通知用户该程序正在发生或者即将发生的进程,也就是说Snack bar的内容一定是和用户当前操作相关的,而Toast弹出的内容和当前操作没有任何关系,只是一个系统提示,比如说“你收到了一条消息”这种。
Snack bar同样短暂的出现在屏幕的底部,不中断用户体验,也不需要用户任何操作,自己就会消失。它继承了Toast的所有基础属性,但是不同的是:
这里值得注意的一点,Material design中已经不再推荐使用Toast而是更推荐Snack bar了,但是目前Toast在安卓应用上仍然在被广泛使用。
下面着重介绍一下Snack bar。
使用场景:既想要展示信息,又想最小程度地打断用户注意。
关键点:
7)Tooltip
类型:非模态
参考规范:Material Design
简介:当Tooltip通过鼠标悬停、聚焦、或者触摸后被激活,它会识别一个与之对应的元素然后在该元素附近显示简短、描述性的文案,通常是对该元素的功能解释,在停留短暂的时长后,Tooltip会自行消失。
关键点:
8)Andriod Notification
类型:非模态
参考规范:Material Design
简介:在软件不被使用期间,Notifications提供关于软件简短、时不时的的相关资讯。这种资讯可以是来自其他用户的交流信息或者提供任务提醒。
Notifications如何被用户注意到:
9)Message bar
类型:非模态
参考规范:Microsoft Fluent UI react 8.65.1
简介:显示软件或者文件的错误、警告、重要的信息。比如说,一个文档上传失败,那么错误的messabe bar就会出现。
关键点:
10)Coachmark &; Teaching bubble
类型:非模态
参考规范:Microsoft Fluent UI react 8.65.1
简介:Coachmark 是为了吸引用户注意力并且增加用户使用他们的机会,当鼠标悬停或者选择Coachmark时,Teaching bubble就会显示。
关键点:
弹窗作为一种容器,在选用时常常和抽屉、页面一起比较,那么在给定一个内容时,我们该根据什么来选择使用哪种类型的容器呢?
首先,我们先把这三个容器的定义搞清楚。
接着,在我们被给定一个需求时,要先分析这个需求,从一下几个方面去判断:
1)信息承载量
既然是容器,必然有容量这一说,在这里用信息承载量可能更合适,信息承载量包括图片、视频、文本、表格等等各种形式的信息量,当信息量非常大,密密麻麻十分恼人时,弹窗自然是不被推荐使用的了,通常来说信息承载量大小有这么一个规律: 页面 >; 抽屉 >; 弹窗。
不过信息承载量只是考虑的第一步,是一个比较宏观的方面,不是决定性因素。
2)页面独立性
独立性可以理解为与前一个或者当前页面的联系是否紧密。 页面的独立性最高,当你不断打开一个又一个新的页面,常常会记不得上一个页面的内容,这就是因为这些页面的内容相对独立,关联性不大。
而我们仅仅是从定义上不难看出,弹窗和抽屉的独立性较低, 弹窗的前提是不离开当前页面内容,甚至弹窗的主体不能够遮住当前页面的重要内容;抽屉是建立在父级页面基础上的,它是对父级页面内容的补充。
大多数弹窗是与当前用户正在执行的操作内容相关的,比如在表单录入的场景下,选择时间会弹出时间弹窗,选择地址时会弹出地址簿弹窗。
抽屉比较适合内容度较深、逻辑紧密、概括性简短的内容但不是时时必须展示的内容, 如购物网站的目录导航、safari收藏夹等等。
而页面和页面之间的逻辑性不强甚至可以毫无逻辑,比如跳转到一个莫名其妙的广告页面。
3)页面切换成本
当用户因为某个业务需求需要频繁在A和B页面间切换时,这个时候我们就要考虑切换成本。
抽屉有一个固定位置的触发按钮,所以当需要频繁操作时,用户能够快速找到并弹出抽屉,减少学习成本。
弹窗回到页面的速度也很快, 如果是非模态弹窗,它可能会自行消失、点击遮罩区域消失或者点击关闭按钮消失,对于模态弹窗来说,只要用户做出了明确的操作后,弹窗就会消失,自然的回到当前页面。
页面是切换成本最高的,一般需要点击返回按钮,返回上一级页面,这个时候页面加载需要一定的时间,用户需要快速认知一个全新的页面需要一定的适应时间,所以页面的切换成本最高。
1)UX Writing规则
2)标题
标题是用户第一眼注意到的内容,用户扫一眼标题来快速了解这个弹窗是做什么的,所以标题的重要性不言而喻。
3)内容
4)如何优化按钮文案
操作清晰可预测。 减少使用中性词, 从而避免用户停顿思考,让用户看到文本的瞬间就明白按钮时会发生什么。
优先考虑“动词+名词”的形式,如果不能够这样表达,再去考虑“确认”“取消”“关闭”这些中性词。
5)反馈
操作后的反馈对于用户体验也很重要,正如你打游戏通关时,系统会发出喝彩的声音,比如你提交了一个表单弹窗,当你提交后,应当显示提交成功的反馈。
首先要明确的一点,在各大规范中都不推荐使用滚动条,因为首先弹窗的内容承载量就不大,如果是业务场景复杂的弹窗,我们可以采用Tab或者分步弹窗,尽量去避免在弹窗中使用滚动条。
那么,如果不得不使用滚动条的情况下,有几点要注意:
1) Web端
调查市面上的电脑分辨率, 从数据图中可见,分辨率900 * 1080是主流,最小的分辨率是1024 * 768。
俗话说“一个水桶,盛水量得看最短的那块木板”, 所以理论上来说, 只要弹窗能满足1024*768的分辨率,就可以适配市面上所有的电脑。
各个平台根据自身业务量和需求的差异性,可以根据内容量再给弹窗的尺寸分类,常见的可以分为: 超级大、大、中、小尺寸,比如蚂蚁中台的Alert的几种尺寸:
2) 手机端
手机端的弹窗一般都是全屏显示,除了一些特殊的弹窗类型如Alert, Error, Notification会有固定的尺寸规范。
弹窗中有两种生效模式: 即时提交模式(immediate commit model)和延迟提交模式(delayed commit model)
举个例子,如mac的偏好设置中的桌面屏保,当你选中后立即生效,这里没有提交也没有确认按钮,这种就是即时提交模式;而延迟提交模式更为常见,比如注册网站会员时,你需要填好所有的信息,然后确认一遍,最后提交。
即时提交模式更适合本身操作量不大,但是切换频繁的操作,尤其对于视觉听觉上的效果改变,即时提交是非常高效的,常见的比如更换手机铃声、选择照片滤镜、更换电脑壁纸等等。
延迟提交模式在B端中非常普遍,它需要用户仔细斟酌输入的内容,用户修改编辑满意后再确认提交,比起效率,它更重视质量、减少出错率。
1) 弹窗内的导航:
当弹窗内有次级弹窗(同一个容器,不同的内容)时,在次级弹窗标题部分,有一个返回按钮,可以返回主弹窗。
2) 用户改变弹窗的显示大小
比如一些长列表,里面的条目很多,有一些字段因为比较长,被隐藏住了一部分,用户需要滚动滑动条,来查看更多的条目,而当弹窗的大小可以被改变时,用户就可以增大弹窗,从而每滚动一次,就能查看更多的条目,减少滚动条的操作次数,更大的视野也让用户的体验感更好。
这里有两个小细节值得注意:
3) 拖拽移动弹窗
有时候一个弹窗弹出来正好遮挡住了底部页面的重要内容,所以弹窗需要有被移动和拖拽的功能:
4) 弹窗的防错功能
在填写表单场景下,比方说用户已经花费了二十分钟填写表单,但是他不小心碰到了键盘上的Esc键,弹窗自动退出,那么他的内容就消失了,这对用户来说是十分糟糕的,有如五雷轰顶!
所以对于一些弹窗而言,添加防错功能是很有必要的,在不小心误触后,弹窗不会立刻关闭,而是弹出一个确认弹窗“你确定要离开吗?你的内容将会丢失”,这个确认弹窗可以大大的降低误触带来糟糕后果,毕竟很少人会连续误触两次嘛。
确认弹窗确实是防错的一个思路,还有一个思路是为弹窗添加自动保存功能,当弹窗不小心关闭后再打开时,刚才的内容还在,不过新用户的心情会经历一个跌宕起伏: “糟糕了!我的心血没了!(哭泣)”–奥!!它们竟然还在,太惊喜了!”
需要明确的一点,在各大规范中,都不推荐弹窗叠弹窗,即使必要情况下,也会限制弹窗的数量,至于为什么这样限制,打个比方你就懂了:大家小时候玩过俄罗斯套娃吧,每打开一个娃娃会发现里面还藏着一个娃娃,试想把娃娃换成弹窗,弹窗中还有弹窗。
但是在复杂的大型企业软件中,不可避免的会出现多个弹窗的情况,我们又该怎么解决呢?
根据用户的目标和任务的对应关系,弹窗和弹窗之间的关系可以分为线性和非线性关系。
1)非线形关系
比如Photoshop,里面的大量窗口都是非线形关系,我可以调一下这个参数,再跳到另一个窗口改变另一个参数,这些参数本身并不存在什么逻辑关系,所以Photoshop的工作台可以将窗口随意的打开、隐藏、关闭,可以根据设计师的使用频率自定义工作台的内容窗口,而面对复杂大量的功能,PS给了诸如搜索的工具,让用户自主的快速找到自己需要的功能。
对于多个非线形弹窗,与其耗费心机的建立一个复杂的结构导航,不如给他们工具,让用户找到他们自己想要的东西。
2)线形关系
当弹窗和弹窗之间存在紧密的逻辑关系时,常见的有三种形态:
举个例子,叮叮的“新建项目”:
假设用户的目标是想要从已有项目中复制一个模版: 点击全部模版后,跳到模版界面,这一步就是“A容器中弹出B容器”。
进入模版弹窗后,点击新建模版,选择“从已有项目中新建”,可以看出这一步的弹窗的容器没有变化,只是将弹窗的内容区域进行改变,这就是“同一容器不同内容”。
而“关闭A容器后,弹出B容器”,这个就不太常见,比如通常我们卸载一些流氓软件时,会确认卸载之后,再确认一次,使得用户十分恼怒,这些流氓软件为了留下来真的费尽心机 ; 还有就是在填写非常重要的信息时,系统为了提醒用户“你一定要填写正确,因为这是不可更改的哦”所以会确认两次。
这个场景不常见,所以绝大多数弹窗只要一个确认弹窗就可以了。
我们从对话框传递的信息的性质和来源, 可以将对话框分为系统弹窗、信息展示弹窗、操作弹窗。《About Face 4》一书中将弹窗更细致地分为属性、功能、通知、公告、进度弹窗,其实理解起来是一样的: 进度和公告是系统弹窗,通知属于信息展示弹窗,功能弹窗就是操作弹窗。
系统弹窗:这是由应用程序直接启动,而不是用户请求发出的,比如“版本升级到2.0”“页面崩溃了”。
信息展示弹窗:顾名思义,就是展示信息的弹窗,这个信息可以是来自其他用户的消息、也可以是查看详情等等。
操作弹窗:用户需要对弹窗执行具体的动作,比如常见的表单录入、确认删除、上传信息等等。
一般的简单场景下,不需要再搭建额外的层级关系, 用常见的简单的方式就可以完成需求, 但是在复杂的业务场景下,我们可能会遇到各种各样棘手的问题,如信息太多、信息太复杂.
于是我们将一些页面中会用到的层级框架运用到弹窗中,但是切记弹窗的承载量是很小的,不要滥用这些手段(比如说弹窗中又有Tabbar,又有侧边栏,这样是很忌讳的),这里提供几种解决思路:
Tab是一种导航控件,当页面的内容眼花缭乱时,我们可以将内容分类然后放入不同的Tab页面中,如Mac中的系统偏好设置的显示器设置。
Tab选项卡的形式是多样化的, 包括仅文字、仅图标、图标+文字、带有次级选项的Tab选项、带数字/角标等等,设计师根据业务场景选择最合适的。
当Tab和底部操作区同时存在时,操作区的层级永远是最高的,所以说当点击操作区按钮时,其生效的范围是所有Tab,而不是当前Tab。
如果用户想在当前tab页面完成操作的话,这个时候可以删掉底部的操作区,推荐使用选择控件如单选框/复选框, 当勾选选项的瞬间,这个行为生效。
在使用Tabbar时有几个小细节要注意:
由于弹窗的宽度限制, Tabbar可承受的数量有限, 当Tab数量太多时,不妨考虑用Sidebar,以腾讯会议的设置弹窗举例。 Sidebar和Tabbar类似,都是导航控件, 所以同样地,如果用户想在当前sidebar选项页面完成操作的话,推荐使用选择控件如单选框/复选框,它也是立刻生效。
在表单录入场景中, 当信息又多又乱的时候,往往会降低用户的阅读效率,增加用户的认知成本,分组就是一个很好的解决办法。将同类的信息归纳成一组,可以给每个组加上一个标题,也可以只是在组和组之间加上分割线,界面更加清晰,操作流程更加高效。
分步弹窗适用于有一定的先后逻辑的操作步骤,必须完成第一步才能进行第二步,不可以像Tabbar或者Sidebar一样随心所欲地去任意位置,最常见的就是网站注册。
这样做有几个好处:
弹窗使我们不得不聚焦于当前任务中,但是在一些信息录入场景中,我们录入的信息并不像我们的身份信息一样信手拈来,比如商品信息的录入,这个时候可以采用侧边栏的形式将参考信息放在旁边。
以叮叮的“新建工作待办”——添加执行人举例子: 为了减轻用户的记忆压力,叮叮在右侧提供一个常驻的侧边栏,用户可以通过“最近聊天”“我的好友”“我的群组”等方式查询到自己好友的姓名,这个侧边栏于左边的页面是相对独立的。
弹窗规范虽然目前来说已经比较完善了,但是随着业务场景的复杂化和多元化,我相信还会有更多新的规则产生, 这就要求设计师不仅仅要了解并合理运用规范,更要勇于质疑和思考,去不断地完善规范。
以上是我对弹窗的一些思考和总结,如果你有不同的想法,欢迎与我交流! 期待听到你的声音!
本文由郝小七指导http://www.woshipm.com/u/917803
作者:自来卷夏忆
本文由 @自来卷夏忆 原创发布于人人都是产品经理,未经许可,禁止转载
题图来自 Unsplash,基于 CC0 协议
期开始尝试将新文章预发表,预发表的文章仅展示在公众号主页(不会群发),以供提前预览,想要看新文章的可以在主页查看,有问题欢迎随时指出。新文章会在合适的时间群发给各位小伙伴!
全文约 5800 字,预计阅读需要 20 分钟
作为一名前端开发,Chrome Devtools 是最常用的工具之一,它提供了很多实用的调试功能。Chrome 团队也在一直积极地更新新版本,本文就来盘点自 Chrome 110 以来,Devtools 中新增的实用调试功能,总有一个你用的上!
该版本中,在Elements面板的Styles选项中新增了一个自定义属性部分。通过使用@property CSS 规则,可以明确地定义CSS自定义属性,并在样式表中进行注册,而无需编写任何JavaScript代码。
通过在Elements > Styles中悬停在属性名称上,可以查看其描述符并通过工具提示来查看已注册属性的详细信息。点击工具提示中的链接可以展开显示已注册属性的部分。
现在搜索结果会显示每行代码中找到的所有匹配项。之前,每行代码只显示第一个匹配项。这种新的行为在搜索压缩文件时特别有用。当点击搜索结果时,它会在编辑器中打开文件,并且不仅在垂直方向上滚动到匹配位置,还会在水平方向上进行滚动。
此外,搜索功能得到了速度提升。下面是改变前(左侧)和改变后(右侧)的对比。
另外,搜索功能现在支持忽略列表,并且不会显示已忽略文件的搜索结果。
现在可以通过拖放的方式重新排列 Sources 面板左侧的边栏。
现在,Sources面板具备以下功能:
DevTools 现在支持更多的导航按键操作:
优化了本地覆盖功能,因此可以在没有访问权限的情况下,通过 Network 面板轻松模拟远程资源的响应头和网页内容。
要覆盖网页内容,需要打开 Network 面板,右键点击一个请求,然后选择“Override content”。
如果已经在DevTools中设置了本地覆盖但将其禁用了,现在 DevTools 会自动启用本地覆盖功能。如果尚未设置本地覆盖,DevTool s会在操作栏中提醒你选择一个文件夹来存储覆盖内容,并授权 DevTools 访问该文件夹。
设置完本地覆盖后,DevTools 会进入 Sources > Overrides > Editor 页面,可以进行网页内容的覆盖操作。
请注意,在 Network 面板中,被覆盖的资源会以“Saved.”的标识显示。将鼠标悬停在图标上可以查看哪些内容被覆盖了。
现在还可以覆盖XHR和fetch请求的内容。通过这样的覆盖,即使后端和API尚未准备好,也可以模拟API的响应来调试网页。
DevTools 目前支持以下请求类型的内容覆盖:图像(例如avif、png)、字体、fetch和XHR、脚本(css和js)以及文档(html)。对于不支持的类型,DevTools 现在会将“Override content”选项置灰。
为了帮助开发者专注于编写代码,因此,Network 面板新增了一个过滤器,过滤掉了可能在Chrome中安装的扩展程序发送的无关请求。要过滤掉所有发送到chrome-extension:// URL的请求,可以勾选“Hide extension URLs”选项。
此外,DevTools 现在不会尝试加载扩展程序的源映射文件,因此将不会看到与代码无关的“无法加载源映射”警告。另外,由代码导致的类似警告现在会显示在Sources面板底部的信息栏中,而不是控制台中显示。
现在在请求的头部中,HTTP状态码旁边会显示易于理解的文本,以便更快地了解请求的处理情况。以往只能看到数字状态码,现在还提供了相应的可读性更强的描述性文本,使得解读和理解请求的处理结果更加方便。
还可以将鼠标悬停在请求表中的状态码上,以查看相同的文本信息。
现在在请求的响应选项卡中,对于具有应用程序/[子类型]+json MIME子类型(如ld+json、hal+json等)的请求,会正确解析响应并提供更美观的显示效果。可以对响应数据进行格式化,使其更易读和易于理解。以前可能只能以原始的、紧凑的形式展示 JSON 数据,而现在提供了更好的可视化格式化效果。
Performance 面板现在在网络轨迹中的事件摘要中显示两个优先级字段:初始优先级和(最终)优先级,而不仅仅是单一的优先级。通过这个额外的字段,可以看到事件的获取优先级是否发生了变化,并调整下载顺序。
此外,还可以在 Network 面板的优先级列中找到相同的信息,并通过启用“Big request rows”设置来查看。
现在,默认情况下启用了 Settings > Preferences > Code folding 选项。该选项允许折叠代码块。
如果需要折叠代码块,将鼠标悬停在代码块开始旁边的行号上,然后单击折叠图标即可。再次单击{...}以展开该代码块。
此外,Settings > Preferences > Automatically reveal files in the sidebar选项现在也默认启用。该设置使得在切换标签页时,Sources -> Page 中的文件树会选择当前在编辑器中打开的文件。
Chrome 团队正在重新引入用户可能导航到的未来页面的完全预渲染。为了进行调试,开发者工具将在 Application 面板中添加Preloading 部分。新的预取和预渲染(统称为“导航预加载”)使用了 Speculation Rules API,而不是基于链接的资源提示。
在下面的演示中,在 Application > Preloading 部分,可以检查以下内容:
DevTools 现在有一个与Chrome更好对齐的全新外观,并使用了全新的配色方案。使用新颜色前后的对比如下图所示。
DevTools 进行了多项改进,可帮助您更快地识别和调试缺少样式表的问题:
在Elements > Styles中的 Easing Editor(缓动编辑器)中,现在支持线性时间函数。
使用 Easing Editor,可以轻松地通过点击调整过渡时间函数和动画时间函数的值。在这个版本中,Easing Editor 得到了线性时间函数的支持。
要配置线性时间函数,点击线性选择器按钮。要添加控制点,请在线上任意位置单击。要删除控制点,可以双击它。还可以选择预设之一:linear, elastic, bounce, emphasized。
Application > Storage部分现在支持存储桶。存储桶是彼此独立的,因此可以为数据片段指定驱逐优先级,并确保最有价值的数据不会被删除。每个存储桶可以存储与已建立的存储API(如IndexedDB和CacheStorage)相关的数据。
打开DevTools,导航到Application > Storage > Indexed DB,并运行代码。DevTools 现在会显示存储桶及其内容。选择一个存储桶以查看其元数据。
现在,统一的元数据视图也适用于本地存储(local storage)、会话存储(session storage)和缓存存储(cache storage)部分。
Elements 面板中为子网格(subgrid)添加了一个新的标志。这个功能目前在Chrome Canary中处于实验阶段。要检查和调试嵌套的子网格,它从父网格继承轨道的数量和大小,点击标志即可。它会切换一个覆盖层,在元素视口的顶部显示列、行及其编号。
在Elements > Styles中,将鼠标悬停在选择器名称上,可在工具提示中查看它的特异性权重(优先级)。
在Elements > Styles中,将鼠标悬停在自定义CSS属性名称上,可以查看其取值。
Sources 面板对于预处理的CSS文件,例如SASS、SCSS和LESS,增加了以下功能:
现在可以使用快捷方式更快地设置条件断点。要打开断点对话框,请按住 Command (MacOS) 或 Control (Windows / Linux),然后单击 Sources > Editor 左侧的行号。
现在 Settings > Ignore List > Content scripts injected by extensions默认情况下是启用的。启用此设置后:
此外,忽略列表的选项有了更清晰的文本。
默认情况下,Network > Response 现在会对压缩过的响应体进行格式美化,与 Sources 面板类似。
此外,SVG 文件还具有语法突出显示功能。
Devtools 默认开启 Settings > Experiments > WebAssembly Debugging: Enable DWARF support 。
这个实验特性可以让开发者在 Wasm 应用中暂停执行和调试 C 和 C++ 代码,同时提供了所有的调试信息:
Chrome的自动填充功能可以根据保存的信息(如地址或支付信息)自动填写表单。为了帮助开发者轻松调试与自动填充相关的问题,Elements面板现在可以用红色波浪线突出显示这些问题。
要查看此功能,需要启用设置:Settings > Experiments > Highlights a violating node or attribute in the Elements panel DOM tree 。
在DOM树中将鼠标悬停在突出显示的问题上,然后点击"View issue",就会打开Issues标签页,其中列出了所有检测到的问题并提供关于出错原因的线索。
现在,Recorder 面板允许在录制过程中添加断言,并提供所有运行时数据。
要添加断言,需要开始新的录制,与页面进行交互,然后点击"Add assertion"。Recorder 会插入一个waitForElement类型的步骤,可以进行自定义。
还可以配置用来断言的步骤,例如JavaScript中的条件语句、节点的子元素数、元素可见性等。
现在可以在 Network 面板中覆盖响应头。之前,需要访问Web服务器才能尝试更改HTTP响应头。
通过响应头覆盖,可以在本地原型化修复各种头部,其中包括但不限于:
要覆盖一个头,可以导航至 Network > Headers > Response Headers,将鼠标悬停在头部的值上,点击编辑,并进行修改。
也可以添加自定义头:
要在一个地方编辑所有的覆盖设置,请编辑Sources > Overrides中的".headers"文件。在这个文件中,还可以点击 Add override rule,使用通配符(*)来覆盖多个请求。
为了帮助开发者在调试过程中更快地找出问题,增强的堆栈跟踪现在隐藏了来自 Nuxt 3.3 或更高版本生成的源代码中的帧。DevTools会跳过这些帧:
为了实现这些改进,DevTools、Nuxt、Vite 和 Rollup 团队合作采用了"X-Google-IgnoreList"源映射扩展:
为了帮助开发者更快地诊断CSS问题,Styles 面板现在会在以下情况下划掉CSS属性和值:
现在,[animation](https://developer.mozilla.org/docs/Web/CSS/animation)简写 CSS 属性中包含了指向对应 @keyframes 规则的链接,这样可以更快地在 Styles 面板中导航。
从之前的版本(112)开始,可以配置开发者工具控制台在按下回车键时应用自动完成建议。
默认情况下,要接受自动完成建议,可以按Tab键或右箭头。为了也能够使用回车键进行自动完成,需要启用设置Settings > Console > Accept autocomplete suggestion on Enter.
此外,另一个设置的文本现在更加用户友好:Treat code evaluation as user action.
命令菜单中的快速打开对话框现在会将列入忽略列表的第三方文件变灰,以更加强调编写的文件。
Recorder引入了一个新的导出选项:Puppeteer(包括 Lighthouse 分析)。使用Puppeteer,您可以自动化和控制 Chrome。借助 Lighthouse 可以捕获并提高网站的性能。
打开录制,在点击下载按钮。选择 Export 选项,然后保存为 .js 文件。
运行Puppeteer脚本,以获得一个Lighthouse报告,并保存在flow.report.html文件中。
现在,Elements > Styles 面板在鼠标悬停在属性上时会显示一个简短的描述。
工具提示中还有一个“ Learn more”链接,该链接会转到该属性的MDN CSS参考文档。
如果对CSS非常了解,可能会觉得这个提示很烦人。可以勾选 Don't show 来关闭所有工具提示。
要重新打开它们,就需要进行如下设置:Settings > Preferences > Elements > Show CSS documentation tooltip。
Elements > Styles 面板现在支持CSS嵌套语法,并将嵌套样式应用于相应的元素。
进一步改进增强的断点用户体验,控制台现在标记由断点触发的消息:
现在,控制台会给出适当的源文件中断点的锚链接,而不再是Chrome创建的用于在V8上运行任何JavaScript片段的VM<number>脚本。
单击断点消息旁边的链接可直接跳转到断点编辑器。
为了帮助开发者专注于代码的关键部分,现在可以直接从Sources > Page面板上的文件树中将不相关的脚本添加到"忽略列表"中。
右键单击任何脚本或文件夹,然后选择与忽略相关的选项之一。可能会看到将脚本或文件夹添加到列表中或从列表中移除的选项。调试器会忽略添加到列表中的脚本,并在调用堆栈中省略它们。
所有添加到忽略列表的脚本和文件夹在文件树中都会显示为灰色。
如果选择了一个被忽略的脚本,点击Configure按钮会转到 Settings > Ignore List。
在Web上,将引入新的CSS颜色类型和色彩空间,DevTools 也引入了新工具来帮助开发人员创建、转换和调试高清色彩。Styles面板现在支持CSS颜色级别4规范中提到的12种新色彩空间和7种新色域。
以下是使用color()、lch()、oklab()和color-mix()的CSS颜色定义例子。
使用 color-mix() 函数时,可以在Computed边栏中查看最终颜色输出。
颜色选择器支持所有新的颜色空间,并有更多的功能。例如,点击 color(display-p3 1 0 1) 的颜色色块。还增加了一条色域边界线,区分了 sRGB 和 display-p3 色域,以便更清楚地了解你所选颜色的色域。
DevTools 支持在不同的颜色格式之间进行转换。可以使用"更改颜色格式"图标来访问转换弹窗,或者在Styles面板中按住Shift键并点击颜色进行转换。
在进行转换时,了解是否对颜色进行了裁剪以适应空间尺寸非常重要。DevTools会在转换后的颜色旁边放置一个警告图标,提醒该颜色是否被裁剪。
此外,还可以使用新的快捷键从屏幕上拾取颜色。按下"c"键激活吸管工具,按下Escape键取消激活。吸管工具仅在sRGB色彩空间中采样颜色。例如,如果尝试采样超出sRGB色彩空间的color(display-p3 1 0 1)颜色,吸管工具将会将该颜色裁剪为sRGB空间中最接近的颜色,即洋红色(color(display-p3 0.92 0.2 0.97))。
最后,颜色格式设置现已被弃用,为新的高清色彩格式腾出空间。
重新设计的断点边栏允许快速访问常用功能,特别是停用、编辑和删除断点。
以下是一些亮点:
使用快捷键可以更快地记录和重放用户流程。Recorder 引入了几个方便的快捷键,可加快用户流程的录制和重放速度。忘记快捷键了?没问题,随时点击"?"按钮查看所有快捷键。
也可以通过Settings菜单自定义这些快捷方式。
如果正在使用其他面板中,并且想要开始录制用户流程,可以使用DevTools中的命令菜单中的"Create a new recording"命令来开始录制。
现在可以在 Application 面板的 Cache 部分找到 Cache Store ,而 Back/forward cache已移至Background Services部分。
*请认真填写需求信息,我们会在24小时内与您取得联系。