首页

什么样的设计可以征服客户?

分享达人

在过去的2020年疫情中,很多设计师都降薪甚至失业,让本不富裕的生活雪上加霜。但与此同时,也有很多设计师反而在逆境中开了窍,接到了更多的单子,做出了更好的案子。


那么怎么才能过上钱多事少在家办公的独立设计师生活呢?我们邀请了八位出色的接单高手来一起探讨。他们中间有正在大厂上班偶尔接单的全职设计师,也有工作多年后毅然创业的创意老炮,有从未上班打卡的独立设计师,还有拥有着整个设计团队的公司老板。

 


他们是:

 

赵威:市场只要存在竞争就会要求我们去做一些革新和改变,这适用于所有行业。

全职设计师 / 5年经验 / 多服务于互联网及新型行业:媒体,社交,海外市场等。/ 年接单金额:数十万级 


迦木木:与其多独自做设计,不如多和顾客沟通,从而发现他们的真实需求。

独立珠宝设计师 / 12年经验 / 直接服务于消费者,女性为主。/ 年接单金额:数百万级


是北瓜呀:设计是一门手工活,活要出色是第一位的。

全职设计师 /  2年半工作经验 / 无固定服务行业。/ 年接单金额:数十万级

 

力虎广告:当你在某个领域足够优秀的时候,机会就会自己走到你的面前。

自营设计机构 / 公司成立5年 / 聚焦电商品牌视觉设计全案的广告公司,客户较多来自家居、母婴和美妆类目。/ 年接单金额:千万级


NiceLabStudio:活儿不分大小,用心去做每一件事,剩下的交给时间。

自营设计工作室 / 从业10年,工作室成立一年 / 多服务于“客户是年轻人”的行业,例如玩具,食品,潮流服饰等。/ 年接单金额:数百万级

 

你好大海品牌设计:设计师应该持有一定的态度、价值,用专业的设计能力和客户平等地对话。

自营设计机构 / 公司成立9年 / 多服务于快消、美妆、生活美学领域,及一些原创设计品牌的合作。/ 年接单金额:数千万级

 

石昌鸿(上行设计):把自己的专业做到极致,无人取代便是你的核心能力。

自营设计机构 / 公司成立8年 / 多服务于餐饮,白酒,茶类客户。/ 年接单金额:数千万级


杨晟Sheen(五感觉醒设计5SD ):认真对待每一次合作,从前的合作伙伴自然感受到你的用心和尽责。

自营设计机构 / 公司成立9年 / 多服务于互联网行业。


 


下面我们就进入主题:



WHY?WHAT?

客户为什么找到你?

设计师的核心能力是?



客户的情怀不多

客户都是实在生意人。设计师在苦恼缺少优质客户的同时,客户更烦恼怎么找到优质靠谱的设计师。客户只能从你的过往表现中为你已经证实的能力买单,而很少愿意去赌你未来可以突然爆发。


 从大家的回答和对设计项目的观察中,可以归纳出以下四个客户看重的设计师特征


1、与客户需求同类型的过往作品

如果你参与甚至主导过和潜在客户需求基本一致的案例,那么,这将会是最能打动客户的表现。例如你发布的作品中很多官网类的案例,那么想要做官网的客户就会循着这些案例找到你。


2、客户同行业的头部客户案例

一定要尽量服务各个商业领域里最头部的那些客户。因为他们的跟风者和崇拜者会愿意以更多的预算和尊重找到你。尽管他们也知道找到大佬的供应商并不能成为大佬,但是人们总是会迷信“明星同款”的威力。


3、独特的设计风格

客户们在争夺他们用户的注意力,在满足他们用户的审美需求。这个时候,一个区别于竞争对手的独特设计风格,会是他们重要的武器。做为设计师,千万不要去完全模仿另一个设计师。有实力的金主,永远只为第一人买单。让自己成为第一人,不要成为谁谁谁第二第三。


4、良好的设计师品牌

几乎所有的被访设计师都把这条作为最主要的原因。良好的设计师品牌意味着更大的知名度和更好的信用度。本文后面我们会围绕这个话题有更深入的探讨。



设计师的专业精神不少

成功带来更大的成功,十位设计师都不约而同地把专业精神视为设计师的价值核心,并且都在继续加强自己的设计方法体系,把每一个单都做为招徕下一个更好客单的引子,也作为验证自己设计观点的现实案例。

大多数设计师都已经选定了自己主要服务钻研的商业领域,用深度来交广度。设计师通过长期的服务和洞察才可以和客户对行业的机会问题等进行深入的交流,而非流于视觉效果表面。

持续的多维度的能力培养也是大家共同提到的关键,大家一致认为良好的学识和思考能力是设计师需要具备的素质。

 


不可替代的设计能力和良好的服务意识,就是设计师的专业精神。

 



 


叁山-浓缩茶 包装设计 THREE MOUNTAIN TEA  by NiceLabStudio





HOW?WHERE?

如何获得客户?

在哪里可以找到客户?



设计平台仍然不可替代

站酷是大家提到最多的关键词,抛开商业互吹,这依然显示出类似站酷,dribbble,behance这样的设计类公共平台在当今接单渠道中仍然保持着不可替代性。

在此之外,八位高手们几乎实践了常见的所有渠道:线下开店,朋友介绍,老客户推荐,中介服务等等,但是都只能带来零星的机会,不足以成为稳定的主要客单来源。

 


自建流量池的可行性不高

有两人提到了自建流量池。随着这些年短视频平台迅速崛起,确实让自建流量池的可能性大大增加。但是由于大众平台话题相对宽泛,并且读者兴趣点也相对分散,目前并没有很多设计师通过运营自媒体实现订单转化的成功案例。确实有一些设计话题下的大号和网红,但是他们的内容目标更多是依靠广告带货等手段直接变现,而非提升设计师品牌。我们会持续关注新媒体平台对外包业务的影响。另外,建立流量池的时间成本和操作难度也完全不同于设计师习惯的创作式工作模式。这次访问的八位设计师中,仅有一位拥有千万粉丝级微博大号。


 

不管在哪里,用作品说话

大家很有默契地提到了创建高质量作品集对吸引客户的决定性作用。渠道不是秘密,作品才是第一要素,好作品+好平台,才会带来好客户,这也是八位高手的共识。作品发布时,不仅要关注视觉上好看,也要注意写清楚必要的项目背景,行业信息等客户关心的内容。在平台与他人的互动中,也尽量保持有礼有理有节的交流,不要给潜在客户留下此人不好沟通的印象。

 


主动上门的客户,比较优质

如果你发布的作品已经获得了客户的欣赏,那么接下来的合作将会比较顺畅。这也是此次采访中大家的同感。这也是设计师品牌话题中的一环,稍后在设计师品牌中我们详细展开。

 


沟通能力+数据能力,设计师的技能点加法

三位设计师提到了沟通表达能力以及对数据的理解使用能力。

其中沟通能力是个传统技能,设计圈一直有三分做七分说的调侃,虽然有些偏颇,但是反映出沟通表达能力的重要性。因为设计师和客户的认知方式,知识结构等都存在着巨大的差异。很多同行间不言而明的常识,在客户那里可能是完全陌生的盲区。好的设计师需要知道怎么建立和客户的同理心,站在他们的角度,用他们习惯的方式去思考问题。

数据能力是时代的召唤。我们现在就生活在一个数据的时代,信息和商品的流动方式,内容和服务的交付方式,甚至消费者的决策方式都基于数据而定。在这个环境下,设计师需要建立对数据的基本认知,美学说服不了的客户,往往可以被数据说服。在之后的系列文章中,我们会在这个话题展开说明。

 

 

 

Mercedes me-梅赛德斯奔驰移动程序  by 赵威G


腾讯游戏创意大赛视觉设计GWB Game Awards 2020  by 五感觉醒设计5SD

 




designer personal brand 

你对设计师的个人品牌怎么看?



设计师应该持续打造自己的品牌

设计一直是个设计师品牌驱动的职业,设计师品牌是客户找到你的原因,它也时常可以形成很高的“品牌溢价”。可以说设计生涯就是个创造和运营设计师品牌的过程。以下我们梳理了设计师们对此的思考。

 


建立:风格,特色,定位

设计师本身往往就是品牌专家,甚至很多就是品牌设计师。但是当局者迷,为客户做品牌设计时思路清晰,节奏明快,到了为自己建立品牌时,很多老江湖也会犯迷糊。大概是因为人最难认清的就是自己。

但是从大家的交谈中,梳理出风格,特色,定位三个线索:

风格 是你最顺手舒适的设计方式,只有你本身就喜欢的方式才可以长期坚持。

特色 是你区别于别人的特征,用来回答为什么找你而不是别人这个灵魂拷问。

定位 是对于市场机会的理性分析,误入夕阳行业的边缘地带会带来事倍功半的后果。

 


输出:品质,一致,体系

规划好了建立一个风格鲜明,特色明确,定位精准的设计师品牌,怎么输出你的品牌印象给到行业和客户呢?大家共同谈到了这三点:


品质:把有品质感的内容展现给外界,这是设计师品牌印象树立的第一要务。品质感包括但不限于完整清晰的案例描述,画质清晰的图片展示。还要有发布平台选择,内容深度选择等一系列的思考。如上文提到的,能给读者留下靠谱专业的“信用感”为佳。


一致:人们不相信万能的神仙,留给每个品牌的记忆空间是很狭窄的。设计师品牌要避免试图营造“啥都擅长”的印象。始终用一致的风格强化设计师品牌的特色印象,保持不变的定位,才可以占领大家的心智。什么都是的品牌,什么都不是。


体系:市场的机会有限,但设计师们时常看起来十分相似,傻傻分不清楚,怎么办?这时候就看同一赛道上,谁有更深入的理解,能提供更全面的服务。前文里大家都在努力构建的设计方法论,在这时发挥了作用。

 


升级:从一个人到一群人

设计师的个人品牌往往成为设计团队公司化运营后的瓶颈。客户指名知名设计师本人来服务,但设计师自己的时间精力无法照顾太多项目。个人品牌的扩展性不高,团队品牌又不容易建立共情。怎么把一个人的名气变成一群人的名气?这是需要在初期就做好预案的问题。

 

 

>>>>> 前往查看8位设计师对此话题的具体回答 >>>>>



上行案例/ 侠客行-九号虾铺 品牌VIS  by 石昌鸿

《无染WURO 》品牌包装设计 by 你好大海品牌设计


 


Opportunities and challenges

工作中最大的困难是?


 

商业思维

独立设计师或是设计公司负责人,区别于职场设计师最大的特点应该就是商业思维了。一方面客户和领导对设计的要求是不同的,客户希望你的设计可以直接作用于商业结果,但领导更多只是希望你可以配合公司策略。另一方面,脱离了职场的设计师,要自己解决柴米油盐,不具备商业思维,就会直接出局。

 


瓶颈/未知/压力

这三项是不同的因素,但是把它们放在一起,代表着设计中最困难也最有趣的部分:挑战未知。做好设计需要的能力很多,每条成长路径上都会存在很多未知的歧途,如何管理好自己状态,始终以昂扬斗志去面对这些压力,是个永恒的话题。大家可以参考下面设计师们的回答和作品,去经历他们各自的成长。

 


人才/合作伙伴

设计是一个链接性的工作,通过链接上下游发生作用。尤其是外包项目,经常无法参与到最初的立项探讨中,导致面临一场场“残局”,所以就需要有强大抗压力和灵活性的伙伴来组成“特种部队”。几位设计公司的负责人,都一致表达了对人才的渴求,希望本文可以帮到他们。更希望大家可以从本文中得到一句一词的提示,让我们做出更棒的作品,拥有更好的客户。


 





<婷谷>向阳而生-品牌设计全案 by 力虎广告

66NORD官网设计 by 是北瓜呀

 


 

不好走的路上才有最好的风景,与大家共勉。


文章来源:站酷  作者:站酷策划

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

问卷发布后,如何整理体验反馈意见?

雪涛

本文从详细问题反馈分析及分类、体验问题价值优先级评估、意见反馈体验问题价值优先级评估等方面,帮你学会整理反馈意见。

问卷发布后,如何整理体验反馈意见?

问卷发布后,如何整理体验反馈意见?


文章来源:优设  作者:
vv酱•-• 

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务





本文从详细问题反馈分析及分类、体验问题价值优先级评估、意见反馈体验问题价值优先级评估等方面,帮你学会整理反馈意见。

问卷发布后,如何整理体验反馈意见?

问卷发布后,如何整理体验反馈意见?


文章来源:优设  作者:
vv酱•-• 

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务





如何设计更懂用户的搜索页

雪涛

搜索模块的逻辑原理
搜索模块的功能及流程分析

“搜索”是目前互联网产品中最常见也是最有必要的功能模块,搜索一方面帮助用户快速触达自己想要商品/服务/咨询等,另一方面作为平台的重要数据入口可以获取比较有价值的用户信息。

目前大部分产品的搜索模块后台逻辑和前端设计大同小异,但是不同的品类的产品又存在一些差异,从产品逻辑上分析基本原理如下图,

用户输入一个关键词,搜索系统根据用户的输入的信息,筛选出系统认为用户感兴趣的内容,同时按照系统认定的重要性进行排序展示。简单而言,搜索可以分为三步。


Step1:对用户输入信息的过滤

用户输入的关键词首先要经过逻辑层进行非法词过滤,错词纠错,特定跳转几步操作

非法词过滤显而易见就是用户输入的敏感词汇会根据后端的非法词库进行判断屏蔽,网上一般有现成的词库可以直接导入系统,不满足的后台可以根据产品属性及业务需求再进行维护扩充。错词纠错输入查询关键词,用户可能会输入成拼音、或者错别字,逻辑中有一套纠错词处理,当系统对比有错误时,会进行纠错处理,最终输出纠错后的结果进行输出。特定跳转是后端将特定词汇设置为特殊跳转,后端需要维护的映射库。比如双十一的时候,输入双十一可能会直接跳转到活动会场,而不是具体的某个商品。 


Step2:根据用户输入信息对内容进行分析解读

经过三种异常词库的过滤后,关键词会进入常规搜索词库。搜索词库是有限的,但是用户的输入却是没有限制的,怎么将无限制的搜索转化为有限的词库,并且匹配到对应的结果呢?这里需要一个关键的步骤即分词,分词是将一个比较长的关键字拆分成多个合理的比较短的关键字,经过分词非标准的关键词就被转化为标准的词库,而这些词就会对应一些搜索目标内容,但这些目标内容并不全展示给用户,展示给用户的也不一定完全跟用户搜索的相关,这里就有两个跟搜索相关的两个关键指标即准确率和召回率,准确率是指所有展示的内容中与用户搜索相关的内容的占比,召回率是指所有与用户搜索相关的内容中被展示出来内容的占比。准确率和召回率是一对存在矛盾的指标,搜索后台会有调和这两个数据相关的目标函数,后台搜索优化的目标就是提高准确率和召回率,让后台与用户搜索相关的内容都能尽可能展示出来。


Step3:对解读后的结果进行排序

搜索系统标准词库都有与之现关联的具体内容,每个具体内容是否包含关键词决定是否展示这些内容,同时根据关键词的权重给展示的内容一个分数,最终根据每个内容的分数进行排序,不同平台的关键词权重不一样,这属于平台运营的机密,权重的高低直接影响目标内容的排序,也直接影响平台的销售额和用户体验。


在前端设计看来一个简单的搜索框,但是后端却需要多层逻辑的判断和输出,最终实现业务与体验的最优化。以上只是作为设计人员的简单总结,方便我们做设计的时候更好跟研发人员沟通。 


从前端功能流程上分析搜索模块可以拆分为启动搜索-输入内容-获取结果

启动搜索

目前大部分的搜索入口分为顶部搜索框/底部导航/局部图标,产品的属性决定搜索功能的重要级,从而影响搜索入口的样式,另外需要明确搜索在当前页面中的的优先级从而明确搜索的样式,底部是app的一个最重要位置,将搜索功能放在底部导航一方面突出搜索功能的重要级别,但相对于放在首页顶部又不至于影响首页的流量分发。页面局部设置搜索图标,相对搜索功能的重要级会低一些。顶部搜索一般是吸顶悬停,用户对搜索的依赖性很高,此类搜索入口的功能也最完整,对设计的要求也最高。 


完整的搜索框从功能点上分包括,扫码/语音/图片/文本等几种搜索能力,设计时需明确搜索框自带的功能点有哪些,功能点的优先级和关联性,总结发现一般电商类服务类产品会比社交信息类产品的搜索更为明显且搜索的功能点更多一些。


输入内容

在输入内容这个阶段,用户可能进行的操作是是输入(语音/文本/图片等)功能,选择联想关键词,清除/修改文本功能信息展示上一般有搜索历史,搜索维度,推荐搜索,默认提示词等,归纳起来基本为关联搜索,引导搜索,细分搜索这三种,目的都是一方面为了满足用户高效搜索的需求,另一方面实现平台营销策略。设计要兼顾这两点,在满足业务的同时给用户更好的搜索体验。

以上搜索返回流程中两大主流平台有一些差异的原因

第一种:搜索结果页—搜索启动页-搜索入口,可能的原因:

            符合移动端的流程可逆的操作习惯

            营销需要,返回至搜索推荐页,多一层页面的曝光机会

            便于用户触发再次搜索的行为

第二种:搜索结果页—搜索入口,可能的原因:

            用户用取消操作,表达的是取消搜索模块,故返回入口,同时也能再次调起

            缩短返回路径,更加高效,注重高效的操作体验 


获取结果

平台属性不同搜索结果页的目标内容会有区别,除了目标内容的输出外,搜索结果页会对应的展示筛选条件和推荐,此时需要做到的是筛选维度清晰,业务核心明确,平台特点突出

在这个阶段用户的目的是在目标信息/商品/服务中进行对比选择,获得自己最想要(从平台角度则是推荐给用户)的。在设计搜索结果页的目标内容时,需要注意信息层级的展示,比如电商平台最突出价格,而咨询分享类产品可能要突出关注度热度等。

大部分平台都有自己的rank逻辑,rank逻辑是根据商品的相关因素综合起来形成的一种排序逻辑,比如电商产品中的转化率/销量/点击率等,而且会根据产品的不同阶段去优化升级,目的是可以输出更符合用户心理的排序,从而更精准高效的满足用户,提升产品体验。


搜索异常状态

搜索异常的状态一般有三种,1.搜索结果为空;2.智能纠错;3.网络异常等,

搜索结果为空时一般需要空态图和文案说明和引导,缓解用户需求没有达成的心情。智能纠错,是在用户输入内容上的一种提示或纠正,如果用户输入的内容有问题或不够标准,在搜索结果中会能给最贴切的搜索结果。网络异常,需要考虑的是提示是在哪个阶段告知用户,用户在没有网络的情况下仍然可以调起搜索启动页,此时提示用户网络异常会比在搜索结果页告知用户的体验要好。


文章来源:站酷  作者:周沐Zhoumu 

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


app界面赏析 ——— 北京蓝蓝设计 移动端UI设计资源分享(二十)

前端达人

移动互联网的迅速崛起,让移动网页,移动客户端越来越重要,客户端的页面设计也是一门很大的学问。科技迅速发展的今手机屏幕的尺寸越来越放大化,但却始终 很有限,因此,在APP的界面设计中,精简是一贯的准则。这里所说的精简并不是内容上尽可能的少量,而是要注重重点的表达。在视觉上也要遵循用户的视觉逻 辑,用户看着顺眼了,才会真正的喜欢。


接下来为大家分享精美的app UI设计案例:


jhk-1617329495749.jpgjhk-1617329712960.jpgjhk-1617329746696.jpgjhk-1618475057961.pngjhk-1618475082684.pngjhk-1618475178817.jpg



--手机appUI设计--

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服



  更多精彩文章:

       手机appUI界面设计赏析(一)

       手机appUI界面设计赏析(二)

       手机appUI界面设计赏析(三)

       手机appUI界面设计赏析(四)

       手机appUI界面设计赏析(五)

       手机appUI界面设计赏析(六)

       手机appUI界面设计赏析(七)

       手机appUI界面设计赏析(八)

       手机appUI界面设计赏析(九)

        手机appUI界面设计赏析(十)

       手机appUI界面设计赏析(十一)

       手机appUI界面设计赏析(十二)

        手机appUI界面设计赏析(十三)

       手机appUI界面设计赏析(十四)

       手机appUI界面设计赏析(十五)

       手机appUI界面设计赏析(十六)

       手机appUI界面设计赏析(十七)

      手机appUI界面设计赏析(十八)

      手机appUI界面设计赏析(十九)





vue传值方式总结 (十二种方法)

前端达人

一.父传子传递

(1)在父组件的子组件标签上绑定一个属性,挂载要传输的变量
(2)在子组件中通过props来接受数据,props可以是数组也可以是对象,接受的数据可以直接使用 props: [“属性 名”] props:{属性名:数据类型}
代码示例:

//父组件
<template>
  <div>
    <i>父组件</i>
    <!--页面使用-->
    <son :data='name'></son> 
  </div>
</template>

<script>
import son from "./son.vue";//导入父组件
export default {
  components: { son },//注册组件
  name: "父组件",
  data() {
    return {
      name: "Frazier", //父组件定义变量
    };
  },
};
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
//子组件
<template>
  <div>{{data}}</div>
</template>

<script>
export default {
components: { },
  name: '子组件',
  props:["data"],
};
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

二.子传父传递

(1)在父组件的子组件标签上自定义一个事件,然后调用需要的方法
(2)在子组件的方法中通过 this.$emit(“事件”)来触发在父组件中定义的事件,数据是以参数的形式进行传递的
代码示例:

//父组件
<template>
  <div>
    <i>父组件</i>
    <!--页面使用-->
    <son @lcclick="lcclick"></son>//自定义一个事件
  </div>
</template>

<script>
import son from "./son.vue"; //导入父组件
export default {
  components: { son }, //注册组件
  name: "父组件",
  data() {
    return {};
  },
  methods: {
    lcclick(){
      alert('子传父')
    }
  },
};
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
//子组件
<template>
  <div>
    <button @click="lcalter">点我</button>
  </div>
</template>

<script>
export default {
components: { },
  name: '子组件',
  methods: {
    lcalter(){
      this.$emit('lcclick')//通过emit来触发事件
    }
  },
};
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

三.兄弟组件通信(bus总线)

(1)在src中新建一个Bus.js的文件,然后导出一个空的vue实例
(2)在传输数据的一方引入Bus.js 然后通过Bus.e m i t ( “ 事 件 名 ” , " 参 数 " ) 来 来 派 发 事 件 , 数 据 是 以 emit(“事件名”,"参数")来来派发事件,数据是以emit(,"")emit()的参 数形式来传递
(3)在接受的数据的一方 引入 Bus.js 然后通过 Bus.$on(“事件名”,(data)=>{data是接受的数据})
图片示例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四.ref/refs(父子组件通信)

(1)ref 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,
(2)可以通过实例直接调用组件的方法或访问数据。也算是子组件向父组件传值的一种
代码示例:

//父组件
<template>
  <div>
    <button @click="sayHello">sayHello</button>
    <child ref="childForRef"></child>
  </div>
</template>
<script>
import child from './child.vue'
  export default {
    components: { child },
    data () {
      return {
        childForRef: null,
      }
    },
    mounted() {
      this.childForRef = this.$refs.childForRef;
      console.log(this.childForRef.name);
    },
    methods: {
      sayHello() {
        this.childForRef.sayHello()
      }
    }
  }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
//子组件
<template>
  <div>child 的内容</div>
</template>
<script>
export default {
  data () {
    return {
      name: '我是 child',
    }
  },
  methods: {
    sayHello () {
      console.log('hello');
      alert('hello');
    }
  }
}
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

五.Vuex通信

组件通过 dispatch 到 actions,actions 是异步操作,再 actions中通过 commit 到 mutations,mutations 再通过逻辑操作改变 state,从而同步到组件,更新其数据状态
代码示例:

//父组件
template>
  <div id="app">
    <ChildA/>
    <ChildB/>
  </div>
</template>
<script>
  import ChildA from './ChildA' // 导入A组件
  import ChildB from './ChildB' // 导入B组件
  export default {
    components: {ChildA, ChildB} // 注册组件
  }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
//子组件A
<template>
 <div id="childA">
   <h1>我是A组件</h1>
   <button @click="transform">点我让B组件接收到数据</button>
   <p>因为点了B,所以信息发生了变化:{{BMessage}}</p>
 </div>
</template>
<script>
 export default {
   data() {
     return {
       AMessage: 'Hello,B组件,我是A组件'
     }
   },
   computed: {
     BMessage() {
       // 这里存储从store里获取的B组件的数据
       return this.$store.state.BMsg
     }
   },
   methods: {
     transform() {
       // 触发receiveAMsg,将A组件的数据存放到store里去
       this.$store.commit('receiveAMsg', {
         AMsg: this.AMessage
       })
     }
   }
 }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
//子组件B
<template>
 <div id="childB">
   <h1>我是B组件</h1>
   <button @click="transform">点我让A组件接收到数据</button>
   <p>点了A,我的信息发生了变化:{{AMessage}}</p>
 </div>
</template>

<script>
 export default {
   data() {
     return {
       BMessage: 'Hello,A组件,我是B组件'
     }
   },
   computed: {
     AMessage() {
       // 这里存储从store里获取的A组件的数据
       return this.$store.state.AMsg
     }
   },
   methods: {
     transform() {
       // 触发receiveBMsg,将B组件的数据存放到store里去
       this.$store.commit('receiveBMsg', {
         BMsg: this.BMessage
       })
     }
   }
 }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
//vuex
import Vue from 'vue'
 import Vuex from 'vuex'
 Vue.use(Vuex)
 const state = {
   AMsg: '',
   BMsg: ''
 }

 const mutations = {
   receiveAMsg(state, payload) {
     // 将A组件的数据存放于state
     state.AMsg = payload.AMsg
   },
   receiveBMsg(state, payload) {
     // 将B组件的数据存放于state
     state.BMsg = payload.BMsg
   }
 }

 export default new Vuex.Store({
   state,
   mutations
 }) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

六.$parent

通过parent可以获父组件实例 ,然 后通过这个实例就可以访问父组件的属 性和方法 ,它还有一个兄弟parent可以获父组件实例,然后通过这个实例就可以访问父组件的属性和方法,它还有一个兄弟parent可以获父组件实例,然后通过这个实例就可以访问父组件的属性和方法,它还有一个兄弟root,可以获取根组件实例。
代码示例:

// 获父组件的数据
this.$parent.foo

// 写入父组件的数据
this.$parent.foo = 2

// 访问父组件的计算属性
this.$parent.bar

// 调用父组件的方法
this.$parent.baz()

//在子组件传给父组件例子中,可以使用this.$parent.getNum(100)传值给父组件。 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

七.sessionStorage传值

sessionStorage 是浏览器的全局对象,存在它里面的数据会在页面关闭时清除 。运用这个特性,我们可以在所有页面共享一份数据。
代码示例:

// 保存数据到 sessionStorage
sessionStorage.setItem('key', 'value');

// 从 sessionStorage 获取数据
let data = sessionStorage.getItem('key');

// 从 sessionStorage 删除保存的数据
sessionStorage.removeItem('key');

// 从 sessionStorage 删除所有保存的数据
sessionStorage.clear(); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注意:里面存的是键值对,只能是字符串类型,如果要存对象的话,需要使用 let objStr = JSON.stringify(obj) 转成字符串然后再存储(使用的时候 let obj = JSON.parse(objStr) 解析为对象)。
推荐一个库 good-storage ,它封装了sessionStorage ,可以直接用它的API存对象

//localStorage
 storage.set(key,val) 
 storage.get(key, def)
//sessionStorage
 storage.session.set(key, val)
 storage.session.get(key, val) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

八.路由传值

使用问号传值
A页面跳转B页面时使用 this.r o u t e r . p u s h ( ’ / B ? n a m e = d a n s e e k ’ ) B 页 面 可 以 使 用 t h i s . router.push(’/B?name=danseek’) B页面可以使用 this.router.push(/B?name=danseek)B使this.route.query.name 来获取A页面传过来的值
上面要注意router和route的区别
使用冒号传值
配置如下路由:

{
    path: '/b/:name',
    name: 'b',
    component: () => import( '../views/B.vue')
 }, 
  • 1
  • 2
  • 3
  • 4
  • 5

在B页面可以通过 this.$route.params.name 来获取路由传入的name的值

使用父子组件传值
由于router-view本身也是一个组件,所以我们也可以使用父子组件传值方式传值,然后在对应的子页面里加上props,因为type更新后没有刷新路由,所以不能直接在子页面的mounted钩子里直接获取最新type的值,而要使用watch

<router-view :type="type"></router-view>

// 子页面
props: ['type']
watch: {
       type(){
           // console.log("在这个方法可以时刻获取最新的数据:type=",this.type)
       },
}, 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

九.祖传孙 $attrs

正常情况下需要借助父亲的props作为中间过渡,但是这样在父亲组件就会多了一些跟父组件业务无关的属性,耦合度高,借助$attrs可以简化些,而且祖跟孙都无需做修改
祖组件:

<template>
    <section>
        <parent name="grandParent" sex="男" age="88" hobby="code" @sayKnow="sayKnow"></parent>
    </section>
</template>

<script>
    import Parent from './Parent'
    export default {
        name: "GrandParent",
        components: {
          Parent
        },
        data() {
            return {}
        },
        methods: {
          sayKnow(val){
            console.log(val)
          }
        },
        mounted() {
        }
    }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

父组件

template>
  <section>
    <p>父组件收到</p>
    <p>祖父的名字:{{name}}</p>
    <children v-bind="$attrs" v-on="$listeners"></children>
  </section>
</template>

<script>
  import Children from './Children'

  export default {
    name: "Parent",
    components: {
      Children
    },
    // 父组件接收了name,所以name值是不会传到子组件的
    props:['name'],
    data() {
      return {}
    },
    methods: {},
    mounted() {
    }
  }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

子组件

<template>
  <section>
    <p>子组件收到</p>
    <p>祖父的名字:{{name}}</p>
    <p>祖父的性别:{{sex}}</p>
    <p>祖父的年龄:{{age}}</p>
    <p>祖父的爱好:{{hobby}}</p>

    <button @click="sayKnow">我知道啦</button>
  </section>
</template>

<script>
  export default {
    name: "Children",
    components: {},
    // 由于父组件已经接收了name属性,所以name不会传到子组件了
    props:['sex','age','hobby','name'],
    data() {
      return {}
    },
    methods: {
      sayKnow(){
        this.$emit('sayKnow','我知道啦')
      }
    },
    mounted() {
    }
  }
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

十.孙传祖使用$listeners

文字内容同第九个

祖组件

<template>
  <div id="app">
    <children-one @eventOne="eventOne"></children-one>
    {{ msg }}
  </div>
</template>
<script>
import ChildrenOne from '../src/components/children.vue'
export default {
  name: 'App',
  components: {
    ChildrenOne,
  },
  data() {
    return {
      msg: ''
    }
  },
  methods: {
    eventOne(value) {
      this.msg = value
    }
  }
}
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

父组件

<template>
  <div>
    <children-two v-on="$listeners"></children-two>
  </div>
</template>

<script>
import ChildrenTwo from './childrenTwo.vue'

export default {
  name: 'childrenOne',
  components: {
    ChildrenTwo
  }
}
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

子组件

<template>
  <div>
    <button @click="setMsg">点击传给祖父</button>
  </div>
</template>

<script>
export default {
  name: 'children',
  methods: {
    setMsg() {
      this.$emit('eventOne', '123')
    }
  }
}
</script> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

十一.promise传参

promise 中 resolve 如何传递多个参数

//类似与这样使用,但实际上后面两个参数无法获取
promise = new Promise((resolve,reject)=>{
    let a = 1
    let b = 2
    let c = 3
    resolve(a,b,c) 
})
promise.then((a,b,c)=>{
    console.log(a,b,c)
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

resolve() 只能接受并处理一个参数,多余的参数会被忽略掉。
如果想多个用数组,或者对象方式。。
数组

promise = new Promise((resolve,reject)=>{
    resolve([1,2,3]) 
})
promise.then((arr)=>{
    console.log(arr[0],arr[1],arr[2])
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

对象

promise = new Promise((resolve,reject)=>{
    resolve({a:1,b:2,c:3}) 
})
promise.then(obj=>{
    console.log(obj.a,obj.b,obj.c)
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

十二.全局变量

定义一个全局变量,在有值的组件直接赋值,在需要的组件内直接使用就可以了。


转自:csdn 作者:Frazier_梁超


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

设计师必须学会的图标技巧

周周


本文从图标的起源、定义到基础的设计方法总结无一不包,还有大量的案例帮你理解布尔运算,是新人设计师学习图标设计的必备干货!

一、图标的定义

一说到图标,我想您一定会觉得非常熟悉。图标,也称为 icon 或 picto,是指有明确含义的图形视觉语言。那么当我们一提起图标设计,您的脑中会想起哪个图标来呢?有可能您想起的是微信APP ,由两个白色气泡组成的启动图标,或者是我们每天使用的 APP 中的那些返回、关闭等系统图标,也可能是商场导视里的卫生间图标等。没错,图标的形式有很多种,它可以应用在很多场景中,并且表现方式非常丰富:有线的、有面的、也有拟物的等等。图标的历史可以追溯到象形文字(Pictogram),我们的祖先在发明文字之前就使用图标记录一天的生活了。听着是不是不可思议呢?从亘古时代的象形文字开始,我们的祖先就偏爱使用这种抽象的图形来表达意思了。在平面设计领域的商标其实也是一种图标,平面设计里的视觉导视(例如卫生间的图标)也有图标的应用,所以图标在我们的生活中应用非常广泛。

万字干货!设计师必须学会的图标技巧

△ 生活中随处可见的图标

在计算机时代,从80年代的施乐公司界面中的单色图标开始,图标就开始出现在屏幕之中了,图标较编程语言更容易被大众理解。到了后来从 iMac 到 iPhone 引领的拟物图标更是开启了一个绚丽的图标设计时代。拟物时代盛行也带来了一些麻烦:拟物图标的质感、光影会吸引走用户的注意力,我们称之为「视觉噪音」。于是 UI设计师开始探索更新的表现形式来设计界面中的图标。扁平图标发展史上有过很多次尝试,比如微软引领的 Metro风格中的图标设计和 Google 引领的扁平设计风格中的长投影风格图标,但由于它们表现形式太过于抽象、缺乏情感的传递,并没有获得用户的垂青。而我们现在界面设计中的图标设计是一种「轻拟物」或「微扁平」的风格:在面积比较小的区域我们使用扁平图标或线形图标;在面积比较大的区域我们会使用加入渐变甚至轻质感的图标。(关于图标风格的变化,可以参考这个网站:https://historyoficons.com)。

万字干货!设计师必须学会的图标技巧

△ 不同的图标设计风格

如今我们界面中的图标可谓非常丰富了,如果根据 Material Design 对图标的分类,UI设计中的图标可以分为带有品牌属性和特性的产品图标、有功能指示作用的系统图标两种图标,下面我们将针对于这两种图标进行研究。

二、产品图标

万字干货!设计师必须学会的图标技巧

产品图标是我们在设计界面的时候体现品牌调性和特性的图标。通过产品图标,用户就可以大概感知这个产品主要是做什么的。比如微信的产品图标是两个对话气泡,暗示了这是一款社交APP;再比如 ofo 的产品图标是字母ofo 的组合,同时也是一辆自行车,这暗示了这款产品是共享单车的APP;再比如 KEEP 的字母「K」的图标,像极了一个在抬腿做运动的人,暗示了这是一个运动APP。

同时有些产品也依靠自身已经在用户心中产生的品牌来直接设计产品图标,比如淘宝APP 的产品图标就是一个「淘」字;支付宝的产品图标就是一个「支」字。优秀的产品图标都会在我们心中打上一个烙印,当我们看到这些图形、配色时,脑中会立即想起来它们的功能和特点。产品图标除了在手机屏幕中作为启动图标,也会出现在闪屏、情感化设计、「关于我们」界面等场景中,所以也要有一定的灵活性,在设计上要以简单、大胆、友好的方式传达产品的核心理念和意图。产品图标很类似在企业识别系统(VI)里的 logo,需要让用户一眼看到它就能够与脑中的产品相关联。所以设计一个优秀的产品图标对于任何产品来说都是非常重要的。

1. 风格

产品图标有不同的风格,这些风格有可能很拟物,也有可能很扁平;有可能很抽象,也可能很具象。通过不同的设计风格可以更加标新立异,从而被用户记住。让用户记住我们的图标真是一件非常重要的事儿,要知道,每个手机都像是一把瑞士军刀,它有无数个功能,而我们的产品只是万种功能中的一个。用户不可能记住手机里所有的 APP 都是什么,所以能在第一时间取得好感和记忆非常重要,产品图标设计得好看并且容易被人记住就成了非常重要的任务。产品图标的主要风格有以下几种。

文字风格

文字是最直白的信息,而且不容易被曲解。所以很多国内的产品都会使用文字来作为自己的产品图标。比如:支付宝、淘宝、今日头条、OFO、爱奇艺、知乎、网易新闻、毛豆新车等。这么做也有它的问题,比如文字给人美的感受不如图形,因为文字需要阅读而不是观察。并且移动端设备都会在启动图标之下加上一行辅助文字,如果图标上的文字和下面的辅助文字完全重合,会显得像介绍了自己两遍一样。如果您决意要使用文字作为产品图标,且是中文的话,那么一定要记得文字最好为1-2个,并且不应该是产品的全称。如果是英文的话,最好是首字母而不是产品全称。当然不管是中文还是英文都需要选择合适气质的字体并做一定的变化。

单读:单读是一个偏文艺的阅读产品,所以产品图标使用了黑白配色和两个非常有文艺气息的宋体繁体字,这样的设计符合产品调性,传递给用户一种产品的文艺气息。

今日头条:今日头条是一款优秀的新闻APP。它的图标非常直白,一张报纸上有红色的头条标题,头条使用了非常粗的黑体字,非常显眼。

淘宝:淘宝采用了一个俏皮的「淘」字作为 icon 的主要元素,并且背景颜色是令人兴奋和刺激的橘黄色,凸显了电商属性。并且这个字使用了很久,用户对此有一定的品牌认知。

爱奇艺:爱奇艺的 icon 采用了英文字母iQIYI 和上下边框相组合的形式。整体看来像是一个电视机,强调了品牌属性和功能,并且使用了在视频领域非常有识别性的绿色,让人一看便知这是爱奇艺了。

万字干货!设计师必须学会的图标技巧

△ 单读、今日头条、淘宝、爱奇艺的产品图标

如果您的品牌使用英文作为产品图标,我们在设计的时候要格外注意英文字母之间的正负空间关系以及不同西文字体的不同气质。

ONE:虽然是中文产品,但是 ONE 的icon 显得非常的高端和小众。ONE 三个字母的正负空间关系做了微调,并且选择了无衬线字体来体现时尚感。下面的小字是一个 slogan,并且和 ONE 的宽度一致。

Pinterest:Pinterest 的产品图标是一个手写体的P,并且用红色圆形作为陪衬。这样一个字母作为 ICON 的好处就是方便用户记忆。

HULU:HULU 是一个国外视频产品,它的产品图标颜色很鲜艳,字母本身有韵律感,所以没有做过多的设计。

Facebook:作为一个社交产品,Facebook 的产品图标同样采用了一个字母代表较长的单词。

万字干货!设计师必须学会的图标技巧

△ ONE、Pinterest、HULU、Facebook的产品图标

正负形与隐喻风格

图标的设计可以使用正负形和隐喻,来让图标更加有耐人寻味的看点。

抖音:抖音的产品图标是一个音符,但是不知道大家是否发现,下面圆形的负空间也是一个音符,所以显得非常巧妙。为了增加动感还加了红和蓝绿色的类似3D的动感效果。

Keep:Keep 产品图标是一个K,但是同时也是一个人抬着腿正在锻炼。

Skillshare:Skillshare 是一个技能交换平台,第一眼看是两个手像太极一样交换着技能,同时也是该产品的首字母:S。

万字干货!设计师必须学会的图标技巧

△ 抖音、Keep、Skillshare、OFO的产品图标

折纸风格

折纸的效果会让人感觉很立体,所以很多产品也选择了折纸效果(比较扁平的手法)来设计产品图标。

Calendar:这个产品的产品图标是一个正在翻页的日历,非常简洁明了。

Snapseed:除了扁平的设计之外,使用了长投影的设计风格。这个长投影也是扁平化的设计。

Netflix:Netflix 的产品图标是该产品的首字母N,这个 N 用了一些阴影来表示立体感。

绘声绘影:同样是用了长投影和折纸效果,显得非常清新。

万字干货!设计师必须学会的图标技巧

△ Calendar、Snapseed、Netflix、绘声绘影的产品图标

填充图标风格

产品图标使用填充图标风格是非常合适的。填充图标风格具有简洁和识别性强的特点。这种 ICON 的可扩展性更高,比如在一些特殊节日时可以用手绘、拼贴等形式来做辅助图形。所以很多公司都钟爱填充图标风格。

Lucking:这是一个线上咖啡外卖的产品。它的 APP图标使用了一个鹿回头的造型。这个鹿造型简洁,非常有识别性。

Tinder:这是一个国外社交APP,通过一个火的填充图标让人第一时间记住这个产品。

youtube:这是国外著名视频APP,它的产品图标同样使用了填充图标风格,是一个有电视机隐喻的圆角矩形,并且中心是一个播放键,简明扼要地说明了这个产品的功能。

Twitter:国外著名社交APP,它的 icon 同样使用了填充图标风格,非常简洁好记。

万字干货!设计师必须学会的图标技巧

△ Lucking、Tinder、Youtube、Twitter的产品图标

线性风格

由于目前设计流行趋势,很多产品图标都会采用扁平的设计风格。扁平除了填充的图标之外,还有一种非常流行的形式——线性风格。线性风格一定要注意不要太细,因为手机和电脑设计环境显示尺寸不同,如果我们做得太细,那么在手机上看会非常尖锐,显得不太好点击。

Airbnb:Airbnb 的背景是一个微渐变,线性风格是一个曲线组成的 A,同时也是一个小蜜蜂。

LOFTCam:为了凸显文艺产品调性,使用了偏细的线条,同时使用了两种主题色。

NextDay:同样非常文艺的产品,使用了比较抽象的手法。这个 ICON 是一个牛奶,突出了这个产品必须今天看,否则就如牛奶一样会过期。

VUE:这是一个摄影产品,同样应用了黑色的微渐变,前面是非常前卫的45度长短不同的线。

万字干货!设计师必须学会的图标技巧

△ Airbnb、LOFTCam、NextDay、VUE的产品图标

LOWPOLY风格

我曾介绍过 LOWPOLY 这种设计风格,这种风格如果应用在产品图标上同样非常抢眼,因为用户的手机上可能安装了很多 APP,那么第一眼扫过去一定会注意到最亮眼的图标。而 LOWPOLY 因为本身造型的独特性非常吸引眼球。当然 LOWPOLY 也有它的问题,比如容易让图标失去细节等,所以很多产品图标都是使用 LOWPOLY 作为图形的背景。

潮自拍:潮自拍使用了暖色邻近色渐变的 LOWPOLY 作为背景,前景使用了一个很潮的S。

潘通色:潘通色本身的最大特征就是色卡,所以使用了 LOWPOLY 的形式。

美妆相机:通常 LOWPOLY 的形式是方块,而美妆相机使用了三角作为基础元素,很特别。

人人:人人的产品图标使用了不同的矩形斜度45°,增加了设计的速度感。

万字干货!设计师必须学会的图标技巧

△ 潮自拍、潘通色、美妆相机、人人的产品图标

微渐变风格

微渐变也是非常常见的表现手法。在拟物被扁平替代以后,我们会发现无法表达空间上的 Z轴。所以用轻微的渐变表现图片的深度非常流行。我认为微渐变可能是众多图标设计风格中最有竞争力的一种。

每日优鲜:每日优鲜在背景上用了很多炫彩的圆球,由于促销时段在原有图标上增加了一个双十一的小标识,在手机中非常抢眼。

陌陌:陌陌图标如果设计成扁平你还会注意到它吗?使用线性图标会使得图标厚度感不够,而微渐变可以非常好地解决这个问题。

全民K歌:使用了紫红色的渐变来塑造一只鹦鹉,如果遇到其他使用场景可以使用扁平版本,这样会让产品图标的使用更加灵活。

Mindnode:这款脑图软件的产品图标使用了三组邻近色的渐变,同时使用了非常微妙的阴影。

万字干货!设计师必须学会的图标技巧

△ 每日优鲜、陌陌、全民K歌、Mindnode的产品图标

卡通风格

卡通风格的产品图标会让用户更有好感,所以我们可以为产品设计一个可爱的卡通角色。好多决策者会认为卡通是一种低龄的审美,其实是错误的。卡通可以说是一种通吃的风格,比如腾讯就是以一个企鹅作为品牌形象开始拓展自己的版图。而卡通本身有不同的风格,比如拟物类的卡通、扁平类的卡通等,也会给人不同的感受。所以如果我们的产品要使用卡通作为产品图标,最好以目标用户群的喜好作为标尺。

开心消消乐:开心消消乐是一个休闲游戏,游戏类APP 的产品图标通常是使用拟物风格,这样可以最大地吸引玩家的注意力和兴趣。

映客:映客是直播APP,通常用户年龄不是很大,所以使用了一个很可爱的猫头鹰作为产品图标。

Waze:Waze 的产品图标不仅可爱而且突出了 Waze 的地图查找功能。

BOO!:BOO! 是一个儿童社交产品,用户比较低龄,所以更适合使用可爱的卡通作为图标。

万字干货!设计师必须学会的图标技巧

△ 开心消消乐、映客、Waze、BOO!的产品图标

2. 图标的网格和参考线

如果我们想设计一个小图标,那么我们可以把画布放大到400%来设计。同时可以使用网格和参考线来作为我们设计的辅助。网格在很多软件里都有,比如在 Illustrator 中点击视图 > 网格,即可开启网格了。参考线模板则需要下载第三方设计的模板,比如 Material Design 的参考线模板就有正方形、圆形、圆形和长方形结合等不同形式。如果对齐模板中的形状,即可得到面积相等的长方形、正方形、圆形。这对我们构建视觉上面积相等的图标很有益处。

万字干货!设计师必须学会的图标技巧

△ 网格和参考线

万字干货!设计师必须学会的图标技巧

△ 不同形状的网格布局

万字干货!设计师必须学会的图标技巧

△ 在网格的辅助下可以设计出大小均衡的图标

3. 尺寸

苹果启动图标尺寸

苹果需要很多尺寸的图标用在不同的场景上,比如说在网页端打开iTunes会使用512px的大图标,而在手机、iPad桌面上的图标大小也不同。除了尺寸不同,这些图标的圆角也有不同的数值。为了简化这部分的难度,苹果为开发者提供了模板,有了模板就不用记那么多东西啦。苹果官方HIG 下载的这套资源中,有 Template-AppIcons-iOS 这个文件,这个文件提供了 PS、Sketch、XD等不同格式。我比较推荐使用 PS 的格式。

打开这个文件,用我们自己设计的启动图标替换掉任意智能对象里的内容。那么打开智能对象就是一个1024x1024px的矩形画布,把我们的产品图标放在这里,保存这个智能对象再关闭它就可以了。这时,你会发现所有尺寸的图标都变成了我们的图标。然后我们把背景隐藏,切出这些图标即可。如果是 AI 完成的产品图标可以直接 Ctrl+C 然后在 PS智能对象中 Ctrl+V复制过来就行。

万字干货!设计师必须学会的图标技巧

△ Template-AppIcons-iOS

安卓启动图标尺寸

安卓启动图标同样需要很多尺寸,主流是需要:1024x1024px、512x512px、144x144px、96x96px、72x72px、48x48px这六种。我们提供给程序员的是直角的矩形,然后程序员通过代码进行切割变成圆角图标。在这里我也做了一个智能对象的模板送给您,只要替换其中的智能对象图像,换成您的1024x1024px图标保存即可。

万字干货!设计师必须学会的图标技巧

△ 安卓图标模板

4. 设计流程

设计产品图标前,首先我们需要找一些和产品气质相符的图片制作情绪板。通过情绪板我们可以感受到产品的调性,然后我们从中提取一些形状和色彩作为我们产品图标的主要造型。这里我举我的产品每日名画的例子,每日名画是一个美术方面的APP,所以我找了一些和美术相关的图片。

万字干货!设计师必须学会的图标技巧

△ 关于美术的情绪板

下面我开始在 AI 设计产品图标了。我建立了一个1024x1024px的画布,然后根据卢浮宫前的金字塔建筑设计了一枚抽象的产品图标,它内在的符号是:带领大家走进艺术的殿堂。同时我也增加了一些自己对美术的含义,如艺术来源于生活高于生活等。这些都写在了设计说明中。

万字干货!设计师必须学会的图标技巧

△ 在Illustrator中设计产品图标

然后我给这枚图标加入了蒙德里安的配色,增加产品的艺术感,并最终完成产品图标的设计。这个图标也可以作为该产品的企业形象(VIS),将来产品周边都可以使用这个图形。

万字干货!设计师必须学会的图标技巧

△ 最终定稿的图标

由于产品会首先上线到苹果设备上,所以我下面把 AI 绘制的产品图标全选复制,然后打开图标模板中的智能对象(双击图标模板中智能对象图层的缩略图),粘贴过来。粘贴的时候系统会提示选择粘贴过来的方式,这里我们选择:智能对象。然后保存并关闭智能对象,这时回到模板PSD 中,就看到了这个效果。

万字干货!设计师必须学会的图标技巧

△ 替换了模板中智能对象的效果

接下来隐藏背景图层,然后按下键盘上的 ctrl+Shift+Alt+S,调出存储为Web所用模式,选择保存到桌面上,格式选择仅图片。关闭 PS,打开桌面上的文件夹,就看到图标被我们工整地切好了。

万字干货!设计师必须学会的图标技巧

△ 产品图标的切图文件

三、系统图标

万字干货!设计师必须学会的图标技巧

第二种图标被称为系统图标。系统图标指的是担负着一定功能和含义的图形,一般来说需要像文字一般地被人迅速理解,所以表达方式上不适合特别复杂。比如微信底部四个系统图标:「微信」、「通讯录」、「发现」、「我」就使用了比较简洁的线性风格。

当然系统图标也不一定要做的非常无趣,比如我们常用的58同城APP 中就有大量的系统图标,在保证识别性的前提下使用了多彩的颜色和不同的造型,显得非常活泼。所以系统图标同样可以做得有趣和多样,前提是保证图标的可识别性。

1. 风格

万字干货!设计师必须学会的图标技巧

填充图标(Filled icon)

填充图标是以面为主要表现形式的图标。在微信APP 底部的 tab栏中,未选中的图标是线性图标,而选中态则是填充图标,并且会变成较为鲜亮的颜色暗示用户该功能被选中了。填充态图标占用的面积要比线性图标多,所以更加显眼。实际上,在最新的苹果设计规范中,苹果也建议开发者在 APP底部 Tab栏中全部使用填充图标,点击态通过改变填充图标的颜色进行区别。这是因为填充图标看上去像可点击的。

万字干货!设计师必须学会的图标技巧

△ 图为填充图标

线性图标(Outlined icon)

线性图标的表现形式是线条,在系统图标里通常是由统一粗细的线条组成。这里可能很多新朋友不明白为什么要使用统一的粗细,这是因为通常系统图标并非单一出现,而是成组使用。比如微信底部的四个 tab图标、网易云音乐顶部导航栏的图标等。在一个场景下的几个同等重要的图标,如果线条粗细不一致,很容易造成它们存在权重上差异的感觉。所以我们在绘制线性图标时,线条通常都会使用统一的粗细。

万字干货!设计师必须学会的图标技巧

△ 图为线性图标

圆角图标(Rounded icon)

无论是线性还是填充的图标,在图标的边角处使用圆角都是圆角图标风格。圆角图标的好处就是让人觉得很温柔,可以非常舒适地点击它。所以很多产品的图标都会使用圆角图标。

万字干货!设计师必须学会的图标技巧

△ 图为圆角图标

尖角图标(Sharp icon)

无论是线性还是填充的图标,在图标的边角处使用尖角都是尖角图标风格。尖角图标的好处是让人感觉到有棱角,视觉上会多凝视几秒。并且给人以正式的感觉,所以像银行、办公等APP 中都较多地使用尖角图标风格。

万字干货!设计师必须学会的图标技巧

△ 图为尖角图标

断线图标(Breaking Lines)

如果我们的线性图标显得太死板,我们可以使用断线这种方式来让它变得俏皮。断线图标就是线性图标的一种风格变化,它的特点就是在线条中出现断口。但是这个断口并不是看起来那么简单,它得遵循几个规则:第一,断线开口只有一个,否则图标会无法识别;第二,断线开口位置不应该在中心线上;第三,断线开口尽量在转折处;第四,断线不应该太过于琐碎。

万字干货!设计师必须学会的图标技巧

△ 土豆APP的标签栏使用了断线的风格

双调图标(Two-Tone icon)

如果我们把图标简单地分为线性图标和填充图标,是不是太无聊了?比如我们要设计一个 iOS平台的 APP,它的底部Tab栏就一定是未选中态是线性的,选中就是填充的吗(或者全部是填充态,仅仅改变颜色)?这也太无聊了吧!所以又出现了双调图标的设计风格。即:双调图标的外形还是线性图标,但是用透明度很高的同类色填充到线性图标内部空间里。这样的图标显得俏皮可爱,并且感觉非常透气。

万字干货!设计师必须学会的图标技巧

△ 图为双调图标

动态图标(Motion)

动态图标是非常有趣的,如果静态图标不足以让用户感受到新鲜,那我们不妨给图标增加动效。比如 QQ应用中底部 Tab栏的图标点击其中一个的时候,其他图标会「偷看」选中态图标的方向。除了底部标签栏之外,很多 APP 点击能触发导航的「汉堡包图标」,点击时也会有一个从导航图标变成返回图标的动画。这都是非常能够调动用户好奇心的。

万字干货!设计师必须学会的图标技巧

△ Material Design中的动态图标

 

四、图标的设计方法

万字干货!设计师必须学会的图标技巧

1. 矢量图形(Vetctor)

我们在使用 Photoshop 工具的时候会感叹,画笔比钢笔好用,橡皮比布尔运算好用。那么我们在画图标的时候能不能使用画笔这样的工具来绘制图标呢?在 Photoshop 里使用画笔工具和橡皮工具、涂抹工具、选区工具的填充、油漆桶工具制作的图形,以及从网络上复制过来的jpg图片文件,这些都是像素图形。它们是计算机记录每一个点的颜色来呈现图像的。这也是为什么我们把一张照片放得特别大它就虚了的原因。而我们通过 Photoshop 中的钢笔工具、布尔运算、贝塞尔曲线、形状图层制作的图形,以及 Illustrator 复制过来的图形、Sktech绘制的图形等,都是矢量图形。它们是计算机记录一个锚点到另一个锚点的方向、位置、色彩来呈现图像的。所以像素图形变化多端、颜色变换丰富、细节更多;矢量图形则文件较小,并且具有随意放大缩小都不虚的能力。因为每个锚点之间的方向、位置都是相对的,放大和缩小不受影响,而像素图形记录每个点的色彩,比如一张2000px x 2000px的图片,缩小到1000px x 1000px就会损失一千个像素信息。我们绘制图标比较适合用矢量图形来设计,因为我们可能需要随时调整图标的大小,并且在不同分辨率的适配中也更加方便。

2. 布尔运算(Boolean)

布尔运算听着很可怕,其实非常简单,布尔运算是数字逻辑推演法,主要有数字逻辑的联合、相交、相减。在我们使用的平面软件中引用了这种逻辑运算方法来使基本图形通过联合、相交、相减等数学计算变成新的造型。比如两个圆形相减可以得到一个月亮的造型,这就是布尔运算了。那么为什么叫布尔运算呢?布尔指的是乔治·布尔(George Boole),一位19世纪最重要的数学家,为了纪念布尔在符号逻辑运算中的杰出贡献,所以我们将这种运算称为布尔运算。布尔运算在 Photoshop、Illustrator、Sketch、Adobe XD、After Effects等我们熟悉的软件中都有,并且操作基本一致。

布尔运算的核心就是两个形状的关系:即Union(并集)、Intersection(交集)和Subtraction(差集,包括A-B和B-A两种)。这些关系有点像我们初中学过的数学,应该比较好理解。但是很多软件中对于布尔运算的关系翻译不同,所以可能大家会有些不适应。比如在 Photoshop 中布尔运算被翻译成:合并形状、减去顶层形状、与形状区域相交、排除重叠形状。而在 Adobe XD 中则翻译成:添加、减去、交叉、排除重叠。虽然名字不同,但是功能是相同的,所以大家在学习新的软件时不妨先找一下布尔运算。

万字干货!设计师必须学会的图标技巧

△ 图为布尔运算不同运算模式

3. 贝塞尔曲线(Bézier curve)

贝塞尔曲线是用于二维图形绘制的数学曲线。1962年法国工程师皮埃尔·贝塞尔发表了贝塞尔曲线,它的诞生主要是为了汽车的主体设计绘制图形的。贝塞尔曲线是绘制矢量图形时的重要工具,我们使用钢笔工具画出的所有图形一般来说都是贝塞尔曲线组成的。贝塞尔曲线由锚点和线段组成,点击锚点就会出现两个手柄,一边是控制前面的线条走向,另一边是控制后端的线条走向。同时我们也可以通过增加锚点工具和删除锚点工具进行调整。要想学好平面电脑绘图软件,贝塞尔曲线是必须修炼的一课(练习贝塞尔曲线的在线游戏:https://bezier.method.ac/)。一般来说,二维平面软件都有贝塞尔曲线的痕迹,钢笔工具、增加锚点、删除锚点、转换点工具,这些都是平面软件的标配。并且,贝塞尔曲线和布尔运算可谓是一对好朋友,在绘制矢量图形时可以使用它们轻松地绘制出准确的造型。

万字干货!设计师必须学会的图标技巧

△ 图为贝塞尔曲线绘制方法

那么我们使用什么软件来绘制图标呢?这里我建议使用 Illustrator。首先,UI设计师使用不同的软件来设计页面,目前主流是 Photoshop和 Sketch,也有很多设计师选择 Adobe XD。而这些软件都是兼容 Illustrator 的,所以使用它来绘制图标非常有灵活性。可能您对 Illustrator 并不熟悉,不过没关系,我们在这里只需要了解它与图标绘制功能相关的功能即可,比如钢笔、布尔运算、属性面板、描边、填充、混合工具等,并不需要学习非常深入。所以大家不必紧张。

笑脸图标

笑脸图标的设计步骤:画出一个正圆;接着画一个小圆,然后 ctrl+F复制平行移动到旁边,然后右键编组。接着,同时选中大圆和编组的小圆进行水平居中对齐。我们绘制一个圆形,然后通过布尔运算减去一个矩形得到半圆形组成嘴,完成。

万字干货!设计师必须学会的图标技巧

△ 笑脸图标

对号图标

对号图标的设计步骤:使用矩形工具画出一个长方形,然后复制,将复制后的长方形向右上移动相同的距离,使用布尔运算剪切,旋转45°后变成一个对号。绘制一个正方形,使用路径选择工具选中,拖动圆角的圆点拉出圆角得到圆角矩形。对号和圆角矩形进行布尔运算,完成。

万字干货!设计师必须学会的图标技巧

△ 对号图标

WIFI图标

WIFI图标的设计步骤:绘制多个圆形并且通过布尔运算相加减得出三个圆圈嵌套的靶子造型。通过旋转过的45°矩形和之前图形布尔运算得到 Wifi图标,完成。

万字干货!设计师必须学会的图标技巧

△ WIFI图标

地理位置图标

地理位置图标的设计步骤:选择矩形工具单击画面输入数值,建立一个100px的圆形。然后选择这个圆形复制它,然后等比例缩小它,和之前的大圆进行布尔运算相减,得到环形。绘制50px的矩形,用对齐工具放在环形的左下方。旋转45°得到地理图标,完成。

万字干货!设计师必须学会的图标技巧

△ 地理位置图标

云彩图标

云彩图标的设计步骤:绘制两个大小不同的圆形,使用对齐工具进行底部对齐。绘制一个矩形,同样底部对齐。合并形状,完成。

万字干货!设计师必须学会的图标技巧

△ 云彩图标

眼睛图标

眼睛图标的设计步骤:绘制出一个正圆。复制这个正圆形,然后按着 Shift+方向键下键,并通过布尔运算得到眼睛外轮廓。绘制两个圆形,通过对齐工具和布尔运算工具得到最终眼睛造型,完成。

万字干货!设计师必须学会的图标技巧

△ 眼睛图标

铃铛图标

铃铛图标的设计步骤:首先用圆形和矩形合并组成主体;使用矩形和圆形进行布尔运算绘制铃铛底部和铃铛顶部的零件,然后进行合并形状;铃铛底部的半圆使用圆形和矩形布尔运算,完成。

万字干货!设计师必须学会的图标技巧

△ 铃铛图标

简易齿轮图标

简易齿轮图标的设计步骤:通过两个圆形进行布尔运算得到环形。绘制一个矩形,上下复制在圆形上,然后把它们俩编组和环形使用对齐工具进行水平垂直对齐。复制矩形编组并旋转90°,得到一个十字形。复制这个十字形并最终全部合并形状,完成。

万字干货!设计师必须学会的图标技巧

△ 简易图标

齿轮图标

齿轮图标的设计步骤:用 AI 的爆炸图形和圆形进行布尔运算画出齿轮;用两个圆形进行布尔运算做出里面的零件,完成。

万字干货!设计师必须学会的图标技巧

△ 齿轮图标

螺丝刀图标

螺丝刀图标的画法:用圆形和矩形做出螺丝刀主体;用矩形旋转并复制再布尔运算做出凹槽;使用矩形做出前面的造型,完成。

万字干货!设计师必须学会的图标技巧

△ 螺丝刀图标

苹果图标

苹果图标的画法:绘制一个六边形。将水平中间两个点向上移动。在中心线上下建立两个锚点,并且向下移动。将下面两个点向内分别移动。使用圆角工具将每两个相同的点一组一组拉成圆角。绘制一个矩形并且旋转45°,然后将左右两个点向内拉得到菱形。用圆角工具使菱形变成叶子造型并且旋转45°。使用一个圆形和苹果造型相切,完成。

万字干货!设计师必须学会的图标技巧

△ 苹果图标设计过程

放大镜线性图标

放大镜线性图标的画法:绘制正圆。绘制一条直线。用属性面板里的对齐工具把它们俩对齐。用描边面板里的属性将描边改成圆头,然后旋转45°即可。

万字干货!设计师必须学会的图标技巧

△ 放大镜线性图标

时钟线性图标

时钟线性图标的画法:绘制正圆。绘制一个矩形,对齐圆形中心。用增加锚点工具在矩形左和下边上增加两个锚点。用直接选择工具框选没用的线条,删除即可。

万字干货!设计师必须学会的图标技巧

△ 时钟线性图标

点赞线性图标

点赞线性图标的画法:绘制两个矩形,并用直接选择工具选择重合的四个锚点,在属性面板里使用对齐工具让它们完全对齐。将大的矩形底部锚点向左移动。绘制一个矩形并和大的矩形左对齐。用直接选择工具选中直角,拖动圆角小圆点让它们变成圆角,完成。

万字干货!设计师必须学会的图标技巧

△ 点赞线性图标

4. 线性图标的处理

如果您掌握了以上填充态图标的设计方法,相信其他图标的设计只要以此及彼的思考,就可以完成。比如线性图标,在绘制线性图标时,我们首先会建立一个半透明的矩形来固定图标应该绘制的范围,比如「40px」。然后我们把填充关闭,只使用描边来绘制线性图标即可。绘制完以后我们无需保存文件,仅通过 Ctrl+C的复制快捷键,然后打开 Sketch 或者 Adobe XD 就可以使用 Ctrl+V 将图标粘贴过去了。但是,如果您使用 Photoshop 做界面设计,可能会多两道手续,首先就是线性图标需要扩展才可以复制到 Photoshop 中。将图标复制一份(扩展之后的图标不方便修改,所以要留着可修改版本),然后点击对象菜单 > 扩展,点确定,就可以把原本是没有闭合的路径改为完整的形状。

万字干货!设计师必须学会的图标技巧

△ 在Illustrator中的扩展

然后复制,打开 Photoshop 粘贴会打开提示框,我们可以选择把图标粘贴成为像素、智能对象、路径、形状。如果粘贴成像素的话,那无疑对修改是非常不利的。如果粘贴成智能对象,双击智能对象会回到 Illustrator 中修改,但是也有一定缺点,那就是智能对象不能直接在 Photoshop 中进行调整。如果粘贴成路径也不是很方便,所以最好是我们将 Illustrator 中绘制的小图标粘贴成形状。选择后,图标就粘贴成了形状图层,我们可以在 Photoshop 中对它进行布尔运算、锚点调整等操作了。

万字干货!设计师必须学会的图标技巧

△ 粘贴到Photoshop中的选项

然而,我们会发现图标粘贴到 Photoshop 中,横竖的路径会出现虚边的情况(圆角和斜线是允许一定的虚边出现的,但是直线不可以)。这种虚边有可能会影响用户的体验,我们必须把它消灭掉。第一种方法:在 Photoshop 中我们可以用直接选择工具后界面上方的对齐路径功能,给它打钩来尝试修复这个问题。第二种方法:我们可以使用直接选择工具选中虚掉的某两个锚点,然后按 Ctrl+T(自由变换),再按键盘的上下或左右「摇一摇」,路径就会清晰了。第三种方法:也可以使用几像素的矩形进行布尔运算强行对齐。三种方法一定能够让图标的横竖路径没有虚边,达到完美的效果。当然 Sketch 和 Adobe XD 都是矢量工具所以复制后没有这个问题。

万字干货!设计师必须学会的图标技巧

在 Photoshop 中使用「摇一摇」的方法对齐路径

万字干货!设计师必须学会的图标技巧

在 Adobe XD 中,图标无需进行扩展,并可以实时调整描边粗细等属性。

5. 应用

标签栏图标

在苹果和安卓APP 的底部,一般都会有一个放置重要功能的常驻栏,在 iOS中被称为标签栏(也叫做Tab栏)。一般,Tab栏的图标是2-5个。每个图标的区域平分整个 Tab栏宽度,底部会有一个22px(11pt)的文字注释。当然如果图标释义较为清晰,也可以为了保持设计感去掉文字注释。如果我们是以 iPhone6/7/8尺寸设计界面,那么我们的标签栏图标尺寸应该是60px(30pt)左右,可以基于这个范围来设计我们的图标。

万字干货!设计师必须学会的图标技巧

△ 互联网产品中优秀的标签栏图标设计

每个 Tab栏的图标都应该设计一个选中状态,可以做样式的变换也可以做颜色的改变,总之要让人知道当前所在的页面是哪个。如果您的 Tab栏由五个 icon 组成,那么可以在中间放置比较重要的功能,并做出突显的样式,比如使用一个圆球当作背景。还要额外注意,图标的选中态样式要和中间突出状态的图标保持区别,以免发生误会。

导航栏图标

在苹果APP 的顶部区域,我们称之为 Navigation Bar,就是导航栏。导航栏左右一般都会有图标,如果是二级页面,左侧一般是返回图标。安卓也有类似的设计。那么我们在设计这种图标的时候一定要保证所有导航栏上的图标大小和风格都是一致的。如果以 iPhone6/7/8尺寸设计界面,那么导航栏图标的尺寸大概是44px(22pt)左右。

万字干货!设计师必须学会的图标技巧

△ 互联网产品中优秀的导航栏图标

金刚区图标

在我们逛淘宝和美团的时候您会发现,在它们页面首页都会有一个区域放置很多分类,一般是6-8个大小一样的图标,有可能是圆形,也可能是不规则形状。这个区域其实在苹果和安卓规范里并没有,属于设计师自创的规范。这个区域经常有八个图标组成,被称为「八大金刚图标」,后来很多产品在这个区域并不使用8个图标,我们就称它们为金刚区了。金刚区图标的设计风格应该尽量是微扁平、轻拟物的感觉,这样会有更好的点击感。尺寸方面,金刚区并没有规范,所以大家可以以设计稿最终效果为准。

万字干货!设计师必须学会的图标技巧

△ 互联网产品中优秀的金刚区图标设计

设计方法:《用四个步骤,帮你学会金刚区图标的设计方法》

总结

图标设计是 UI设计中非常重要的一环,因为除了文字和图片的排版之外,在扁平时代我们能够传递给用户情绪和设计感的通道就是页面中的各种图形和图标了,如果做不好图标,用户就将在使用界面时失去乐趣。所以,我建议每位 UI设计师都需要在平时做大量的图标练习。在不同的图标风格中,学会使用各式各样的武器。




文章来源:优设网    作者:郗鉴


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



“五一”机票酒店价格报复性上涨,我决定在家躺平……

seo达人

 

令人期待的“五一”假期将至,一场报复性出游蓄势待发。与此同时,机票酒店价格也迎来了报复性上涨。

6a600c338744ebf855dd05c39b8cb1226159a71f.jpeg

资料图:玉渊潭人头攒动。中新网记者 李金磊 摄

“五一”假期或迎2亿人次出游

今年“五一”放假5天,当前疫情防控形势稳定,春节“就地过年”积压的探亲、出游需求有望进一步释放,再加上“五一”本来就是传统出行旺季,业内预计“五一”假期或迎来报复性出游,旅游人次有望突破2019年同期,达2亿人次新高。

火车票秒光、热门航班经济舱一票难求、热门景区门票售罄、酒店民宿预订火爆……种种迹象表明,“五一”出行需求强烈,一个史上最热的“五一”假期在路上了。

“五一”火车票紧俏。多条热门线路火车票瞬间秒光,“12306崩了”一度登上热搜,不少人感叹“五一”抢票太难,堪比春运。

热门航班经济舱售罄。去哪儿数据显示,“五一”假期机票预订量超过2019年同期三成水平。热门航班经济舱一票难求。以“五一”当天北京飞往三亚的航线为例,多数航班经济舱已经售罄。

热门城市酒店民宿火爆。携程数据显示,“五一”期间酒店预订量比2019年同期增长43%。途家大数据显示,很多网红民宿在“五一”期间已提前满房;长沙、西安、厦门、武汉、桂林、青岛多地民宿宣布库存“告急”。

热门景区门票售罄。记者4月23日登陆故宫网站发现,“五一”假期前三天(5月1日至5月3日)的故宫门票已经售罄。

4610b912c8fcc3ce2a42c59dd030b080d53f201f.jpeg

“五一”假期前三天故宫门票已售罄。

热门城市机票酒店大幅涨价

报复性出游蠢蠢欲动,在出游热情高涨的同时,机票和酒店的价格也迎来报复性上涨。

中国民航局运输司副司长商可佳4月16日在新闻发布会上表示,从“五一”假期机票预订情况看,可谓“量价齐升”,明显高于今年清明假期,也有望高于2019年“五一”假期。

携程数据显示,目前“五一”机票订单量已经赶超2019年同期水平,增长23%。“五一”机票经济舱平均票价为1021元,超过2019年同期均价。上海、北京、三亚、广州、成都、重庆、西安、厦门、杭州、深圳位列前十大出行目的地。

从酒店来看,去哪儿数据显示,截至目前,2021年“五一”假期国内酒店预订量已经超过2019年同期四成以上,每晚均价为458元,比2019年时贵了85元;而与2020年五一假期相比,预订量增长8.1倍。

部分热门目的地酒店价格涨幅较高。据报道,比如三亚的酒店平均价格较2019年同期上涨了80.5%,平均每间夜的价格高达1696元。

“五一”假期机票和酒店价格上涨,也引发了网友的吐槽。

“好久不出门,看了一眼‘五一’的机票和住宿怎么都这么贵,普普通通的酒店一晚都一千了?没钱都不敢出去玩。”

“‘五一’前一周开始计划出游,我体会到了机票和酒店惊人的价格。”

“后悔没有早订票!看完机票和酒店价格,我决定在家里躺5天了。”

78310a55b319ebc487a0678ac053a9f41f171641.jpeg

图为三亚大东海旅游景区的沙滩吸引了许多游客前来游玩,享受阳光沙滩。 骆云飞 摄

跨省长线游热度高

“五一”5天长假进一步刺激了跨省长途旅游的热情。请3天假休9天的方案为计划长线旅游人群提供了可能。

携程数据显示,“五一”假期超7成人群选择跨省旅游,黄金周“迁徙式旅游”盛况或将重现。

去哪儿大数据研究院院长兰翔表示,虽然2020年“五一”假期也是五天,但当时出游仍以周边游、短途游为主。今年国内疫情防控形势总体保持良好,人们出游信心不断恢复、出游需求也日益增加,清明假期就是一次短暂的试水。今年“五一”,更多的游客会选择跨省长线游。

西北和西南再度火热,新疆酒店预订增幅明显。去哪儿数据显示,与2019年同期相比,酒店预订量增长超过7倍。今年“五一”假期酒店预订增幅最高的十个目的地中,四个目的地来自新疆。

“五一”假期,你去哪里玩?

(来源:中国新闻社)

 蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

刷新记录!印度疫情单日新增46万人,局势或将全面失控!

seo达人

 

印度卫生部官方网站公布的最新数据显示,截至 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,一连串名词会蹦出来:

  • babel-cli
  • babel-core
  • babel-runtime
  • babel-node
  • babel-polyfill
  • ...

这些都是 babel 吗?他们分别是做什么的?有区别吗?

babel 到底做了什么?怎么做的?

简单来说把 JavaScript 中 es2015/2016/2017/2046 的新语法转化为 es5,让低端运行环境(如浏览器和 node )能够认识并执行。本文以 babel 6.x 为基准进行讨论。最近 babel 出了 7.x,放在最后聊。

严格来说,babel 也可以转化为更低的规范。但以目前情况来说,es5 规范已经足以覆盖绝大部分浏览器,因此常规来说转到 es5 是一个安全且流行的做法。

如果你对 es5/es2015 等等也不了解的话,那你可能真的需要先补补课了。

使用方法

总共存在三种方式:

  1. 使用单体文件 (standalone script)
  2. 命令行 (cli)
  3. 构建工具的插件 (webpack 的 babel-loader, rollup 的 rollup-plugin-babel)。

其中后面两种比较常见。第二种多见于 package.json 中的 scripts 段落中的某条命令;第三种就直接集成到构建工具中。

这三种方式只有入口不同而已,调用的 babel 内核,处理方式都是一样的,所以我们先不纠结入口的问题。

运行方式和插件

babel 总共分为三个阶段:解析,转换,生成。

babel 本身不具有任何转化功能,它把转化的功能都分解到一个个 plugin 里面。因此当我们不配置任何插件时,经过 babel 的代码和输入是相同的。

插件总共分为两种:

  • 当我们添加 语法插件 之后,在解析这一步就使得 babel 能够解析更多的语法。(顺带一提,babel 内部使用的解析类库叫做 babylon,并非 babel 自行开发)

举个简单的例子,当我们定义或者调用方法时,最后一个参数之后是不允许增加逗号的,如 callFoo(param1, param2,) 就是非法的。如果源码是这种写法,经过 babel 之后就会提示语法错误。

但最近的 JS 提案中已经允许了这种新的写法(让代码 diff 更加清晰)。为了避免 babel 报错,就需要增加语法插件 babel-plugin-syntax-trailing-function-commas

  • 当我们添加 转译插件 之后,在转换这一步把源码转换并输出。这也是我们使用 babel 最本质的需求。

比起语法插件,转译插件其实更好理解,比如箭头函数 (a) => a 就会转化为 function (a) {return a}。完成这个工作的插件叫做 babel-plugin-transform-es2015-arrow-functions

同一类语法可能同时存在语法插件版本和转译插件版本。如果我们使用了转译插件,就不用再使用语法插件了。

配置文件

既然插件是 babel 的根本,那如何使用呢?总共分为 2 个步骤:

  1. 将插件的名字增加到配置文件中 (根目录下创建 .babelrc 或者 package.json 的 babel 里面,格式相同)
  2. 使用 npm install babel-plugin-xxx 进行安装

具体书写格式就不详述了。

preset

比如 es2015 是一套规范,包含大概十几二十个转译插件。如果每次要开发者一个个添加并安装,配置文件很长不说,npm install 的时间也会很长,更不谈我们可能还要同时使用其他规范呢。

为了解决这个问题,babel 还提供了一组插件的集合。因为常用,所以不必重复定义 & 安装。(单点和套餐的差别,套餐省下了巨多的时间和配置的精力)

preset 分为以下几种:

  • 官方内容,目前包括 env, react, flow, minify 等。这里最重要的是 env,后面会详细介绍。
  • stage-x,这里面包含的都是当年最新规范的草案,每年更新。
    这里面还细分为
    • Stage 0 - 稻草人: 只是一个想法,经过 TC39 成员提出即可。
    • Stage 1 - 提案: 初步尝试。
    • Stage 2 - 初稿: 完成初步规范。
    • Stage 3 - 候选: 完成规范和浏览器初步实现。
    • Stage 4 - 完成: 将被添加到下一年度发布。

例如 syntax-dynamic-import 就是 stage-2 的内容,transform-object-rest-spread 就是 stage-3 的内容。
此外,低一级的 stage 会包含所有高级 stage 的内容,例如 stage-1 会包含 stage-2, stage-3 的所有内容。
stage-4 在下一年更新会直接放到 env 中,所以没有单独的 stage-4 可供使用。

  • es201x, latest
    这些是已经纳入到标准规范的语法。例如 es2015 包含 arrow-functions,es2017 包含 syntax-trailing-function-commas。但因为 env 的出现,使得 es2016 和 es2017 都已经废弃。所以我们经常可以看到 es2015 被单独列出来,但极少看到其他两个。
    latest 是 env 的雏形,它是一个每年更新的 preset,目的是包含所有 es201x。但也是因为更加灵活的 env 的出现,已经废弃。

执行顺序

很简单的几条原则:

  • Plugin 会运行在 Preset 之前。
  • Plugin 会从前到后顺序执行。
  • Preset 的顺序则 刚好相反(从后向前)。

preset 的逆向顺序主要是为了保证向后兼容,因为大多数用户的编写顺序是 ['es2015', 'stage-0']。这样必须先执行 stage-0 才能确保 babel 不报错。因此我们编排 preset 的时候,也要注意顺序,其实只要按照规范的时间顺序列出即可。

插件和 preset 的配置项

简略情况下,插件和 preset 只要列出字符串格式的名字即可。但如果某个 preset 或者插件需要一些配置项(或者说参数),就需要把自己先变成数组。第一个元素依然是字符串,表示自己的名字;第二个元素是一个对象,即配置对象。

最需要配置的当属 env,如下:

"presets": [ // 带了配置项,自己变成数组  [ // 第一个元素依然是名字  "env", // 第二个元素是对象,列出配置项  { "module": false } ], // 不带配置项,直接列出名字  "stage-2" ] 

env (重点)

因为 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。它的取值可以是 amdumdsystemjscommonjs 和 false。这可以让 babel 以特定的模块化格式来输出代码。如果选择 false 就不进行模块化处理。

其他配套工具

以上讨论了 babel 的核心处理机制和配置方法等,不论任何入口调用 babel 都走这一套。但文章开头提的那一堆 babel-* 还是让人一头雾水。实际上这些 babel-* 大多是不同的入口(方式)来使用 babel,下面来简单介绍一下。

babel-cli

顾名思义,cli 就是命令行工具。安装了 babel-cli 就能够在命令行中使用 babel 命令来编译文件。

在开发 npm package 时经常会使用如下模式:

  • 把 babel-cli 安装为 devDependencies
  • 在 package.json 中添加 scripts (比如 prepublish),使用 babel 命令编译文件
  • npm publish

这样既可以使用较新规范的 JS 语法编写源码,同时又能支持旧版环境。因为项目可能不太大,用不到构建工具 (webpack 或者 rollup),于是在发布之前用 babel-cli 进行处理。

babel-node

babel-node 是 babel-cli 的一部分,它不需要单独安装。

它的作用是在 node 环境中,直接运行 es2015 的代码,而不需要额外进行转码。例如我们有一个 js 文件以 es2015 的语法进行编写(如使用了箭头函数)。我们可以直接使用 babel-node es2015.js 进行执行,而不用再进行转码了。

可以说:babel-node = babel-polyfill + babel-register。那这两位又是谁呢?

babel-register

babel-register 模块改写 require 命令,为它加上一个钩子。此后,每当使用 require 加载 .js.jsx.es 和 .es6 后缀名的文件,就会先用 babel 进行转码。

使用时,必须首先加载 require('babel-register')

需要注意的是,babel-register 只会对 require 命令加载的文件转码,而 不会对当前文件转码

另外,由于它是实时转码,所以 只适合在开发环境使用

babel-polyfill

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 主要有两个缺点:

  1. 使用 babel-polyfill 会导致打出来的包非常大,因为 babel-polyfill 是一个整体,把所有方法都加到原型链上。比如我们只使用了 Array.from,但它把 Object.defineProperty 也给加上了,这就是一种浪费了。这个问题可以通过单独使用 core-js 的某个类库来解决,core-js 都是分开的。
  2. babel-polyfill 会污染全局变量,给很多类的原型链上都作了修改,如果我们开发的也是一个类库供其他开发者使用,这种情况就会变得非常不可控。

因此在实际使用中,如果我们无法忍受这两个缺点(尤其是第二个),通常我们会倾向于使用 babel-plugin-transform-runtime

但如果代码中包含高版本 js 中类型的实例方法 (例如 [1,2,3].includes(1)),这还是要使用 polyfill。

babel-runtime 和 babel-plugin-transform-runtime (重点)

我们时常在项目中看到 .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,它内部集成了

  1. core-js: 转换一些内置类 (PromiseSymbols等等) 和静态方法 (Array.from 等)。绝大部分转换是这里做的。自动引入。
  2. regenerator: 作为 core-js 的拾遗补漏,主要是 generator/yield 和 async/await 两组的支持。当代码中有使用 generators/async 时自动引入。
  3. helpers, 如上面的 asyncToGenerator 就是其中之一,其他还有如 jsxclassCallCheck 等等,可以查看 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-loader

前面提过 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.x

最近 babel 发布了 7.0。因为上面部分都是针对 6.x 编写的,所以我们关注一下 7.0 带来的变化(核心机制方面没有变化,插件,preset,解析转译生成这些都没有变化)

我只挑选一些和开发者关系比较大的列在这里,省略的多数是针对某一个 plugin 的改动。完整的列表可以参考官网

preset 的变更:淘汰 es201x,删除 stage-x,强推 env (重点)

淘汰 es201x 的目的是把选择环境的工作交给 env 自动进行,而不需要开发者投入精力。凡是使用 es201x 的开发者,都应当使用 env 进行替换。但这里的淘汰 (原文 deprecated) 并不是删除,只是不推荐使用了,不好说 babel 8 就真的删了。

与之相比,stage-x 就没那么好运了,它们直接被删了。这是因为 babel 团队认为为这些 “不稳定的草案” 花费精力去更新 preset 相当浪费。stage-x 虽然删除了,但它包含的插件并没有删除(只是被更名了,可以看下面一节),我们依然可以显式地声明这些插件来获得等价的效果。完整列表

为了减少开发者替换配置文件的机械工作,babel 开发了一款 babel-upgrade 的工具,它会检测 babel 配置中的 stage-x 并且替换成对应的 plugins。除此之外它还有其他功能,我们一会儿再详细看。(总之目的就是让你更加平滑地迁移到 babel 7)

npm package 名称的变化 (重点)

这是 babel 7 的一个重大变化,把所有 babel-* 重命名为 @babel/*,例如:

  1. babel-cli 变成了 @babel/cli
  2. babel-preset-env 变成了 @babel/preset-env。进一步,还可以省略 preset 而简写为 @babel/env
  3. babel-plugin-transform-arrow-functions 变成了 @babel/plugin-transform-arrow-functions。和 preset 一样,plugin 也可以省略,于是简写为 @babel/transform-arrow-functions

这个变化不单单应用于 package.json 的依赖中,包括 .babelrc 的配置 (pluginspresets) 也要这么写,为了保持一致。例如

{
  "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。(这个插件我自己没有单独用过,惭愧)

不再支持低版本 node

babel 7.0 开始不再支持 nodejs 0.10, 0.12, 4, 5 这四个版本,相当于要求 nodejs >= 6 (当前 nodejs LTS 是 8,要求也不算太过分吧)。

这里的不再支持,指的是在这些低版本 node 环境中不能使用 babel 转译代码,但 babel 转译后的代码依然能在这些环境上运行,这点不要混淆。

only 和 ignore 匹配规则的变化

在 babel 6 时,ignore 选项如果包含 *.foo.js,实际上的含义 (转化为 glob) 是 ./**/*.foo.js,也就是当前目录 包括子目录 的所有 foo.js 结尾的文件。这可能和开发者常规的认识有悖。

于是在 babel 7,相同的表达式 *.foo.js 只作用于当前目录,不作用于子目录。如果依然想作用于子目录的,就要按照 glob 的完整规范书写为 ./**/*.foo.js 才可以。only 也是相同。

这个规则变化只作用于通配符,不作用于路径。所以 node_modules 依然包含所有它的子目录,而不单单只有一层。(否则全世界开发者都要爆炸)

@babel/node 从 @babel/cli 中独立了

和 babel 6 不同,如果要使用 @babel/node,就必须单独安装,并添加到依赖中。

babel-upgrade

在提到删除 stage-x 时候提过这个工具,它的目的是帮助用户自动化地从 babel 6 升级到 7。

这款升级工具的功能包括:(这里并不列出完整列表,只列出比较重要和常用的内容)

  1. package.json
  2. 把依赖(和开发依赖)中所有的 babel-* 替换为 @babel/*
  3. 把这些 @babel/* 依赖的版本更新为最新版 (例如 ^7.0.0)
  4. 如果 scripts 中有使用 babel-node,自动添加 @babel/node 为开发依赖
  5. 如果有 babel 配置项,检查其中的 plugins 和 presets,把短名 (env) 替换为完整的名字 (@babel/preset-env)
  6. .babelrc
  7. 检查其中的 plugins 和 presets,把短名 (env) 替换为完整的名字 (@babel/preset-env)
  8. 检查是否包含 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 VS JavaScript 深度对比

前端达人



TypeScript 和 JavaScript 是目前项目开发中较为流行的两种脚本语言,我们已经熟知 TypeScript 是 JavaScript 的一个超集,但是 TypeScript 与 JavaScript 之间又有什么样的区别呢?在选择开发语言时,又该如何抉择呢?

本文将会深入对比这两种语言,讨论两种语言之间的关联和差异,并概述两种语言各自的优势。

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 易学易于理解


  • JavaScript 和 TypeScript 的主要差异

    TypeScript 可以使用 JavaScript 中的所有代码和编码概念,TypeScript 是为了使 JavaScript 的开发变得更加容易而创建的。例如,TypeScript 使用类型和接口等概念来描述正在使用的数据,这使开发人员能够快速检测错误并调试应用程序

  • TypeScript 从核心语言方面和类概念的模塑方面对 JavaScript 对象模型进行扩展。

  • JavaScript 代码可以在无需任何修改的情况下与 TypeScript 一同工作,同时可以使用编译器将 TypeScript 代码转换为 JavaScript。

  • TypeScript 通过类型注解提供编译时的静态类型检查。

  • TypeScript 中的数据要求带有明确的类型,JavaScript不要求。

  • TypeScript 为函数提供了缺省参数值。

  • TypeScript 引入了 JavaScript 中没有的“类”概念。

  • TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块中。


  • TypeScript 的优势

    下面列举 TypeScript 相比于 JavaScript 的显著优势:

    1. 静态输入

    静态类型化是一种功能,可以在开发人员编写脚本时检测错误。查找并修复错误是当今开发团队的迫切需求。有了这项功能,就会允许开发人员编写更健壮的代码并对其进行维护,以便使得代码质量更好、更清晰。

    2. 大型的开发项目

    有时为了改进开发项目,需要对代码库进行小的增量更改。这些小小的变化可能会产生严重的、意想不到的后果,因此有必要撤销这些变化。使用TypeScript工具来进行重构更变的容易、快捷。

    3. 更好的协作

    当发开大型项目时,会有许多开发人员,此时乱码和错误的机也会增加。类型安全是一种在编码期间检测错误的功能,而不是在编译项目时检测错误。这为开发团队创建了一个更高效的编码和调试过程。

    4. 更强的生产力

    干净的 ECMAScript 6 代码,自动完成和动态输入等因素有助于提高开发人员的工作效率。这些功能也有助于编译器创建优化的代码。

    JavaScript 的优势

    相比于 TypeScript,JavaScript 也有一些明显优势。

    1. 人气

    JavaScript 的开发者社区仍然是巨大而活跃的,在社区中可以很方便地找到大量成熟的开发项目和可用资源。

    2. 学习曲线

    由于 JavaScript 语言发展的较早,也较为成熟,所以仍有一大批开发人员坚持使用他们熟悉的脚本语言 JavaScript,而不是学习 TypeScript。

    3. 本地浏览器支持

    TypeScript 代码需要被编译(输出 JavaScript 代码),这是 TypeScript 代码执行时的一个额外的步骤。

    4. 不需要注释

    为了充分利用 TypeScript 特性,开发人员需要不断注释他们的代码,这可能会使项目效率降低。

    5. 灵活性

    有些开发人员更喜欢 JavaScript 的灵活性。

    如何抉择

    TypeScript 正在成为开发大型编码项目的有力工具。因为其面向对象编程语言的结构保持了代码的清洁、一致和简单的调试。因此在应对大型开发项目时,使用 TypeScript 更加合适。如果有一个相对较小的编码项目,似乎没有必要使用 TypeScript,只需使用灵活的 JavaScript 即可。


    作者:grain先森
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。






    蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服

    日历

    链接

    blogger

    蓝蓝 http://www.lanlanwork.com

    存档