印度卫生部官方网站公布的最新数据显示,截至 4月22日24时,印度单日新冠肺炎确诊病例达461,477例。印度新冠肺炎累计确诊数16,263,695累计死亡病例186,928例。
据路透社报道,印度古吉拉特邦火葬场内的煤气炉和柴火炉已经连续工作了很长一段时间,在新冠疫情期间还从来没有停下过,设备上的金属零件甚至都已经开始熔化。不仅如此,印度多个城市的火葬场都出现了遗体积压的情况,连火化场地和使用的木柴都出现短缺。
一直梦想赶超中国的印度,面临这样的崩溃局面,到底会如何反应?
01为什么疫情爆发如此厉害?
4月14日是印度教的庆典“大壶节”,是世界上参加人数最多的节日之一。2021年4月14日,共有1.5亿印度人参加大壶节活动,约有65万印度教徒在恒河内共浴。
大壶节是印度最重要的节日,可以相当于我国的春节。不同的是,疫情影响下的春节,在党和政府领导下,全国上下人民齐心协力共同抗击疫情。
而邻国印度的大壶节仍轰轰烈烈举行,官员甚至喊出口号:圣洁的恒河会冲走新冠病毒!这对于我国人民来说,简直是不可想象!
02印度面临多重困境
印度由于历史问题累积,导致了公共卫生体系建设不完善、医疗条件落后、广大人民受教育水平低。而这些问题在疫情中无疑是协同放大,将印度的疫情防控推向更糟糕的境地。
在疫情之中我国的神器是:有效隔离、细心护理和中药防治。而印度大概就是:恒河水、牛粪和牛尿。
据报道,印度安得拉邦的村子里,数千人无视社交距离进行“泼粪大战”以庆祝节日,当地村民们会互掷牛粪以祈求健康。
印度人民受教育程度普遍较低也严重影响了疫情的控制。《纽约时报》指出,许多印度居民担心疫苗存在副作用,甚至质疑疫苗是政府的阴谋。按目前的接种速度,印度需要大约十年的时间才可让全国70%的人口接种疫苗。
03印度局势或将剧变
在疫情影响下,印度经济也遭遇重大打击:国内通货膨胀严重,难以利用宏观调控继续刺激经济;其次,严重的疫情状况也使得印度国内的外资纷纷撤出,这同时也导致了印度每天都有数万人失业。
更不用说印度对周边国家不断地挑衅和军事冲突,危机时刻一触即发。
疫情的控制不力对印度来说,无疑是一场人道主义灾难。也许,印度得先思考如何解决眼前的民生问题,才能准备“超越中国”。
文章来源:腾讯网
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
最近几年,如果你是一名前端开发者,如果你没有使用甚至听说过 babel,可能会被当做穿越者吧?
说到 babel,一连串名词会蹦出来:
这些都是 babel 吗?他们分别是做什么的?有区别吗?
简单来说把 JavaScript 中 es2015/2016/2017/2046 的新语法转化为 es5,让低端运行环境(如浏览器和 node )能够认识并执行。本文以 babel 6.x 为基准进行讨论。最近 babel 出了 7.x,放在最后聊。
严格来说,babel 也可以转化为更低的规范。但以目前情况来说,es5 规范已经足以覆盖绝大部分浏览器,因此常规来说转到 es5 是一个安全且流行的做法。
如果你对 es5/es2015 等等也不了解的话,那你可能真的需要先补补课了。
总共存在三种方式:
其中后面两种比较常见。第二种多见于 package.json 中的 scripts
段落中的某条命令;第三种就直接集成到构建工具中。
这三种方式只有入口不同而已,调用的 babel 内核,处理方式都是一样的,所以我们先不纠结入口的问题。
babel 总共分为三个阶段:解析,转换,生成。
babel 本身不具有任何转化功能,它把转化的功能都分解到一个个 plugin 里面。因此当我们不配置任何插件时,经过 babel 的代码和输入是相同的。
插件总共分为两种:
举个简单的例子,当我们定义或者调用方法时,最后一个参数之后是不允许增加逗号的,如 callFoo(param1, param2,)
就是非法的。如果源码是这种写法,经过 babel 之后就会提示语法错误。
但最近的 JS 提案中已经允许了这种新的写法(让代码 diff 更加清晰)。为了避免 babel 报错,就需要增加语法插件 babel-plugin-syntax-trailing-function-commas
比起语法插件,转译插件其实更好理解,比如箭头函数 (a) => a
就会转化为 function (a) {return a}
。完成这个工作的插件叫做 babel-plugin-transform-es2015-arrow-functions
。
同一类语法可能同时存在语法插件版本和转译插件版本。如果我们使用了转译插件,就不用再使用语法插件了。
既然插件是 babel 的根本,那如何使用呢?总共分为 2 个步骤:
babel
里面,格式相同)
npm install babel-plugin-xxx
进行安装
具体书写格式就不详述了。
比如 es2015 是一套规范,包含大概十几二十个转译插件。如果每次要开发者一个个添加并安装,配置文件很长不说,npm install
的时间也会很长,更不谈我们可能还要同时使用其他规范呢。
为了解决这个问题,babel 还提供了一组插件的集合。因为常用,所以不必重复定义 & 安装。(单点和套餐的差别,套餐省下了巨多的时间和配置的精力)
preset 分为以下几种:
例如 syntax-dynamic-import
就是 stage-2 的内容,transform-object-rest-spread
就是 stage-3 的内容。
此外,低一级的 stage 会包含所有高级 stage 的内容,例如 stage-1 会包含 stage-2, stage-3 的所有内容。
stage-4 在下一年更新会直接放到 env 中,所以没有单独的 stage-4 可供使用。
arrow-functions
,es2017 包含 syntax-trailing-function-commas
。但因为 env 的出现,使得 es2016 和 es2017 都已经废弃。所以我们经常可以看到 es2015 被单独列出来,但极少看到其他两个。很简单的几条原则:
preset 的逆向顺序主要是为了保证向后兼容,因为大多数用户的编写顺序是 ['es2015', 'stage-0']
。这样必须先执行 stage-0
才能确保 babel 不报错。因此我们编排 preset 的时候,也要注意顺序,其实只要按照规范的时间顺序列出即可。
简略情况下,插件和 preset 只要列出字符串格式的名字即可。但如果某个 preset 或者插件需要一些配置项(或者说参数),就需要把自己先变成数组。第一个元素依然是字符串,表示自己的名字;第二个元素是一个对象,即配置对象。
最需要配置的当属 env,如下:
"presets": [ // 带了配置项,自己变成数组 [ // 第一个元素依然是名字 "env", // 第二个元素是对象,列出配置项 { "module": false } ], // 不带配置项,直接列出名字 "stage-2" ]
因为 env 最为常用也最重要,所以我们有必要重点关注。
env 的核心目的是通过配置得知目标环境的特点,然后只做必要的转换。例如目标浏览器支持 es2015,那么 es2015 这个 preset 其实是不需要的,于是代码就可以小一点(一般转化后的代码总是更长),构建时间也可以缩短一些。
如果不写任何配置项,env 等价于 latest,也等价于 es2015 + es2016 + es2017 三个相加(不包含 stage-x 中的插件)。env 包含的插件列表维护在这里
下面列出几种比较常用的配置方法:
{ "presets": [ ["env", { "targets": { "browsers": ["last 2 versions", "safari >= 7"] } }] ] }
如上配置将考虑所有浏览器的最新2个版本(safari大于等于7.0的版本)的特性,将必要的代码进行转换。而这些版本已有的功能就不进行转化了。这里的语法可以参考 browserslist
{ "presets": [ ["env", { "targets": { "node": "6.10" } }] ] }
如上配置将目标设置为 nodejs,并且支持 6.10 及以上的版本。也可以使用 node: 'current'
来支持最新稳定版本。例如箭头函数在 nodejs 6 及以上将不被转化,但如果是 nodejs 0.12 就会被转化了。
另外一个有用的配置项是 modules
。它的取值可以是 amd
, umd
, systemjs
, commonjs
和 false
。这可以让 babel 以特定的模块化格式来输出代码。如果选择 false
就不进行模块化处理。
以上讨论了 babel 的核心处理机制和配置方法等,不论任何入口调用 babel 都走这一套。但文章开头提的那一堆 babel-*
还是让人一头雾水。实际上这些 babel-*
大多是不同的入口(方式)来使用 babel,下面来简单介绍一下。
顾名思义,cli 就是命令行工具。安装了 babel-cli
就能够在命令行中使用 babel
命令来编译文件。
在开发 npm package 时经常会使用如下模式:
babel-cli
安装为 devDependencies
scripts
(比如 prepublish
),使用 babel
命令编译文件
npm publish
这样既可以使用较新规范的 JS 语法编写源码,同时又能支持旧版环境。因为项目可能不太大,用不到构建工具 (webpack 或者 rollup),于是在发布之前用 babel-cli
进行处理。
babel-node
是 babel-cli
的一部分,它不需要单独安装。
它的作用是在 node 环境中,直接运行 es2015 的代码,而不需要额外进行转码。例如我们有一个 js 文件以 es2015 的语法进行编写(如使用了箭头函数)。我们可以直接使用 babel-node es2015.js
进行执行,而不用再进行转码了。
可以说:babel-node
= babel-polyfill
+ babel-register
。那这两位又是谁呢?
babel-register 模块改写 require
命令,为它加上一个钩子。此后,每当使用 require
加载 .js
、.jsx
、.es
和 .es6
后缀名的文件,就会先用 babel 进行转码。
使用时,必须首先加载 require('babel-register')
。
需要注意的是,babel-register 只会对 require
命令加载的文件转码,而 不会对当前文件转码。
另外,由于它是实时转码,所以 只适合在开发环境使用。
babel 默认只转换 js 语法,而不转换新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign
)都不会转码。
举例来说,es2015 在 Array 对象上新增了 Array.from
方法。babel 就不会转码这个方法。如果想让这个方法运行,必须使用 babel-polyfill
。(内部集成了 core-js
和 regenerator
)
使用时,在所有代码运行之前增加 require('babel-polyfill')
。或者更常规的操作是在 webpack.config.js
中将 babel-polyfill
作为第一个 entry。因此必须把 babel-polyfill
作为 dependencies
而不是 devDependencies
babel-polyfill
主要有两个缺点:
babel-polyfill
会导致打出来的包非常大,因为 babel-polyfill
是一个整体,把所有方法都加到原型链上。比如我们只使用了 Array.from
,但它把 Object.defineProperty
也给加上了,这就是一种浪费了。这个问题可以通过单独使用 core-js
的某个类库来解决,core-js
都是分开的。babel-polyfill
会污染全局变量,给很多类的原型链上都作了修改,如果我们开发的也是一个类库供其他开发者使用,这种情况就会变得非常不可控。
因此在实际使用中,如果我们无法忍受这两个缺点(尤其是第二个),通常我们会倾向于使用 babel-plugin-transform-runtime
。
但如果代码中包含高版本 js 中类型的实例方法 (例如 [1,2,3].includes(1)
),这还是要使用 polyfill。
我们时常在项目中看到 .babelrc 中使用 babel-plugin-transform-runtime
,而 package.json
中的 dependencies
(注意不是 devDependencies
) 又包含了 babel-runtime
,那这两个是不是成套使用的呢?他们又起什么作用呢?
先说 babel-plugin-transform-runtime
。
babel 会转换 js 语法,之前已经提过了。以 async/await
举例,如果不使用这个 plugin (即默认情况),转换后的代码大概是:
// babel 添加一个方法,把 async 转化为 generator function _asyncToGenerator(fn) { return function () {....}} // 很长很长一段 // 具体使用处 var _ref = _asyncToGenerator(function* (arg1, arg2) { yield (0, something)(arg1, arg2); });
不用过于纠结具体的语法,只需看到,这个 _asyncToGenerator
在当前文件被定义,然后被使用了,以替换源代码的 await
。但每个被转化的文件都会插入一段 _asyncToGenerator
这就导致重复和浪费了。
在使用了 babel-plugin-transform-runtime
了之后,转化后的代码会变成
// 从直接定义改为引用,这样就不会重复定义了。 var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); // 具体使用处是一样的 var _ref = _asyncToGenerator3(function* (arg1, arg2) { yield (0, something)(arg1, arg2); });
从定义方法改成引用,那重复定义就变成了重复引用,就不存在代码重复的问题了。
但在这里,我们也发现 babel-runtime
出场了,它就是这些方法的集合处,也因此,在使用 babel-plugin-transform-runtime
的时候必须把 babel-runtime
当做依赖。
再说 babel-runtime
,它内部集成了
core-js
: 转换一些内置类 (Promise
, Symbols
等等) 和静态方法 (Array.from
等)。绝大部分转换是这里做的。自动引入。regenerator
: 作为 core-js
的拾遗补漏,主要是 generator/yield
和 async/await
两组的支持。当代码中有使用 generators/async
时自动引入。asyncToGenerator
就是其中之一,其他还有如 jsx
, classCallCheck
等等,可以查看 babel-helpers。在代码中有内置的 helpers 使用时(如上面的第一段代码)移除定义,并插入引用(于是就变成了第二段代码)。
babel-plugin-transform-runtime
不支持 实例方法 (例如 [1,2,3].includes(1)
)
此外补充一点,把 helpers 抽离并统一起来,避免重复代码的工作还有一个 plugin 也能做,叫做 babel-plugin-external-helpers
。但因为我们使用的 transform-runtime
已经包含了这个功能,因此不必重复使用。而且 babel 的作者们也已经开始讨论这两个插件过于类似,正在讨论在 babel 7 中把 external-helpers
删除,讨论在 issue#5699 中。
前面提过 babel 的三种使用方法,并且已经介绍过了 babel-cli
。但一些大型的项目都会有构建工具 (如 webpack 或 rollup) 来进行代码构建和压缩 (uglify)。理论上来说,我们也可以对压缩后的代码进行 babel 处理,但那会非常慢。因此如果在 uglify 之前就加入 babel 处理,岂不完美?
所以就有了 babel 插入到构建工具内部这样的需求。以(我还算熟悉的) webpack 为例,webpack 有 loader 的概念,因此就出现了 babel-loader
。
和 babel-cli
一样,babel-loader
也会读取 .babelrc 或者 package.json 中的 babel
段作为自己的配置,之后的内核处理也是相同。唯一比 babel-cli
复杂的是,它需要和 webpack 交互,因此需要在 webpack 这边进行配置。比较常见的如下:
module: { rules: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel-loader' } ] }
如果想在这里传入 babel 的配置项,也可以把改成:
// loader: 'babel-loader' 改成如下: use: { loader: 'babel-loader', options: { // 配置项在这里 } }
这里的配置项优先级是最高的。但我认为放到单独的配置文件中更加清晰合理,可读性强一些。
最近 babel 发布了 7.0。因为上面部分都是针对 6.x 编写的,所以我们关注一下 7.0 带来的变化(核心机制方面没有变化,插件,preset,解析转译生成这些都没有变化)
我只挑选一些和开发者关系比较大的列在这里,省略的多数是针对某一个 plugin 的改动。完整的列表可以参考官网。
淘汰 es201x 的目的是把选择环境的工作交给 env 自动进行,而不需要开发者投入精力。凡是使用 es201x 的开发者,都应当使用 env 进行替换。但这里的淘汰 (原文 deprecated) 并不是删除,只是不推荐使用了,不好说 babel 8 就真的删了。
与之相比,stage-x 就没那么好运了,它们直接被删了。这是因为 babel 团队认为为这些 “不稳定的草案” 花费精力去更新 preset 相当浪费。stage-x 虽然删除了,但它包含的插件并没有删除(只是被更名了,可以看下面一节),我们依然可以显式地声明这些插件来获得等价的效果。完整列表
为了减少开发者替换配置文件的机械工作,babel 开发了一款 babel-upgrade
的工具,它会检测 babel 配置中的 stage-x 并且替换成对应的 plugins。除此之外它还有其他功能,我们一会儿再详细看。(总之目的就是让你更加平滑地迁移到 babel 7)
这是 babel 7 的一个重大变化,把所有 babel-*
重命名为 @babel/*
,例如:
babel-cli
变成了 @babel/cli
。
babel-preset-env
变成了 @babel/preset-env
。进一步,还可以省略 preset
而简写为 @babel/env
。
babel-plugin-transform-arrow-functions
变成了 @babel/plugin-transform-arrow-functions
。和 preset
一样,plugin
也可以省略,于是简写为 @babel/transform-arrow-functions
。
这个变化不单单应用于 package.json 的依赖中,包括 .babelrc 的配置 (plugins
, presets
) 也要这么写,为了保持一致。例如
{
"presets": [ - "env" + "@babel/preset-env" ]
}
顺带提一句,上面提过的 babel 解析语法的内核 babylon
现在重命名为 @babel/parser
,看起来是被收编了。
上文提过的 stage-x 被删除了,它包含的插件虽然保留,但也被重命名了。babel 团队希望更明显地区分已经位于规范中的插件 (如 es2015 的 babel-plugin-transform-arrow-functions
) 和仅仅位于草案中的插件 (如 stage-0 的 @babel/plugin-proposal-function-bind
)。方式就是在名字中增加 proposal
,所有包含在 stage-x 的转译插件都使用了这个前缀,语法插件不在其列。
最后,如果插件名称中包含了规范名称 (-es2015-
, -es3-
之类的),一律删除。例如 babel-plugin-transform-es2015-classes
变成了 @babel/plugin-transform-classes
。(这个插件我自己没有单独用过,惭愧)
babel 7.0 开始不再支持 nodejs 0.10, 0.12, 4, 5 这四个版本,相当于要求 nodejs >= 6 (当前 nodejs LTS 是 8,要求也不算太过分吧)。
这里的不再支持,指的是在这些低版本 node 环境中不能使用 babel 转译代码,但 babel 转译后的代码依然能在这些环境上运行,这点不要混淆。
在 babel 6 时,ignore
选项如果包含 *.foo.js
,实际上的含义 (转化为 glob) 是 ./**/*.foo.js
,也就是当前目录 包括子目录 的所有 foo.js
结尾的文件。这可能和开发者常规的认识有悖。
于是在 babel 7,相同的表达式 *.foo.js
只作用于当前目录,不作用于子目录。如果依然想作用于子目录的,就要按照 glob 的完整规范书写为 ./**/*.foo.js
才可以。only
也是相同。
这个规则变化只作用于通配符,不作用于路径。所以 node_modules
依然包含所有它的子目录,而不单单只有一层。(否则全世界开发者都要爆炸)
和 babel 6 不同,如果要使用 @babel/node
,就必须单独安装,并添加到依赖中。
在提到删除 stage-x 时候提过这个工具,它的目的是帮助用户自动化地从 babel 6 升级到 7。
这款升级工具的功能包括:(这里并不列出完整列表,只列出比较重要和常用的内容)
babel-*
替换为 @babel/*
@babel/*
依赖的版本更新为最新版 (例如 ^7.0.0
)
scripts
中有使用 babel-node
,自动添加 @babel/node
为开发依赖
babel
配置项,检查其中的 plugins
和 presets
,把短名 (env
) 替换为完整的名字 (@babel/preset-env
)plugins
和 presets
,把短名 (env
) 替换为完整的名字 (@babel/preset-env
)
preset-stage-x
,如有替换为对应的插件并添加到 plugins
使用方式如下:
# 不安装到本地而是直接运行命令,npm 的新功能 npx babel-upgrade --write # 或者常规方式 npm i babel-upgrade -g
babel-upgrade --write
babel-upgrade
工具本身也还在开发中,还列出了许多 TODO 没有完成,因此之后的功能可能会更加丰富,例如上面提过的 ignore
的通配符转化等等。
转自:知乎。作者:前端解忧杂货铺
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?在选择开发语言时,又该如何抉择呢?
本文将会深入对比这两种语言,讨论两种语言之间的关联和差异,并概述两种语言各自的优势。
JavaScript 是一种轻量级的解释性脚本语言,可嵌入到 HTML 页面中,在浏览器端执行,能够实现浏览器端丰富的交互功能,为用户带来流畅多样的用户体验。
JavaScript 是基于对象和事件驱动的,无需特定的语言环境,只需在支持的浏览器上就能运行。
JavaScript 语言具有以下特点:
JavaScript 是一种脚本编写语言,无需编译,只要嵌入 HTML 代码中,就能由浏览器逐行加载解释执行。
JavaScript 是一种基于对象的语言,可以创建对象同时使用现有对象。但是 Javascript 并不支持其它面向对象语言所具有的继承和重载功能。
JavaScript 的语法简单,使用的变量为弱类型。
JavaScript 语言较为安全,仅在浏览器端执行,不会访问本地硬盘数据。
JavaScript 语言具有动态性。JavaScript 是事件驱动的,只根据用户的操作做出相应的反应处理。
JavaScript 只依赖于浏览器,与操作系统的因素无关。因此 JavaScript 是一种跨平台的语言。
JavaScript 兼容性较好,能够与其他技术(如 XML,REST API 等)一起使用。
TypeScript
TypeScript 是 Microsoft 开发和维护的一种面向对象的编程语言。它是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以载入 JavaScript 代码运行,并扩展了 JavaScript 的语法。
TypeScript 具有以下特点:
TypeScript 是 Microsoft 推出的开源语言,使用 Apache 授权协议
TypeScript 增加了静态类型、类、模块、接口和类型注解
TypeScript 可用于开发大型的应用
TypeScript 易学易于理解
TypeScript 可以使用 JavaScript 中的所有代码和编码概念,TypeScript 是为了使 JavaScript 的开发变得更加容易而创建的。例如,TypeScript 使用类型和接口等概念来描述正在使用的数据,这使开发人员能够快速检测错误并调试应用程序
TypeScript 从核心语言方面和类概念的模塑方面对 JavaScript 对象模型进行扩展。
JavaScript 代码可以在无需任何修改的情况下与 TypeScript 一同工作,同时可以使用编译器将 TypeScript 代码转换为 JavaScript。
TypeScript 通过类型注解提供编译时的静态类型检查。
TypeScript 中的数据要求带有明确的类型,JavaScript不要求。
TypeScript 为函数提供了缺省参数值。
TypeScript 引入了 JavaScript 中没有的“类”概念。
TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块中。
下面列举 TypeScript 相比于 JavaScript 的显著优势:
静态类型化是一种功能,可以在开发人员编写脚本时检测错误。查找并修复错误是当今开发团队的迫切需求。有了这项功能,就会允许开发人员编写更健壮的代码并对其进行维护,以便使得代码质量更好、更清晰。
有时为了改进开发项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。使用TypeScript工具来进行重构更变的容易、快捷。
当发开大型项目时,会有许多开发人员,此时乱码和错误的机也会增加。类型安全是一种在编码期间检测错误的功能,而不是在编译项目时检测错误。这为开发团队创建了一个更高效的编码和调试过程。
干净的 ECMAScript 6 代码,自动完成和动态输入等因素有助于提高开发人员的工作效率。这些功能也有助于编译器创建优化的代码。
相比于 TypeScript,JavaScript 也有一些明显优势。
JavaScript 的开发者社区仍然是巨大而活跃的,在社区中可以很方便地找到大量成熟的开发项目和可用资源。
由于 JavaScript 语言发展的较早,也较为成熟,所以仍有一大批开发人员坚持使用他们熟悉的脚本语言 JavaScript,而不是学习 TypeScript。
TypeScript 代码需要被编译(输出 JavaScript 代码),这是 TypeScript 代码执行时的一个额外的步骤。
为了充分利用 TypeScript 特性,开发人员需要不断注释他们的代码,这可能会使项目效率降低。
有些开发人员更喜欢 JavaScript 的灵活性。
TypeScript 正在成为开发大型编码项目的有力工具。因为其面向对象编程语言的结构保持了代码的清洁、一致和简单的调试。因此在应对大型开发项目时,使用 TypeScript 更加合适。如果有一个相对较小的编码项目,似乎没有必要使用 TypeScript,只需使用灵活的 JavaScript 即可。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
下面是我提出一个VGLT-MO三层一环结构,帮助大家理解设计体系。
包围着这三层内容的一环是管理结构(Management Structure)与组织流程(Organization Process),它促进整个设计体系成为一个活的生态系统。
我曾参与过国内某知名企业的设计体系建设过程,遇到了很多困难,但也收获了更多的认知,了解到不能怎么做和应该如何做,进一步促成了本篇文章;因此我试着搭建出设计体系的通用结构,并且文章后面阐述其中的价值和如何去构建设计体系。
系统规则影响系统行为,稳定的设计体系结构促进产生稳定的设计体系,关于设计体系的原则我将其归结为以下4点原则:
1)形式上,通用却灵活
设计体系是独立存在于现有业务外的,用可预测的规则进行构建和管理,指导方向一致性,而非每个人独自开脑洞。
但是规则并不是限制,当指导不足以传达更佳的用户体验时就通过体系机制的设计,即时迭代设计体系。
设计师可以更快地完成原型和迭代工作,因而更加灵活地去思考满足需求的解决方案。
2)关系上,整合但互通
整合设计与开发,链接设计与实现的代码,有效地将体验的设计与落地的开发相结合;但又通过独立化的模块设计以及模块间关系的设计,搭配良好的机制和协同工具帮助使用者更流畅地使用。
3)组织上,开放共享且跨域同步
通过组织流程的设计让基于模块化设计思维的组件、设计模式、内容策略等等能被尽可能多的人重复利用,提高知识复用率;并让关于用户的知识在组织中的设计师、工程师、产品经理、市场营销人员等人中保持同步和流通。
4)成果上,协同而一致
通过良好的开发体验,用设计开发的规范化指导,让大范围的开发与设计都能良好地匹配用户心智模型和多设备多平台需求,带来优质且统一的产品价值传达和用户体验实现。
除了创建更高的可用性(Usability)之外,也能建立更高的可访问性(Accessibility),让体验在如障碍群体、各类配置低下的设备、有法律与文化的国际差异等在产品多次迭代中也能更易达成一致(这些往往是较少被考虑到的内容)。
不同组织和产品的设计体系都会不一样。
设计体系有不同规模(Kholmatova,2017),简单来说可以分为平台级设计体系(如Apple的人机交互指南HIG, Microsoft的流畅设计体系FDS)和公司级设计体系(如Atlassian的Atlassian设计体系ADS;Salesforce的闪电设计体系LDS,Adobe的Spectrum),如蚂蚁金服的Ant Design等)。
设计体系的开放程度不一,而且有些设计体系并不对外开放(如Airbnb的设计语言系统DLS),而微软的流畅设计体系则是全程开放。
我们可以从实践规则(严格/松散)、构造方式(模块化/整合化)和管理机制(集中式/分布式)(Kholmatova,2017)。
任何组织都能在其中找到合适的定位,有些设计体系极为严格,而有些反而得益于其松散性与灵活性;如Airbnb的设计体系整体上更为严格,拥有详实的设计规范文档、设计与开发有精准的同步流程、拥有严格的新模式入库流程,详实全面的设计文档等;通过内网进行使用,并开发一系列的插件工具促进设计与开发流程。
而TED只有两名 UX 设计师和四名前端工程师专职负责设计体系相关工作,因此就更稍显松散;不同的程度都是和自身组织的团队文化和产品特征有关的,他们更加关注有效地实现产品设计目标。
“我们鼓励以正确的方式进行设计,而非一味强调一致性原则;页面的性能表现对于我们来说更为重要,如果它无法有效地承载内容,我们会将其修改到能够承载为止;一致性与模式化的信条对于我们来说无法成为驱动设计决策的关键要素。”——Michael McWatters,TED UX 架构师
是标准化还是松散化,更多依靠组织文化下的选择。它们各有利弊。一个紧凑严格,利于精准,但有时较为死板,会限制设计师进行创造发挥;一个灵活适应,利于拓展和快速变更,但难以控制,它们都需要找到解决自身缺陷的方法。
关于模块化还是整合化,我们可以根据各自适应的产品特征进行抉择。
例如模块化方式适用于:
典型的例子包括电商产品、新闻类产品、在线教育平台、金融平台、政府信息平台等等。
而整合化方式则适用于:
典型的例子包括创意展示类页面、一次性的运营活动页面、作品集等等。
当然有许多不同的特质让每个设计体系各不相同,关键的是,我们如何找到适合的定位;而关于管理方式上的划分,我将在第4章-如何构建设计体系中进行更多详细的论述。
知道设计体系是什么,更需要了解设计体系不是什么。
关于设计体系有一些误区,例如:
设计体系是设计规范(Design Guidelines)吗?
许多人都会将设计规范与设计体系相提并论。但实际上,他们并不是一个层级的东西,或者更准确的说是设计体系包含了设计规范。
设计体系是模式库(Pattern Library)或组件库(Component Library)吗?
模式库的建立在设计体系内,而模式库是记录和共享设计模式的工具,只是设计体系的工具化和显现化的部分;像Bootstrap这样的工具包不被认为是设计体系,因为它们缺少一些定义设计系统的重要元素:模式库、风格指南和设计语言。
设计体系是否会扼杀组织内的创造力?
不好的设计体系当然会,但好的设计体系往往会通过机制和流程,促进实际的创造力,因为来自终端的良好的解决方案可以更快被整个组织所采用,而不必担心那些即将沦为沉没成本的过往设计与技术资产的限制。
设计体系是一劳永逸的吗?
设计体系是动态的,永远是随着组织需求和用户需求而变化的,一切说自己已经完成了设计体系的建设的人都是将静态的设计规范曲解成了设计体系。
文章来源:人人都是产品经理 作者:龙哩个龙
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
编辑导语:设计在产品中日常可见,但设计体系从何而来?很多时候,我们可以基于一套架构严谨、规则统一的体系框架,对产品表现层面的设计工作可以逐渐实现模块化运作;本文作者分享了关于设计体系的整体详细介绍,我们一起来了解一下。
——WHY 为什么?
设计体系从何而来,为何出现?设计体系如何发展到现在的样子?
——WHAT 是什么?
设计体系是什么?不是什么?关于设计体系有哪些误区?与设计规范、组件库、模式库的区别是什么?有哪些现存的设计体系?
——HOW 如何做?
如何搭建自己公司的设计体系?
——FUTURE 设计体系的未来如何?
这篇文章有大量我的个人理解,因此难免出错或是不准确的地方。
国内设计和前端界对Design System主要存在两种叫法,设计系统和设计体系。
看看百度词条对两个词汇的解释:
系统,来源于古代希腊文(systεmα),英文为system,日文音译,后引为中文,即形容若干部分相互联系、相互作用,形成的具有某些功能的整体。
体系,英文为structure,泛指一定范围内或同类的事物按照一定的秩序和内部联系组合而成的整体,是不同系统组成的系统。
要了解Design System,首先就得了解到它一定不是一堆UI组件,不只是设计师的事;如果称Design System称为“设计系统”,则是把它当成“产品”存在了,过于静态,失去了人之间的联系,但恰恰是人之间的联系才能促成优秀设计体系的生成。
因此尽管原英文单词不同,但依据实际表达的意思,本文偏向于认同“设计体系”的名称,相信你读完之后也会认同这样的叫法。
目前来说,设计体系尚未出现清晰的定义,我们可以看一些设计体系的专家的定义:
“由明确的标准指导的可重用组件的集合,这些组件可以组装在一起以构建任意数量的应用程序。”——Will Fanguy(2017,inVision设计体系专家)
“一组相互关联的模式和实例的共享,通过将一致地组织它们以服务产品目标。模式(Pattern)是我们用来创建界面的重复元素:如用户流、交互、按钮、文本字段、图标、颜色、排版、微复制等;实例(Practices)是我们在团队工作中如何选择创建、获取、共享和使用这些模式。”—— Alla Kholmatova(2017,著有设计体系:数字化产品设计的系统化方法)
“由个人、团队或社区记录和发布的视觉风格、组件和其他的库,以作为代码和设计工具,以便采用产品可以更加高效和有凝聚力。”——Nathan Curtis(2017,设计体系咨询专家,帮助多个企业搭建设计体系)
在本文综合的理解下,我试着为设计体系下了更加清晰的定义:
设计体系(Design System,也可以叫设计系统)是可重用组件的集合,由清晰的标准引导,通过机制化的组织流程和具象的指南与工具加以整合,以帮助开发者(设计、工程等)高效且一致地创建大量的应用,并且动态地确保用户体验的一致性。
如果你之前不太了解设计体系,可能现在有点懵,没关系,相信读完我这篇文章,你一定就能了解。
试想一下,现在你现在是UX设计师A1,我们现在因为某项用户需求或业务需求需要处理。
尽管A1设计师和B1工程师的自己的习惯可能类似,但由于参与人数的增多和任务量的增多,每个人都有自己的见解与习惯;考虑这一个按钮中的每一种元素,回忆一下数学中的排列组合问题,最后将发现同一个问题的解决方案的组合情况将会产生成百上千甚至万种可能,而这里很多都是重复工作。
怎么办?我们需要定义明确清晰的规则,让不同的人都能为统一问题达成相对一致的解决方案处理,即达成设计工程化。
设计体系便是一种解决办法。但尽管是叫“设计体系”而不是叫“开发体系”,但这并不意味着这只是设计的事情;因此接下来,我将谈谈设计体系是如何诞生的。
上面的故事已经从侧面体现出,当业务与用户的需求迫使组织面对一系列的问题,迫使企业需要探索合适的解决方法。
总的来说,设计体系的出现便是用来应对组织在敏捷、协作和债务处理等方面的需求。
——敏捷响应需求:在多设备、多平台的现在,组织不可能选择每隔几年再更新一个全新的数字产品,因为这意味着在交互上用户需要重新学习,在战略上这种方式的不确定性因素过大,如果失败就意味资源的大量浪费。
就特性而言,数字产品不同于实体产品,往往需要尽快上市,最小成本检验,尽快迭代,以获取更强的竞争力,而且以往写的代码也不会被磨损,需要定期进行维护;因此这些便对组织满足用户体验的速度做出了要求,因此更多的组织逐渐采用如等以敏捷(Agile)和精益(Lean)思维为基础的敏捷开发(Scrum)、设计冲刺(Design Sprint)等方法。
——复杂的协作鸿沟:对用户来说,只需要点击升级便可获得最新的体验,但这意味着这种体验的即时在线化将体验迭代的简单交给了用户,而复杂就留给了组织;UX设计师、前端工程师、产品经理、内容策略师们、可访问性专家等等组成的组织结构和工作流程都需要得到适应性的改变,才能提供快速迭代的流程去完成版本管理、设计管理、债务管理等工作?
Alex Schleifer(Airbnb设计副总监)也提到这样的情况:虽然工具的提升帮助编码的速率和设计的效率都在提升,但最终使设计生效的是多方面的协作的结果,然而原有方式越来越多暴露出在跨学科沟通上的问题,这些依然阻碍着产品创新以实现更佳用户体验的效率。
——债务大量累积: 这里的债务不是指经济上的债务,在设计上,由于设计人员的个体差别和缺乏系统性机制促进设计经验沟通,设计往往在长期的开发过程中提供了许多定制化的解决方案;在UI上可以体现为不同样式的按钮或颜色等、UX上可以体现为同一软件上的交互逻辑混乱等,这造成了设计债务(Design Dept)。
而技术债务(Technical Dept)亦是如此,为同一个问题,不同的工程师使用不同的代码或是令牌标记,加大了代码设计与维护、拓展的难度;同时,我认为其中还存在一个债务,我将其称之为产品债务(Product Dept),不同类别的产品经理等负责产品定义等职能的人员为同一产品或业务功能提供了不同,但效果相似的产品解决办法。
而且无论你是互联网公司,亦或是传统产品公司,越是庞大的体系,人员就越细分,在整体设计上的知识就越分裂,就越有可能出现同一问题多个定制化解决方案的情况,这会让出现在工程、产品、设计上的债务就越庞大。
这些设计、技术、产品债务让管理、维护都异常艰难;而且只要审视一下我们日常工作的周遭,就会发现债务其实无处不在;那些杂乱的视觉形象应用、那些不统一的工业产品材料与色彩、那些无准则的交互行为、那些不一致的反馈声音、同一数字产品不同的功能模块定义等等……
时至今日,设备和用户的多样性都在激增,以往的标准、工作流程和基础设施都难以支撑;我们用设计和开发应对的问题越来越多,变化也越来越多,但我们一直在定制化和通用化之间无序游离。
可以在一些软件中看到同样的一个功能按钮出现十几种形式,而它们要解决的问题却几乎一样;也可以看到那些拙劣的设计规范中,万物归为一种单调样式,降低了开发成本,却带来用户认知的困难。它们都难以维护,极大地阻碍了组织创造体验、达成商业可持续和创新的效率。
面对着这些问题,公司只能存在几种选择(Suarez等人,inVison):
大部分组织为了满足快速发展的需要,往往更多采用A和B的方式(例如各种各样的业务扩充,产生了大量对工程和设计人员的需求,如阿里、网易、字节、美团等)。
但提升人员,仍然不能解决定制化方案的拓展问题,仍然存在大量不可复用的方案,造成效率的浪费;好比毒素累积,治标不治本,当达到足够的毒素累积之后,创新将寸步难行。
如果不首先创新构建方式,就无法创新产品,这是非常简单的真理。——Alex Schleifer(Airbnb设计副总监)
虽然组织内也一直在提升效率,但管理只能提升局部效率,工具才能带来系统的变革。
设计体系的提出并不只是为了解决用户体验的问题,而是适应组织内的开发需求。而通配式解决方案的方法则更具系统性、远期性。这便是设计体系的源头,模块化(Modularity)是一个关键词。
早在福特的时代,“流水线”思维就将生产流程模块化进而提升生产效率和生产一致性,形成大批量的工业化时代,形成了强势的美国汽车工业;二战之后,20世纪60年代,丰田作为日本汽车制造商的一分子运用精益生产的小批量生产方法,注重发掘工人的创造力,即时解决问题,响应需求,降低远期浪费。 (E Ries, 2012)
回到软件开发上来。20世纪60年代,越来越多组织发现软件发展的速度已经跟不上硬件的升级,软件开发越来越容易缓慢、难维护且容易出错。在开发上,预算超支、超时运行,在使用效果上效率和质量都很低下;在运维上,不符合要求、难以维护管理代码,容易造成软件无法交付。
硬件与软件之间的差距以及解决这个问题而造成的困境,软件危机(Software Crisis)便出现了。
没人能对这些问题视而不见,开发者与设计师的先驱们开始探索解决方案。
1968年,第一届北约软件工程(NATO)会议上,道格拉斯·麦克罗伊(Douglas McIlroy)提出了基于组件(Component-based)的开发方法,通过复用代码来提高编程潜力的方法,减少编程的工作量,同时能帮助编程工作更高效、更易于扩展且灵活,提升软件开发速度;因此这被认为是有可能是解决“软件危机”的方法之一,这种方法可以算是早期的设计体系的基础雏形。(软件危机&INvision)——维基百科,关于软件危机的描述
而在设计界,也有先驱提出了类似方法。1977年,Alexander等人通过其书A Pattern Language,提出了模式语言(Pattern Language),期望用系统化的方法解决设计建筑、城镇和建设方式的问题,帮助形成一种实现为250多种不同类型建筑的持续性方式(Koivisto,2019);这种语言通过共享共同的模式,用共同设计的方式将更多人纳入设计过程。
如果每个模式都是解决共同的问题,那么当面向同样的问题时,用模式等方式快速应用以前的解决方法将可能是高效的工具;这里的模式(Pattern)便是用户界面设计中的循环解决方式,模式库是特定用户界面上重复设计元素的集合。
在网页开发时代,网页设计师用基础的网页架构就能搭载数以万计的页面。
21世纪初,YUI和jQuery UI等库的引入,为开发人员提供了一套小部件和模式的工具包,以创建更一致的网站用户界面(Forst, 2016)(例如Bootstrap是Twitter开发的基于网页解决方案的前端工具包,供设计师和开发人员使用)。
但这些方法也会些有优有劣,例如Mary Collin就曾对使用Bootstrap开发的网页进行综合对比,结果发现Bootstrap容易导致成果缺乏独特性,看起来外观非常一致;但在另一方面,在移动端响应性和拓展性方面效果很不错,因为足够稳定。
Mary Collin的一些网页对比
在现代,互联网兴起,尤其是移动互联网的兴起,降低了信息分发与复制的边际成本和提供了庞大的用户量;即时在线的网络为数字产品的测试和快速迭代提供了可能,良好的用户体验能为企业创造的价值将远超传统时代,体验的重要性迫使数字产品不得不用更快速的升级换代过程满足用户需求。——(俞军,2020)
但规范或库本身是静态的,依然具备过多的不确定性,并且缺乏对开发全链路的支持,尤其是未来的每一次的设计如何决策。
因此进一步,一些通用设计资产(Design Assets)被逐渐固定下来,并辅以使用的规则描述,设计模式(Design Patterns)逐步形成,为协作而生,通过为重复的共同问题快速生成解决方案,并尽可能在整个组织内保持一致以提升效率。因为类似的原因和目的,也同时产生了例如样式指南、设计语言、内容指南、甚至是品牌识别系统等等类似产物。
在软件开发问题上,设计规范和设计模式成为内部设计师们依靠复制粘贴进行传播的文档,亦或是前端工程们网上开源共享的模式库(Pattern libraries)或组件库。
与设计模式不同,模块化设计(Modular Design)引入了敏捷设计方法的思想;建立在以前的基础上,让解决方案的更快、更短的迭代,前端框架是提供特定解决方案和特定外观和感觉的工具”(Frost,2013)。
框架本质上是模块化的,它们专注于单个项目或设计问题(Frost,2013);对于多个设计问题,框架、模式库或模块化设计本身不足以系统地使用,这样的背景下,便迎来了设计体系的涌现。
2013年,Brad Forst提出了原子设计(Atomic Design)理论为设计体系的出现奠定了一波理论热度,提供了更加形象化的描述说明;这让更多人意识到这些问题的存在,并且提供了易于理解且广泛传播的理论基础和解决方案。
Brad Forst,原子设计(Atomic Design)理论
原子设计理论将交互元素似化学因子一般逐步拆分。
这是一种逐步拆分式的模块化方法。
他建议用模式库(Pattern Library,也被称为用户界面库、组件库、资产库等)集合构成用户界面的可重用组件,并通过指南(Guideline)指导如何创建,以进一步综合了风格指南、流程指南、设计语言等等设计指南;包括他之内的几位设计体系先驱都提出要进一步整合领域内语言,开始更多地使用设计体系(Design System)这样的语言来代表类似的事物。
理论如此,实践永远不会落下。互联网的广泛普及带来用户需求量爆炸,对公司来说,越来越多的业务量压力和一致的体验需求的迫使下,越来越多的企业推出了自家的设计体系。
2014年伊始,Google推出了质感设计体系(Material Design System),类似的时间前后Atlassian搭建了Atlassian设计体系和Airbnb也在内部搭建设计体系(即后来的设计语言体系,DLS,Design Language System);在此之后,一系列公司跟进开始研究和开放自己的设计体系。
例如Apple的人机界面指南(HIG),Microsoft的流畅设计体系(Fluent Design System)、IBM的碳设计体系(Carbon Design System),Salesforce的Lightning设计体系、Shopify的Polaris设计体系,甚至一些英国、美国、澳大利亚等公共部门也推出了自己的设计体系,如英国政府的GOV.UK设计体系。
而在国内,搭建的比较完善的有知名的蚂蚁金服Ant Design设计体系,还有Element,以及View UI等中台设计体系,以及许多存在于部门内部、仍然只是设计规范、或者设计体系不完全体的内容。
——插个题外话,微软的流畅设计体系(Fluent Design System)是我这篇文章最开始的起点,从简单论述微软如何统一用户体验聚焦到流畅设计体系。
当然关于Fluent Design System的更多内容,我会在本系列文章之后,单独出篇文章描述我的发现【稿子都差不多了,写着写着就写成了设计体系系列文章哈哈】。
我们现在知道设计体系是为了什么了,但在现在的阶段,问题不是能搭建什么,而是如何能更好地搭建。
“体验工程的建设已经远远不止于一套设计规范或一套组件库,他需要一套完整的系统来支撑,解决内部协作的一致性问题,解决设计系统更新的周期性问题,解决一群设计师与工程师如何规模化的生产各种业务 UI 的问题,从而最终解决用户体验一致性的问题“——Alibaba Fusion Design
文章来源:人人都是产品经理 作者:龙哩个龙
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
借着疫情期间在家休假的时间,将平时用到的一些零零散散的图标绘制方法与思路进行了一次全面的汇总与沉淀。从实习期间画一组图标的无从下手,每一个图标看起来都像是散装的一样,到后来慢慢学习与练习,到现在变得了解了图标的绘制流程,过程也是比较麻烦,因为很少有全面的图标讲解文章,都是看一篇懂一点,然后在揉到练习当中。所以本篇文章尽量将图标进行细致一些的流程说明,有不足之处还望指教。
图标可用性,顾名思义就是图标绘制出来是否能被用户所看懂并快速识别,是否可以为业务赋能。为此我总结出了四条图标绘制的评判标准。
用户是否能在某页面上迅速找到该图标,凸显性的目的是可以快速查找,帮助用户做选择。图标在识别的速度上远远大于文字,所以在一些页面中的重要功能使用图标的目的是为了吸引用户的注意力,让重要功能得到凸显,提高重要功能的点击率。
图标的目的是要让用户猜出他看到的图标所表达的意义,有什么作用,以及点击后会出现什么样的场景,发生什么样的事情。所以一个图标的好与坏最重要的因素就体现在这里:图标的可识别性与可预知性。
影响图标可识别性的三点因素
3. 美观度
图标是否美观,对用户是否有足够的吸引力。在《设计通用法则》一书中有一条设计法则是:美即适用效应。不管任何事物,美丽的外表都会给人带来好感,让人觉得这种事物在任何方面都非常美好。作为设计师,把一件事物美观化是一件终生的必修课,用户对图标或者界面的第一印象就是始于颜值。
4. 业务属性
图标是否符合业务属性,是否可以唤起用户的使用情绪,提高点击率,起到为业务赋能的作用。在界面中,我们设计的图标最终目的不只是让用户觉得它美观,而是要为我们的产品赋能,什么是为产品赋能呢?通俗来说就是使图标能够提升点击率从而给公司创造收益。
图标如何为产品赋能呢?
1. 线性图标
线性图标,顾名思义,即图标是由直线、曲线、点在内等元素组合而成的图标样式。线性图标具有辨识度高,清晰唯美,简约易看等优点,线性图标不会对页面造成太多的视觉干扰。缺点是:线性图标的创作空间较少,太复杂的线性图标看起来会让人感觉到累。
2. 面性图标
面性图标,即使用对图形内容进行色彩填充的图标样式。面性图标是现实生活中物体的缩影,优点非常多,比如表意能力强,细节丰富,色彩丰富,情绪感强,视觉突出,创作空间大等。面性图标可以让用户迅速定位图标位置,快速预知点击后的状态。但是面性图标在页面中不可过多出现,否则会造成页面臃肿,难分主次,用户视觉疲劳。
3. 混合型图标
在设计图标类型的时候,不一定局限于单纯的线性与面性,也可以两者结合,让图标即有线性描边的轮廓,还有色彩填充的区域,混合型图标可以让页面变得更加有活力,同时还可以吸引用户的注意力,美观与创意性强。但是混合型图标在商业产品中要谨慎使用,因为使用不当会让页面变得杂乱不堪,用户无法识别图标表达的语义。
色彩情绪即颜色心理,指不同波长色彩的光信息作用于人的视觉器官,通过视觉神经传入大脑后,经过思维,与以往的记忆及经验产生联想,从而形成一系列的色彩心理反应。在任何场景下合理使用色彩心理可以调起用户情绪,还可以让用户产生联想进而快速识别。
在设计图标的时候,合理的运用色彩情绪,会使图标更具有科学性,可以让用户在使用的过程中更加自然、舒服,同时也会增加用户的识别速度唤起用户的使用情绪。
色彩情绪表
在配色时,我们采用更具备科学性、更符合人类感官的 HSB 系统进行配置。在根据主色配置渐变色时,我们经常是在主色的基础上加白或者加黑。但是只加入大量的白或者黑就会改变原本色彩的明度与饱和度,从而使画面显得雾蒙蒙的,不够清晰通透。正确的做法是在给主色变亮减暗的同时,改变主色的饱和度。在 hsb 色相条中,最亮的三个颜色分别是,蓝紫色,青绿色与黄色,如果需要加亮主色就在混白的同时将蓝色向青色改变色相,如果需要减暗则是相反,这样在调制渐变色变化的过程中不会出现太脏的颜色。
常见的色彩搭配
中性色(黑白)+主色、主色+点缀色、主色+透明度、单渐变、双渐变错层、撞色叠加穿透等效果。一般常用的就是中性色+主色、主色+点缀色。
点缀色配色
我们在绘制图标的时候,应该将图标的每个像素尽量对齐于像素点,这样导出图标时像素的边缘不会出现锯齿,不会出现过于模糊的情况。通常在绘制时我们应该去除绘制软件中 x 与 y 轴,宽(w)与高(h)的小数点,这样就可以避免无法对齐像素的情况。
在绘制两个或者以上的图标时,为了避免多个图标出现大小不一的情况,我们应该使用由谷歌材料设计语言提供的图标参考线进行绘制,使用图标盒子可以让一整套图标在视觉效果上更加统一和谐,不会出现一大一小一长一短的情况。
使用方法
先绘制一个 152*152px 的正方形,一个 176*176px 的正圆形,一个宽 176*128px 的水平矩形和一个 128*176px 的垂直矩形,圆角为 4px,然后将这个四个形状进行水平居中对齐,之后得出一个图标的参考线。
在宽度相等的情况下,正方形的面积要大于正圆的面积,所以在绘制圆形图标时应该将圆形的上下左右四个顶点顶齐与图标盒子正方形区域的四条边;在绘制方形图标时应该将方形的四个角点顶齐与圆形参考线的外围边;在绘制横向矩形与纵向矩形图标时,应该将图标的左右边或者是上下边控制在正方形的参考线之内,这样矩形图标绘制出来会更加的圆润,相对于其他的形状图标更加匹配。
我们绘制的图标必须要保证清晰度,可辨别性。不管是在强光下还是正常光下都需要良好的可读性。这就需要图标不论是自身元素之间的对比度还是和页面底板背景之间的对比度都需要很好的可读性。我们检测图标的可读性通常要将图标的背景色底板在黑色和白色之间进行切换对比,不论是黑色还是白色的背景都可以看清图标的全部细节,还需要确保图标中的每一种颜色都是可见的。第二就是将图标拿到强光下进行观察,在强光下是否可以看清图标的主题结构,图标是否有足够的辨识度。
在绘制图标时,我们可以参考 WCAG 2.1:图形和用户界面组件的对比度至少为 3 : 1 的标准进行相应配色,以达到良好的可视状态。
可访问性测试:https://webaim.org/resources/contrastchecker/
在绘制多个类型相同的图标时,我们需要注意这一套图标合集需要在视觉上保持统一性。在一整套产品中,会有很多种图标,但是图标的功能不一样,所表达的内容也不同。这时,图标一致性的意义就体现出来了,根据格式塔原理中的相似性原则:人们会将如元素彼此相似的东西感知为一组。这也意味着如果具有相同功能、含义和层次结构级别的元素,则应在视觉上保持统一匹配。我们倾向于将彼此相似的元素视为同一个分组,相似性可以帮助我们组织和分类页面里的元素对象,并将它们与特定的含义或功能相关联。有不同的方法可以使元素被认为是相似的,这些方法包括颜色、大小、形状、纹理、尺寸和方向的相似性。
图标内容的统一会让用户明白相似的图标所代表的的功能也相同,而且在视觉上也更加和谐美观。因此我们在绘标后还需检查线条的粗细比重,边角的大小,配色方案,细节层次和设计元素在整个合集中是否是不变且一致的。
呼吸感的意思就是适当留白。在设计中,适当的留白可以突出主体内容,让内容具备易看性。不管是图标还是界面,元素与元素之间都应该存在一定的间距。在图标的绘制过程中,我们应该注意图标元素之间的间距不宜过近,元素也不宜过多。图标是一个物体的简略缩影,目的是为了表达内容,让用户快速理解,但是在有限的空间中,太过复杂的细节会影响图标的识别速度。因此在图标的绘制过程中应该删除所有无法传达图标意义的元素,避免使图标变得太过复杂难以识别。
布尔运算在设计行业中被得到广泛的运用,比如工业设计,影视后期,logo 设计等,布尔运算具有一致性与规范性的优点。我们在设计面性图标的时候可以合理使用布尔运算进行绘制,这样绘制的图标具有吸引力和说服力。
在页面中,有需要吸引用户点击的图标,也有起到辅助作用的指示图标,还有引导用户操作的图标,这些图标在页面中占据着不同的地位.在所有图标中,有色图标强于无色图标,多色图标强于单色图标,面性图标强于线性图标,带背景图标强于无背景图标,在设计图标的时候应该根据业务需要进行视觉强弱不同的设计。
如文上所说,图标采用与业务相符合的色彩搭配会让用户在使用的过程中更加自然、舒服,同时也会增加用户的识别速度,唤起用户的使用情绪。一个图标的绘制是否具备商业价值也恰恰体现在这里。
如下图所示,左图是斗鱼直播 APP 的截图,右图是京东金融的图标截图。这两款产品的业务以及所对应的用户群体完全不一样,斗鱼是一款直播的产品,直播面向的用户群体是青少年,所以整体的产品调性是:萌、活泼、多彩、绚丽、时尚等,斗鱼直播的图标绘制需要面向年轻人,色彩的高饱和与有趣的元素来抓住用户的眼球。但是京东金融是一款理财的产品,面向的用户则是中老年,大多数都是有一些存款的人,这些人不需要斗鱼那样花里胡哨的元素,他们只在乎这个产品是否安全,利息是否高,所以京东金融这个产品的整体风格就需要偏向于:安全、高端、大气,这样才能给用户从视觉上营造信任感。我们设计图标时通常使用产品的调性作为主风格,但是像美团淘宝这些业务众多的产品中,我们就需要根据产品下的细分业务进行风格定位,然后设计中相应融入产品的品牌元素,使用合理的色彩情绪等让图标变得更符合业务的风格。
当我们的图标绘制完成后需要测试这一组图标的重心是否统一,常用的方法是使用标准的正圆形和正方形来和所有绘制的图标进行对比,保证所有的图标重心相近,视觉统一。也可以采用不同角度的观察法,可以从上下左右四个角度去观察图标,看看图标在不同的角度下重心是否统一。
情绪板是在执行一项设计操作之前非常重要的一个步骤,情绪板并不是像设计平台展示作品集里那样放几张图片,几个关键词,而是一套对接下来设计的一个风格走向定位。根据不同的用户人群,不同颜色的色彩情绪,不同产品的业务,将用户调研的结果,产品的背景进行总结与思考,定位接下来的设计风格。
选取照片
观察生活,对想画的图标进行照片实物造型的提取。图标是对生活中事物的精简概括。利用现实照片作为设计参考可以让绘制出的图标更真实,辨识度更高,还可以做到差异化设计。
造型勾勒
使用矢量软件的基本图形与钢笔工具描着照片进行轮廓的绘制。
简化优化
简化草稿轮廓的结构,只保留一个物体的主要特点元素,删除多余元素。优化图标细节,需要时将图标线性转面性。
业务属性
根据业务需要,调整图标风格,添加质感。
无规矩不成方圆,规矩的出现可以让一切杂乱的东西变得合理,统一起来。在设计上也是如此,规范具有统一输出,指引细节、便于查看的好处,规范就是一组图标中的规矩,所有图标的绘制都按照规矩来,最终的成品就会显得井然有序。
在制定规范时,我们通常先绘制出一个符合业务风格的图标,然后根据这一个图标定制后续的图标规范,最基本的规范便是描边宽度,断点位置、圆角大小,主色辅色,渐变角度,点缀元素,光影角度等,在一组中的图标需要在这些图形属性中进行统一,这样的图标虽然形状不一样但是在视觉上看起来是属于同一合集的。
制定规范一般分为三个过程:
文章来源:优设网 作者:箫灬西人生
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
来源 | BranD的好奇心(ID: BranDmag)
2021年最受欢迎的字体
shillington网站评选出20款字体
众所周知,字体对于塑造品牌、塑造企业形象有着举足轻重的作用,其设计以本身的文化性、时尚感以及表形表意的双重作用都具有同等重要性。由此可见,很多企业以及品牌都采用字体作为自己的独特标志。
▲Garnett字体
前段时间,shillington网站出了一份关于2021年最受欢迎的20款字体设计的测评报告, 可以看到很多字体的复兴,榜单上这些字体设计不仅仅局限于新颖和时尚,还包括了一些较复古的,视觉上更为成熟的字体,这份榜单都会给设计师们带来哪些惊喜呢?那就让我们一起拭目以待吧!
01Futura Now
Futura Now是Monotype工作室设计的一款字体,它不仅包含了102种可变样式,还是经典无衬线字体Futura的权威版本。近90年来,该字体广受欢迎,使用范围也很广,从儿童读物到时尚杂志,都有它的踪影。
Monotype的创意总监Steve Matteson还说过:“尽管是以现代字体而闻名,但Futura Now却出奇的温暖。”它更像是一个中间地带,处于粗矿与温暖的边界,不卑不亢,一切刚刚好。
02FS Renaissance
FS Renaissance也是Monotype工作室发布的一款独特显示字体,它由字体艺术家和设计师Craig Back以及创意总监Pedro Arilla合作而诞生,这种单一样式的字体探索了艺术与设计的关系。在艺术家和设计师的共同努力下,每个字母都被制作成独立的艺术品。
文艺复兴时期代表着艺术,科学,学习和哲学的蓬勃发展,FS Renaissance字体受该时期的启发,特别强调了将字体作为艺术品或雕塑的想法,并在兼具外部优雅感的印刷基础上,使其的设计在功能和艺术之间取得了完美的平衡。
03Neue Haas Grotesk
在1957-1961年期间,它经过Max Miedinger设计、Eduard Hoffmann艺术指导完成了对经典字体Helvetica的现代诠释。但是Christian Schwartz设计师认为Helvetica的数字化涉及了太多的妥协,因此,经他设计出来的全新数字版本Neue Haas更忠于原版字体。
该字体作为一款很实用的无衬线字体,具备着一定的结构严谨以及简洁美观的优点,其线条更是干净利落,毫无多余的点缀,这在视觉上,它的效果很佳。还有,它现在可以从谷歌字体库中免费使用了。
04Circular
Circular是由Laurenz Brunner设计并通过Lineto发行的无衬线字体,它作为一款无衬线字体,虽然字型具有几何形状的特征,但它能比大部分的同风格作品更具吸引力和特色都得益于一些古怪的元素。
05Whyte
这是一款由Dinamo设计设计的无衬线字体,它可以在平滑与尖锐的视觉中取得平衡与过渡的良好效果。最令人兴奋的是,它这款可变字体得到了InDesign的支持,我们相信2021年它将会流行起来且成为大众追捧的字体之一。
06GT America
由NoëlLeu和SebMcLauchlan设计的GT America本质上是延续了19世纪美国哥特式和20世纪欧洲新哥特式字体的风格。它提供84种样式,在字型宽度和字重上融合了两种传统设计元素并将此特点发挥到淋漓尽致。
07Noe Display
Noe Display是一款显示字体,它轻而易举地彰显出其大胆的笔触方式,以常规黑色粗体为主,字母之间可以通过楔形的衬线转折。不仅如此,该字体还为整体视觉赋予了富有戏剧性和冲击力的体验。
08Basis Grotesque
Basis Grotesque最初是按常规字体的粗细来进行绘制的,主要途径仅是用于重塑摄影杂志《Hotshoe》。在这之后,由Colophon开发并发布了该字体,并在三年后用于商业用途。该字体在字重之间的比例,及其字体骨架上均有着微妙的平衡。
///
09Eksell Display
Eksell Display是来自传奇瑞典设计师Olle Eksell(1918–2007)于1962年创作的一款独特的衬线字体。最初的字母形状是在Olle位于斯德哥尔摩的工作室中工作室中绘制的,在此版本中,这些字母已经通过很仔细的数字化处理,并发展成四种不同的风格。
10Lars
无衬线字体Lars是一款通用字体。该系列以圆形符号为主,可以区分字母大小写,涵盖了多种语言,并且可读性强。
11Simula
Simula作为一款衬线字体,还是艺术家、设计师Justin Sloane的设计的首款字体,它在一些小细节上的设计处理得很好。该字体是对手写字体的重新诠释,将传统的手写字风格演绎得淋漓尽致。
12Parnaso
当今,紧实,瘦弱和人文主义的衬线真的很流行,这款字体就是一个很好的例子。
它的创作灵感来自19世纪复兴的古罗马风格,这是对Didot和Bodon现代风格的最好反击,其具有高对比度和鲜明的细节,常常成为编辑或广告作品中首选。该字体还提供了八种不同字重和宽度的样式,可以组合在一起或独立使用。
13IvyMode
IvyMode是由设计师Jan Maack专门为杂志定制开发的一款无衬线字体,它一共拥有10种字体形式,具有高对比度和突出的笔划结尾,自然而然,成为奢侈品牌们的首要选择。
14Orpheus
Orpheus字体的设计灵感受到Walter Tiemann在1928年设计的两种衬线字体的启发,该字体在包装和娱乐设计中很受欢迎。受手写体的影响,它的斜体设计将古典罗马美学风格与装饰艺术的魅力结合在一起,打造出别具一格的视觉效果。
15Garnett
Garnett是由Connor Davenport设计并通过Sharp Type发行的带有现代风格的字体。它的设计灵感来自于19世纪英国古怪的怪诞风格以及受到美国哥特式风格的影响,该字体系列有六种字重,还带有与字重相匹配的斜体。
16FS Meridian
这是一款充满几何形状的字体,灵感来自时间的精确但不完美的性质(Meridian有‘子午线’含义,该字体因此得名)。该字体还具有宽阔的单线外观,富有人性化的元素和可不断进行延伸的形式风格。
17Moderat
Moderat是一款几何无衬线字体,其特征是笔画间的对比和棱角分明的细节。该字体适用于正文和屏幕显示场景,一共拥有42种样式,还相对应地匹配斜体。
18Miller Banner
Miller Banner是一款经典的字体,它广受人们欢迎,该字体是由Richard Lipton改编自Matthew Carter的热门美剧《米勒》的宣传字体。它有锋利的线条感和非常戏剧性的笔画对比,非常适合在文章标题中使用。
19Monument Grotesk
Monument Grotesk是一款独特而自信的字体,它看起来未经修饰和造型奇特且十分具有粗狂感。该字体有7种不同的字重可供选择,包括斜体,mono和semi-mono cut以及带有相应斜体的粗体和黑体。
20Bely
Bely是由Roxane Gataud设计的富有冒险精神的衬线字体,其特点主要体现在尖锐的三角形衬线上,它含有两种粗细匹配的斜体以及显示字体,我们可以在粗细笔画之间看到很明显的对比。在Altrincham项目中可以看到它的运用效果。
字体本身作为一种文化传递的载体,其的魅力就在于让大众可以感知到它所传达的设计理念。看完以上的字体,有哪款字体令你印象特别深刻的呢?欢迎小伙伴们到评论区留言喔~
图片 | 来源于网络
*本篇部分文字资料整理于shillington网站,
仅供学习与分享,版权归原作者所有。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
2020年可以说是一个风险年,但更是一个机会年,全球各类资产都出现了大行情机会,市场的投资热情再次被点燃。借着这股东风,在2020年年尾,我们开始了对公司金融产品的优化改造工作,希望通过改造提升产品的用户体验,配合来年的运营活动,提升产品的用户数和活跃度。改造工作主要为优化开户流程、提升社区氛围、完善交易功能三个部分。后续我将通过系列文章对这次优化设计过程中的思考进行分享。
表单作为平台与用户联系最为紧密的一环,良好的表单设计可以带给用户流畅自然的用户体验,保证用户情绪的正向增长,而混乱无序的表单则会引起用户的负面情绪,影响甚至阻碍用户操作的完成,降低用户对品牌好感度和信赖度。对于我们这样的金融产品而言,产品内存在着如开户表单、出金申请表单、调整杠杆申请表单等形形色色的表单,如何将这些表单整理归纳形成一套完整的表单设计体系,带给用户统一、高效且优质的填写体验,是我们这次表单优化的主要的任务。
系列文章中关于表单设计部分我将分为上下两期来向大家分享,体系化表单设计(上期)主要介绍在项目中总结出的表单设计中的方法论,下期则是介绍方法论在我们项目中实际的应用,希望这次的分享能为你今后的表单设计提供思路与参考。
表单在我们工作、生活中的使用由来已久,在还没有互联网的年代,表单就已经是人们收集和存储数据、信息的重要手段,并一直沿用至今。如体检时填写的体检表、入职时填写的入职登记表、银行开户时填写的开户表都是使用的这种印刷的纸质表单。它们身上有很多设计可以作为重要的参考,帮助我们优化 UI 中的表单元素。
表单是 UI 界面中最为常见的元素,它通常是用来搜集和呈现一些数据、信息和特定的字段。表单的应用极为广泛,比如登录应用时填写账号密码、网上购物时完善订单信息、OA系统中提交休假审批、修改个人中心信息时……都是在和表单发生互动。
表单的目的、内容、大小等虽然各有不同,但是表单的基本构成元素是相对固定的,在设计过程中,设计师需要合理组织这些元素,帮助用户在填写表单时,轻松愉快的完成,表单主要组成部分如下图。
1.标签:告诉用户此处相应的输入元素是什么;
2.输入区:可交互的输入区域,根据字段类型使用相应的交互组件;
3.占位符:对当前项进行额外的信息描述;
4.前置图标(可选):描述文本所需的输入类型和特征;
5.后置图标(可选):对输入内容进行控制,如:下拉的展开与收起、清空;
6.帮助(可选):提供表单内容的注释或辅助类容,如:说明、注意事项;
7.反馈(可选):告知用户当前操作可能或已出现的问题,如:提交成功、错误提示、网络问题;
8.键盘(可选):在文本编辑时需要使用键盘,如:设备系统键盘、应用内置键盘;
9.操作按钮:操作按钮是在表单的结尾,如:提交、下一步、清空所有信息。
在如今这个互联网时代,我们几乎每天都会接触到形形色色的表单,作为用户与产品链接的枢纽,表单设计的好坏会直接的影响产品的实际数据表现。好的表单结构清晰,交互合理,用户能够高效愉悦的完成表单填写,为用户节省了时间,同时也提高了自身产品的转化。而差的表单往往信息逻辑混乱,填写效率低,且容易让人产生挫败感而中途放弃,在无形中浪费掉了很多潜在商业机会。是什么造成了不同表单之间出现如此大的体验差异,我们又该如何做才能设计出令用户愉悦的表单呢?在实际项目过程中,总结出一套适用于移动端表单设计的路径图-通过做好五个步骤,设计出令人愉悦的表单。
合理的表单框架选择是打造用户友好型表单的基础,在进行表单设计时,我们首先需要依照表单的使用场景和复杂程度,选用最为恰当的表单框架。确定好表单框架,也就决定了后续设计中表单信息如何组织以及呈现。我们将表单框架划分为“录入方式”、“标签布局”和“按钮逻辑”三个部分,在表单设计时通过对这三个部分的选用来确定最终的表单框架形态。
按照表单录入方式的不同我们大体上可以将表单录入方式分为“单步录入”、“分步录入”和“分级录入”三种,在进行表单设计时需要根据实际情况选择与使用场景匹配的录入方式。
单步录入是表单中最为常见的录入方式,在一个页面内呈现所有的录入项,结构简单,快速录入、快速提交,适用于录入项较少的表单。
相对于PC端而言,移动端手机屏幕尺寸较小,一份在PC端1-2屏就能完全展示的表单在移动端往往需要7-8屏。将一个需要7-8屏才能展示完整的表单放在一个页面内让用户填写,用户容易产生抵触情绪会造成表单完成率的降低。
为了提高用户填写效率,减少用户的抵触情绪,我们可以将一个冗长的表单拆分成多个步骤,分步录入。通过拆分成一个个步骤,让表单信息呈现更为清理有条理,并且能引导用户逐步填写完成表单录入。
当表单处于以下4种场景时选择建议选用分步录入模式:
1.表单录入项过多,在一个页面内已经不能合理清晰的组织传递信息。
2.表单内容的录入方式存在较大差异,不适宜在一个页面内进行展示。
3.表单录入项在业务上存在先后顺序,只有先完成上一步字段录入,才能够进入下一步。
4.在业务上很重要的表单,为了让用户能够沉浸、快速的完成表单填写时。
分布录入模式下步4种步骤导航选择:
1.文字导航:当表单为2步录入表单时,我们展示步骤条带给用户的引导意义并不大,通常这种情况下我们会选择省略掉步骤条,只展示当前步骤名称,给予用户提示。
2.步骤条导航:当表单录入步骤为3-4步时,我们可以在页面顶部放置步骤条显示所有步骤内容标题,用户通过步骤条能够对表单有一个清晰的预期。
3.双层步骤导航:当表单录入步骤大于4步时,受限于移动端屏幕尺寸,横向上不够容纳步骤数太多的步骤条,这时我们可以其中某些关联的步骤归纳为一个大步骤,形成双层步骤导航。
4.进度条导航:当表单录入步骤大于4步,又担心双层导航给用户传递出表单极端复杂的印象,劝退用户。这时我们可以使用进度条导航,用百分比进度条来展现表单填写进度。
分级录入大家可能相对较为陌生,分级录入在B端产品中会有相对多见,一般运用于有明显上下级关系的表单,如项目管理工具中新建任务表单,在新建任务的同时还能新建下属子任务。又如客户关系管理软件中,新建订单的同时新建下属的订单明细。我们可以将使用分级录入模式的表单视为两张表单,子表单添加的数据会回显到主表单上。
标签用于提示用户需要输入的是什么信息。合理的标签布局结构,能够提高用户的阅读效率,还能降低信息填写时的错误率。常见的标签布局形式有:左右结构、上下结构和浮动结构。不同的标签布局都有各自的优点和缺点,我们需要根据项目实际情况来选择最合适的标签形式。
左右结构是目前最为常见的标签布局形式,左右结构中标签和输入区域在一行内排布,其中标签位于左侧且居左对齐,输入项位于右侧有居左和居右对齐两种对齐方式。
优点:节省纵向页面空间,在移动端有限的页面空间内能展示更多的录入项。
缺点:标签的长度无法确定,视觉上显得参差不齐,表单的信息浏览和填写效率一般,标签横向展示空间有限,对于多语言适配场景不太友好。
上下结构也是我们能够经常在表单中见到的标签布局形式,上下结构中标签位于上方且居左对齐,输入区域位于下方也为居左对齐。
优点:用户的视觉浏览路径相对于左右结构来说较短,拥有较强的信息浏览和填写效率,标签横向展示空间充足,对于多语言适配场景友好。
缺点:占据纵向空间多,一屏内能展示的录入项较少。
Material Design中文本录入的标签形式就是选用的浮动结构,在浮动结构中标签和提示文字合二为一,正常状态下,标签位于输入区域内部原本提示文案的位置,当用户输入时,内部的标签就会上移为文本输入让出空间,完成填写后标签和输入文案上下排列展示。
优点:结构简单,视觉干扰少,信息浏览和填写效率高。
缺点:填写项过多时,表单信息传递不够清晰。
内部结构相对于前面3种结构较为少见,比较长出现在登录场景,在浮动结构中标签和提示文字合二为一,正常状态下,标签位于输入区域内部原本提示文案的位置,当用户输入时,内部的标签就会消失,完成填写后只展示输入文案。
优点:结构简单,视觉干扰少,聚焦于操作。
缺点:只适用于如登录等录入项极少的场景,一旦录入项变多,由于录入后不展示标签,将导致用户后续很难判断输入的信息是否准确。
按钮作为表单的重要组成部分之一,合理的按钮逻辑能够为用户顺畅完成表单填写提供帮助,表单的按钮逻辑主要由按钮的位置和按钮的点亮逻辑两部分组成。
按钮在页面中的位置情况主要有以下3种:
1.顶部按钮:以文字的形式固定在顶部导航栏的右侧,顶部按钮尺寸较小,因为它所占空间有限,因此在操作上相对来说不便于点击。所以这类顶部按钮更适用于「编辑页面」,需要用户谨慎操作。
2.表单底部:按钮跟随表单放置于表单的最下方,根据表单内容纵向空间的大小而上下移动。因为表单内容较多时,容易下沉过多而导致按钮不可见,所以将按钮放置于表单底部更适用于当表单录入项较少不足半屏的场景。
3.设备底部:操作按钮常驻在设备底部展示,适用于表单录入项过多的情况,在表单设计时可以尽量将必填项放置在表单前面,用户填完必填项后就可以点击操作按钮提交或者进入下一步,而不用滑动到表单底部再进行操作。
1.当表单录入项较少时,且有明确预期按钮何时可用,可以先置灰主按钮,完成必填项填写后再点亮主按钮。
2.当表单录入项较多时,且用户不清楚为什么按钮不可以用,此时按钮可以常亮,并在用户点击时给予反馈,告知错误原因。
在确定好表单框架以后,对于表单内容信息的进行有效的组织也尤为重要,特别是对于一些结构复杂、录入项多的表单,如果不对信息进行组织,很容易显得繁杂混乱,容易让用户在一开始就产生抵触的情绪,甚至选择放弃。那么如何合理有层次的组织信息呢?
我们在设计表单时潜意识里都想要从用户那里获取到更多的信息,表单中因此出现很多必要性较低的录入项,表单也因此变得冗长,让人第一眼就生出「好多信息需要填,好麻烦」的沉重感,在填写表单之前就萌生退意。我们在进行表单设计时需要保持克制,聚焦于表单的核心任务,让表单尽量短而美。那么我们要如何为表单减负,可以尝试以下方法。
表单中每多一个录入项需要填写,都有可能会失去一部分用户好感度甚至流失一部分用户。在设计时我们需要判断某个字段信息对于用户来说是否有必要在表单中进行填写,尽可能的删减掉额外的无用字段。例如注册表单,如让用户使用邮箱注册,那么用户的姓名字段是否是注册的必选项?如果不是必选项是否可以在之后的信息完善中进行填写。
在表单中时有一些信息他们本身紧密相关,我们完全可以视情况将其合并为一个录入项,来减少不必要的录入操作,达到简化表单,提升录入效率的目的。合并录入项要结合实际的使用场景以真实的提升表单体验为目的,而不是一味的追求表单的最简化。
根据用户使用数据,适当将使用频次不高、或者提供给专业用户的高级表单项隐藏起来。例如一份表单中有一个填写项,90%的用户都不需要填写,那么默认收起。保持表单的简洁,让绝大多数用户快速完成,避免大量的表单给用户的焦虑,而又满足了小众用户的需求。
根据沉没成本的定义:人们在做决策时,受到了自己过去所投入的时间、金钱、精力等因素的干扰,对于先前付出了投资的事情有更强的忠诚度和继续投资的意愿。进行流程设计时也可以遵循这个原理,将容易完成的表单放在前面,这样做有3个好处:
1.简单的表单更容易激起用户的填写欲望,用户会迫不及待地去完成。相反,用户一开始就看到过于复杂的表单,很容易被吓到,从而放弃整个任务。
2.用户通过完成简单的表单,可以增加自信心,即使后面的表单变复杂了,用户也更有耐心去完成。
3.当用户将前面简单的表单完成后,放弃整个表单的机会成本就变高了,即使后面碰到较难的任务,用户放弃的几率也会降低。
当我们我们设计的表单字段内容较多时,需要合理的对字段信息进行分组,这样整体看起来更加有组织性。接近性(格式塔原理)原则告诉我们: 相互靠近的物体被认为比相互距离较远的物体更有关联性,这样能使设计界面层次有序,视觉清晰,减少视觉噪音。分组时需要注意:
1.内容属性相近或有关联性的放在一组。
2.根据信息的重要性及难易程度排列分组,将选填的表单内容靠后
在表单录入设计阶段,我们需要明确认识到一点,用户在面对一份表单时往往没有我们想象中的那么有耐心,复杂繁琐的录入操作可能会直接劝退用户。我们需要做的就是化繁为简,思考如何给用户减负,让用户简单高效的完成表单录入。表单录入操作提效有一些切实可行的方法,下面请我将一一向分享。
对于用户而言,填写信息永远都不是一件有趣的事情,在对用户足够了解的前提下,我们可以选择为表单中的部分录入项提前设置合理的默认值,节省用户的操作时间。默认值的设置不是一个随性发挥的过程,而是基于用户行为和数据的理性判断,并且也不是每个字段都适合设定默认值。关于如何设置合理的默认值,什么字段适合设定默认值,下面几点可供大家参考:
在一些业务场景,会使用到用户之前在其它表单中已经录入的信息,此时在填写新表单时,可以默认带入之前的数据。
如果用户正在填写的内容有相关的关联数据,可以默认带入。如我们在填写订单时可以默认带入该订单关联的商品基础信息。
基于移动端设备的能力,我们可以在用户开放权限的情况下获取一定的用户信息(位置信息、电话区号、运动数据等),在特定情况下默认填写,如滴滴通过GPS定位自动帮用户填入上车位置。
像电话区号、证件类型、国籍等用户录入结果相对固定的字段,可以根据情况提设置合理的默认值。
相较于PC端而言,移动端设备屏幕尺寸较小,虚拟按键的输入效率远不及实体键盘,在移动端手动输入的成本较高。因此,为了打造便捷优雅的操作体验,移动端表单需要尽量减少用户的手动输入。以下方法可以减少手动输入。
联想输入是给予用户输入字段的自动补全功能,用户少量输入后进行选择。录入方式由原来的输入变成半输入后选择,减少用户的输入成本,提高用户操作效率。
对于表单填写过程中可以固化选择的信息,应让用户进行选择操作以代替手动输入,尽可能地让用户减少输入成本。
一份用户可能会多次填写的表单,我们可以提供用户的历史输入项供其选择,如滴滴的打车页面会将我的常用目的地放置在目的地输入框的旁边供我快速录入。
一些新型的交互组件的使用能够简化信息录入的操作,例如滑块组件等。
在填写表单时如果填写项需要频繁的页面跳转会使得整体的填写效率变低,增加用户的操作成本。在进行表单设计时应尽量规避这种频繁的页面跳转,选用更流畅灵活的交互方式。
在网页端表单设计中,用户在表单填写中需要对选项进行选择时,常用的交互形式是在选择器的下拉列表中进行选项的二次点击。而在移动端设计中,触发选择器后的二次点击会增加用户的填写成本。所以在设计时,当选项少于8时,在表单中直接显示所有可选项,当选项超出过多时则在列表浮层中进行选择。
在表单填写中我们期望用户保持专注,尽量避免产生引导用户离开当前页面的填写交互,这种交互跳转很容易打断用户固有的行为轨迹。因此运用浮层、弹窗等交互来完成辅助信息的采集是我们较为推崇的交互形式。
对于一些标准证件类信息的录入,可以通过OCR识别文件内容。当用户上传图片后,运用图像识别技术提取关键信息并自动填入结果。值得注意的是,如果图片不清晰或存在水印,将大大降低识别准确度。此时应提供修正渠道,让用户可以逐一校对并修改文本内容。
短信验证码升级方案。直连三大运营商,一步校验手机号与当前SIM卡号一致性。优化注册/登录/支付等场景验证流程,有效提升拉新转化率和用户留存率。不做数据加工与号码精准营销,保护用户隐私。
为了避免让用户频繁的跳入跳出相同类型的输入项,首先整合表单的信息字段,将同类型的字段进行合并,同时结合输入控件,设计联动式组件,让用户在表单输入时更加高效。
设计不是简单的元素拼凑,深入下去,有很多细节需要推敲,细节应该是含蓄的,包含在整体之内。好的细节设计不容易被用户的眼睛直接发现,但是会让用户与产品的交互过程变得通顺、舒适,概括来说就是润物细无声。对应到表单设计上,我们需要通过表单设计中的细节把控,让表单录入这件事变得简单、高效。
当表单中同时出现必填项和选填项时我们需要对其做出区分,避免用户不知道哪些字段必须填写、哪些字段可以选择性填写。沿用通用符号习惯,在表单中我们往往使用 * 号来标记必填项。但是当表单中的必填项多于选填项时,大量的 * 号会增加用户的认知负担,面对这种情况,我们可以使用暗提示来标记选填项帮助用户识别。
如电话号码、银行卡号这类有数字组合规律的号码字段,我们可以沿用它们在线下的数字组合规律,通过空格对号码字段进行划分,帮助用户校验和阅读。
出于保护用户账号安全考量,我们在进行密码输入时通常使用隐暗文字的方式来保护用户账户安全,但是暗文字的显示方式会让用户无法确认密码信息。因此我们可以在输入时,让输入字段短暂显示,保持1秒然后再转变为暗文字,这样既可以让用户明确内容,也保证了用户的账户安全。
我们在进行表单设计时,输入区域的长度要符合心理预期,需要预判填写内容长度来确定输入区域的长度。这样不仅在体验上一致,而且在视觉体验上更加愉悦。
用户应该对他们的操作所带来的结果非常自信,使用“提交”、“注册”、“立即支付”、“创造账户”等确定性文案来描述用户将采取的操作。
报错信息应当一目了然,从用色、图标到文本都应当起到高亮的效果,而且报错信息应当靠近输入框,而非表单的底部或者顶部或者按键旁边。
在设计主要由文本输入框构成的表单页面时,要考虑键盘出现可能会遮挡输入框的情况,我们需要把控件放在scrollView上,当键盘会遮挡输入框时,则表单滚动。
对于异常情况不能只是冷冰冰的告知失败,这样容易给用户带来挫败感,且缺少下一步操作指引。错误反馈不应该只着眼于结果,错误反馈的阐述角度应该是引起用户关注、让其快速了解出错情况,并指导如何处理。
经过前面几个步骤,表单整体形态已经确定,最后一步我们需要从整体体验的角度对表单进行完善和调整。包含表单的容错性考量、表单流程闭环的打造、视情况而定的趣味性设计。
即便你的产品90%的时间都运行良好,但是如果在用户需要帮助时置之不理,他们是不会忘记这一点的。——《Getting Real》
容错性概念源于计算机领域,容错性是指计算机系统在发生故障的情况下,依然能够保证系统正常运行。计算机这种保证系统正常运行的能力也被称为容错能力。延伸到互联网产品设计领域,容错性的范畴更为宽泛,包括降低用户操作的出错率、及时提供纠错帮助、提供解决方案等内容。
容错设计与用户体验息息相关,我们在表单页面设计时也需要进行容错性考量,尽量避免用户错误操作的出现。当用户出现错误操作时,帮助用户识别、诊断,及时反馈问题所在,并提出有效的解决方案,帮助用户快速从错误中恢复。让表单填写流程更顺畅,给用户带来更优的用户体验,关于表单容错性设计可以从以下几个方面来进行。
引导和提示要突出表现,从而引起用户关注,确保用户在操作前能注意到引导或提示信息。引导与提示用语要简单且易于理解,当重要或操作不可逆时,要询问用户让其知道这样操作的后果。
如何从设计上避免用户出错,限制是一种非常必要的方式,可以通过限制用户的某些交互操作或者增加某些操作的难度来对用户操作进行限制避免用户出错。
当用户出现填写错误时,及时的反馈错误并提供纠错帮助,出错信息应当用清晰准确且用户易于理解,能够对用户解决当前问题提供建设性帮助。
允许用户犯错,操作者能归够撤销以前的指令,帮助用户在犯错以后能够快速回到正确状态。
表单的终点并不是提交,一个好的表单设计需要兼顾考虑用户填写前的引导、填写时的及时校验与帮助、还有填写后的整体流程体验,为用户提供完整的、形成闭环的表单填写体验。
举个例子,当我们设计的表单需要用户准备如身份证、银行卡这类的证件时,需在表单填写前告知用户,避免用户填写途中才发现证件未准备,导致用户填写流程中断。再如,用户在填写完证券开户表单后,其实还需要通过审批后用户才能进行入金交易等操作,这时我们需要一个结果页来告知用户表单提交的结果状态和下一步的操作指引。
表单设计并不一定需要是严肃且正式的,在表单设计时可以尝试引入一些趣味性的元素,研究表明,更大的文字输入框、适度的留白空间、优雅的动画效果、趣味性界面设计会让人心情愉悦更有填写的欲望。
例如bilibili的登录页面,在用户输入账号时上方的卡通形象是睁眼的,当切换到输入密码或者验证码时卡通人物会有一个捂住双眼的动作十分有趣,这样的趣味性设计能够在一定程度上缓解用户在填写表单时的焦虑情绪,并增加对于bilibili保护账号安全的信赖感。
以上就是我对于移动端表单设计的一些归纳和总结,过往的项目中自己设计大量的表单页面,走了不少弯路犯了不少错误,但也通过项目不断的反思总结,收获不少的关于表单设计的经验。在这里将项目中关于表单的一些思考和经验分享出来,总结出自己的一套关于表单设计的方法论,也是希望能够对正在进行表单设计或者即将进行表单设计的你提供一点点参考与帮助。
文章来源:站酷 作者:Yone杨
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
this指向的问题也是JavaScript中的难点之一了,也是面试常问的问题,很多时候对this指向的问题就很懵逼,明明应该是指向他,为什么又指向他了…所以我就学习了一下这方面的知识,整理了一下,希望能够帮助大家
首先看一段代码
function identify(){
return this.name.toUpperCase()
}
function speak(){
var greeting = '你好,我是'+identify.call(this)
console.log(greeting)
}
var me ={
name:'kyle'
}
var you ={
name:"reader"
}
identify.call(me)
identify.call(you)
speak.call(me) //? 你好,我是KYLE
speak.call(you) //? 你好,我是READER
上面的这段代码中可以从不同的上下文对象 me 和 you 中重复的使用identify函数和speak函数
如果你不使用this的话 你就要显式的将上下文对象作为参数传递进去,比如这样:
function identify(context){
return context.name.toUpperCase()
}
function speak(context){
var greeting = '你好,我是'+identify(context)
console.log(greeting)
}
var me ={
name:'kyle'
}
var you ={
name:"reader"
}
identify(me)
identify(you)
speak(me)
speak(you)
就像这样,这样看起来就不想上面那样简洁了,你要把一个对象传来传去的
刚见到this的时候 觉得this指向是这个函数自身,或者是函数的作用域,后来发现其实不是这样的的,不过也不能说错了,因为有些情况确实是这样的,比如这样:
function foo(num){
console.log('foo'+ num)
this.count ++
}
foo.count = 0
var i;
for(i = 0;i<10;i++){
if(i>5){
foo.call(foo,i)
}
}
console.log(foo.count) //4 这样的话 this指向了foo本身 foo上面的count属性++
无法指向函数作用域
var a = 3
function foo() {
var a = 2;
bar.call(foo);
}
function bar() {
console.log( this.a );
}
foo(); // undefined
我们要记住非常重要的一点:this是在运行的时候进行绑定的,而不是在定义的时候绑定,this的绑定跟函数声明的位置没有关系,主要是取决于函数的调用方式,想要找到this指向谁,我们就要看懂函数是怎么调用的。
1.默认绑定
当一个独立函数正常调用的时候,不带任何修饰的调用
// 非严格模式下
var a = 3
function foo(){
console.log(this.a) //a
}
foo()
这种情况下 this.a被解析成了了 全局变量a,this指向是全局对象
// 严格模式下
var a = 3
function foo(){
"use strict"
console.log(this.a) //TypeError
}
foo()
严格模式下 this不会指向全局对象 this绑定的是undefined
2.隐式绑定
调用位置上是否有上下文对象
function foo(){
console.log(this.a)
}
var obj = {
a:2,
foo:foo
}
obj.foo() //2
调用位置会使用obj上下文对象来引用函数,foo被调用的时候 他的落脚点指向是obj对象,隐式绑定的规则就会把this指向这个上下文对象。所以this.a就跟 obj.a是一样的
function foo(){
console.log(this.a)
}
var obj = {
a:2,
foo:foo
}
var obj2 = {
a:3,
obj:obj
}
obj2.obj.foo() //2
当多层调用的时候 只有最后一层才会影响函数的调用位置 比如上面这个 this绑定的还是 obj 而不是obj2
注意
隐式绑定会出现隐式丢失的问题,会失去绑定对象,最后应用默认绑定
var a = 3;
function foo(){
console.log(this.a);
}
var obj = {
a:2,
foo:foo
}
var bar = obj.foo
bar() //3
bar 是 obj.foo的一个引用 他引用的是foo函数本身,此时bar就是一个不带任何修饰的函数调用 应用默认绑定
var a = 3;
function foo(){
console.log(this.a);
}
var obj = {
a:2,
foo:foo
}
setTimeout( obj.foo, 100 ) //3
setTimeout(function(fn){
fn()
},100,obj.foo) //3
参数传递也是一种隐式赋值,回调函数丢失this是非常常见的…
3.显式绑定
隐式绑定的时候我们必须在一个对象内部包含一个指向函数的属性,然后通过属性间接引用函数,把这个this间接隐式的绑定到这个对象上
如果我们不想在对象内部包含函数的引用 ,而想在某个对象上强制调用函数
我们可以把这个函数绑定到对象的原型上,也算是不用再对象内部包含函数了吧…
更好的办法是我们可以使用函数的 call() apply() bind() 这种方法
function foo(){
console.log(this.a)
}
var obj = {
a:2
}
foo.call(obj) //2
foo.apply(obj) //2
如果你第一个参数传入的是一个原始类型 比如字符串 布尔 数字作为绑定对象 这些原始类型会被转换为 对象的形式 new String() new Number()…
硬绑定
Function.prototype.bind()
function foo(){
console.log(this.a)
}
var obj = {
a:2
}
var obj2 = {
a:3
}
var bar = foo.bind(obj) //会返回一个硬编码的新函数 他会把参数设置为this的上下文
bar.call(obj2) //2 返回的新函数
有些api 方法 会提供一个可选参数 context 其作用跟bind一样 确保你的回调函数使用指定的this 比如 array.forEach(fn,context)…
4.new绑定
使用new 来调用函数的时候会执行以下操作
1.创建一个全新的对象
2.这个新对象会被执行原型的链接
3.新对象会绑定到函数调用的this
4.如果没有返回其他的对象,那么函数会自动返回这个对象
function Foo(a){
this.a = a
}
var bar = new Foo(2)
console.log(bar.a) //2
使用new 来调用Foo函数 会构造一个新对象并把它绑定到Foo调用中的this上 然后返回了
函数不带任何修饰的时候单独调用才会触发默认绑定 所以说默认绑定是优先级最低的了
那剩下三个规则哪个的优先级最高?
显示绑定跟隐式绑定比较
function foo(){
console.log(this.a)
}
var obj1 = {
a:1,
foo:foo
}
var obj2 = {
a:2,
foo:foo
}
obj1.foo() //1
obj2.foo() //2
obj1.foo.call(obj2) //2
obj2.foo.call(obj1) //1
可以看到 显示绑定的优先级还是更高一点
new 绑定跟隐式绑定比较
function foo(arg){
this.a = arg
}
var obj1 ={
foo:foo
}
var obj2 ={}
obj1.foo(2)
console.log(obj1.a) //2
var bar = new obj1.foo(4)
console.log(obj1.a) //2
console.log(bar.a) //4
可以看到 new绑定的优先级比隐式绑定要高
new 绑定跟显示绑定比较
new跟call apply无法一起使用 无法通过new foo.call(obj),试一下硬绑定
在这里插入代码片
function foo(arg){
this.a = arg
}
var obj1 ={}
var bar = foo.bind(obj1)
bar(3)
console.log(obj1.a) //3
var baz = new bar(4)
console.log(baz.a) //4
console.log(obj1.a) //3
new 调用bar修改了硬绑定时候的 函数的this new的优先级高一点
所以我们可以根据下面的优先级规则进行判断了
1.函数是否在new中调用 是的话this绑定新创建的对象 var bar = new Foo()
2.函数是否通过call apply 显示绑定或者是 bind硬绑定 如果是的话this指向指定的对象 foo.call(obj)
3.函数是否在某个上下文中调用 隐式绑定,如果是 this绑定那个上下文对象 注意绑定丢失的问题
4.如果都不是 就是默认绑定非严格模式下绑定的是全局对象 严格模式下绑定的是undefined
1.将null和undefined作为call apply参数 作为this绑定对象的时候 这些值会被忽略 应用的是默认绑定
var a =3
function foo(){
console.log(this.a) //3
}
foo.call(null)
2.箭头函数
function foo(){
return ()=>{
console.log(this.a)
}
}
var obj1 = {
a:3
}
var obj2 = {
a:4
}
var bar = foo.call(obj1)
bar.call(obj2) //3 this绑定的是obj1 而不是obj2!!!
在看一个
function foo(){
setTimeout(()=>{
console.log(this.a) //2
},100)
}
var obj = {
a:2
}
foo.call(obj)
箭头函数不使用this绑定的四种规则,而是根据外层作用域来决定this的,外层作用域的this绑定的是什么 他的this就是什么
转自:csdn 论坛 作者:Selfimpr欧
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com