‘==’和‘===’都是Javascript中的比较运算符,都是比较运算符两边是否相等。对于‘==’和‘===’的区别,大家也都知道:
‘==’仅仅是比较运算符两边的数值是否相等,如果数值相等则返回true;‘===’不仅会判断运算符两边的数值是否相等,并且还会判断两边的类型是否相等,只有数值和类型都相等才会返回true。虽然知道以上的判断依据已经能解决绝大数此类问题,但是如果往其中深究来说,会有同学问:在比较的时候‘===’先判断类型,如果类型不同就直接返回false,这个没什么问题。但是如果是‘==’比较两个不同类型的数据时,具体是怎么进行计算判断的呢?
既然是不同类型进行比较,肯定最终参与比较的结果必须是同一个类型的,因此JS会存在一个隐式转换的问题,并且很多JS的隐式转换很难通过console.log()等方法直观的观察到,因此很多初学者会对JS的隐式转换感到疑惑。
首先让我们回忆一下,咱们的JS中一共有哪些数据类型?
六大数据类型
基本数据类型(简单数据类型)
number 数值型(NaN)
string 字符串
boolean 布尔型
undefined 未定义
null 空引用
引用数据类型(复杂数据类型)
object
JS基础中,我们学习到咱们的JS中一共有六种数据类型,分为基本数据类型(简单数据类型)和引用数据类型(复杂数据类型),不同类型的值进行比较的时候,存在隐式转换的问题,咱们通过‘==’来验证一下JS隐式转换的情况。
1.我们首先来看看下列的语句计算结果:
console.log(NaN==true);//false
console.log(NaN==false);//false
console.log(NaN==0);//false
console.log(NaN==1);//false
console.log(NaN==NaN);//false
由上面的例子可以看出,NaN属于Number数据类型中一个特殊情况,如果‘==’两边同为Number数据类型的数字,很直观的可以看出值是否相同一眼就可以看出结果,但是作为Number类型的特殊情况,NaN在进行比较的时候,也会有特殊的结果:如果 x 或 y 中有一个为 NaN,则返回 false;
2.我们继续看看下列的语句计算结果:
console.log(null == undefined); //true(特殊情况)---------------------------------
console.log(null == ''); //false
console.log(undefined == ''); //false
在上述例子中,引出了一个null,null是一个简单数据类型,它的意义就是一个空应用,但是你如果通过console.log(typeof null) 来打印结果的时候却发现,结果竟然是object?此时你可能会怀疑人生,然后疯狂的翻阅之前学习的资料,因为object明明是一个复杂数据类型,怎么会在判断null这个简单数据类型的类型时打印出来呢?其实,这个问题属于一个历史问题。咱们学习的JS在发展过程中是通过ECMAScript来确定规范的,每年都会有新的规定和规范提出,在JS的发展过程中,null一开始的作用就是用来指向一个空地址,让开发者在创建数据的时候,先用null赋值给还未给值的对象用于标准初始化。但是其实咱们开发过程中很少用到,但是这个仍作为规范留了下来。又因为typeof是根据数据的前几位判断数据类型的,null相当于空指针,前几位是地址的格式,所以判断结果就为object。又因为undefined值是派生自null值的,因此ECMA-262规定对他们的相等测试要返回true。所以这一情况判断的条件为:如果 x 与 y 皆为 null 或 undefined 中的一种类型,则返回 true(null == undefined // true);否则返回 false(null == 0 // false);
3.请看下列例子:
console.log(true == '123'); //false
console.log(true == '1'); //true
console.log(false == '0'); //true
console.log(true == !0); //true
console.log([] == []); //false
console.log([] == ![]); //true 比较地址 ------------------------------------------------
var a = c = [];
var b = [];
console.log(a == b); //false
console.log(a == !b); //true
console.log(a == c); //true
console.log(Boolean([]) == true); //true
console.log(Number([]) == 0); //true
console.log(Number(false) == 0); //true
其实比较的逻辑为:如果 x,y 类型不一致,且 x,y 为 String、Number、Boolean 中的某一类型,则将 x,y 使用 Number 函数转化为 Number 类型再进行比较;
使用Number函数可以将其他的数据类型转变为Number类型,这一同为Number类型的数据,对比起来就会变得十分简单。值得注意的是在上述的例子中,两个空数组进行比较,结果返回的结果仍然为false,这个是怎么回事呢?其实这个很好理解,因为数组也是对象的一种,是复杂数据类型,所以用变量储存对象时储存的其实是地址。对象的内容相同,但是储存在堆区的位置不同,所以地址也是不同的,所以在判断的时候返回的是false。
其实在JS中还有很多的隐式转换情况,以上只是针对于‘==’的隐式转换情况,对于这些问题,在实际开发过程中,需要作为开发者不断的学习和积累,这也是咱们作为开发者的一个要求之一。
作为用户,在很多时候会很容易判断出一个网站的用户体验是否优秀,因为主观感受是很难被欺骗的。但是作为网站的设计者和开发者,角色转换之后,所需要面对问题就复杂得多。身为构建者,要让体验尽善尽美需要花费大量的时间精力来完善整个体验的闭环。今天为你所整理的这7个 UX设计的原则,能够帮你更好地进行网站的 UX设计,并且尽可能地将整体的用户体验提升到一定高度。
想要创造难忘的用户体验,自然要围绕着用户体验本身来进行设计。甚至在某种意义上来说,数据和内容也应该是服务于体验的, 它们应该以什么样的体验来呈现出来,这是设计者需要反复思考和琢磨的问题。
图形、布局、文本和交互元素之间的协同工作才能创造体验,任何一个维度缺一不可,单纯的信息展示是不够的。
想让你的网页能在互联网上大量的信息中脱颖而出,体验是至关重要的。现代网页中大量的视觉和交互内容存在,是为了能通过体验直击人心,这样才能在激烈的竞争中存活。
如果你认为网站内容是用来读的,那就错了。现代用户的注意力集中的时间非常短,绝大多数用户在浏览信息的时候,都是快速扫视,而非逐字逐句地仔细阅读,信息的展现一定要直观、清晰,确保能够一瞥就能看明白。借助信息图表和视觉,更快地传达信息和数据。
你需要让你的内容更加吸引用户,绝大多数用户会为触动它们的信息和内容而驻足,当他们想要了解更多的时候,才会点击,了解更多。
用户只需要半秒就能判断出网站设计和内容,你需要尽量让网站的交互和指引足够清晰,显而易见。不要让按钮难以被用户发现,在首页上放上一大堆的按钮和链接,不如通过视觉上的引导,让用户注意到最关键的那个 CTA按钮。
通过迭代和测试,不断地优化和提升网站的易用性。有的设计对于绝大多数的用户都非常有用,凸显最重要的选项,允许隐藏额外的功能,并且为用户提供显示全部的选项。
除了清晰的设计,整体的一致性也很重要。统一的配色、交互和图形能够让用户对于后续的操作有更清晰的预期,减少用户在后续操作过程中探索的力度,这是通过统一性设计提升产品易用性的一种方式。
当某个设计元素在其他地方很常见的时候,它就已经形成了特定的 UI 模式,尽量不要去修改它,哪怕是很富有创意的方式。当你将这种约定俗成的元素修改成其他样子的时候,用户需要花费比平时更长的时间来判断它究竟是什么。这种认知负荷将会影响整个网站的使用效率和转化率。比如汉堡图标,比如网站登录入口的位置(右上角)。没有必要在这种地方重新「标准化」。
对于链接、导航、布局这样基本的元素,应该始终优先考虑其可用性,在此基础上再发挥创意。
虽然非传统的设计很酷,但是它的可用性问题同样很大。创造性的设计同样是需要控制其程度和平衡,如果非要打破常规,尽量控制好程度,并且一次最多打破一条规则,不能更多。
在开始创建网站和 APP 之前,你应该对于你的目标客户群体有足够清晰的了解,这样才能更好地为他们来设计界面。
一旦你清楚地了解了你的用户,就能了解他们的需求和愿望,并且设计出符合他们预期的界面和体验。这个时候,你的竞争对手能够为你提供灵感和想法。注意对方的色彩,布局,风格和功能。
尽可能使用你的受众已经熟悉的 UI 模式和 UI 元素,能够更快让他们上手。在此基础上,适当地进行差异化的设计,这样效率更高。
当你确定了受众之后,记得尽量把他们的反馈纳入到你的设计当中。
当界面中优先放置最重要的元素,通过视觉层次来凸显它们,确保用户能够更快注意到它们。在设计中,有很多方法能够凸显内容,但是最有效的方法始终是让它们更大更醒目。
视觉层次的构建能够让网站内容更加清晰,也更加富有功能性。
Peter Moville 在 usability.gov 这个网站上列举出了用户体验设计的关键因素,它的核心价值在于通过不同的维度更好地掌控用户体验的质量:
除了上面的维度之外,还有一些值得参考的 UX设计的质量衡量标准:
用户体验设计的目标不仅仅是让产品本身更优秀,更重要的是从情感层面上和用户产生关联。有界面而没有体验,这样的产品在今天的竞争中是活不下去的。
从用户的操作流程上来说,如果用户想使用一个功能,必然首先要发现它。如果连功能入口都找不到,后续的用户体验也无从谈起。而筛选功能可以帮助用户对功能信息进行快速的定位,缩短用户的查找时间,这篇文章我就来跟大家聊一下筛选功能。
三种常见基本样式
首先要明确一个概念,筛选功能并不是普通的单一功能项,它和导航一样是一个体系。既然是体系,必然有最基本的组成部分。筛选功能(体系)常见的样式有以下三种:tab类,(下拉)列表类,标签类。这三种样式是筛选功能最基本的组成元素,不管你产品的筛选功能做的有多么复杂,都可以看成是这三种基本元素的不同组合形式。
Tab
Tab是最常见的筛选样式,一个tab项代表一个筛选维度,直接平铺的展示出来,用户很容易感知到。
根据方向我们可以将tab分为横向栏tab和侧向栏tab。横向栏tab可展示2-5个选项,如果超过了5个,那么就需要用户滑动才能看到。所以当筛选维度过多的时候,我们可以考虑使用侧向栏tab,京东商品分类这里用的就是典型的侧向栏tab,我数了一下总共40个选项,这里如果使用横向栏tab用户可能要侧向滑动8屏,操作成本过高。
当然当选项过多的时候,我们还有一个法子,就是使用弹框,用户点击后可以看到全部的选项。
列表式
列表式也可称之为list,其特点就是占用空间小。因为它可以将选项隐藏起来,用户需要点击才能看到所有的选项,因此在有限的空间里可以展示更多的筛选维度。碍于手机屏幕尺寸的限制,列表式筛选现在应用的越来越普遍。
列表式筛选的样式其实有很多。可以做成popover类,actionsheet类,activityview类。这些样式很难去说谁好谁坏,这里我就只是列举出来,具体用哪种样式,大家自己来判断。
标签式
对于标签式,很难进行准确的定义,我更倾向于将单选按钮,多选按钮,switch等统称为标签式,标签式只能针对单一条件进行筛选,这点和tab很类似。标签式很少单独出现,多数情况下都是与tab和列表式结伴而行。
在淘宝里用户可以点击视图icon来切换视图模式,这就是典型的标签式筛选。
当然以上三种只是最常见的筛选元素,其余的还有输入框,滑块,地区/日期选择器等主要用于信息录入的组件。
常见的筛选体系
了解了最基本的元素,接下来看一些比较复杂的筛选样式。上面我也提到了任何产品的筛选体系都可以看成是这三种基本元素的不同组合形式。为了让大家更好的理解,我一一举例来说明:
tab+tab:
tab之所以受到青睐,是因为其较低的学习成本。每一个tab代表一个类别,而且是直接展示给用户看的,所以很多产品的筛选功能都会优先考虑使用tab。即使功能结构复杂到无法用一层tab来完成筛选任务,设计师也会考虑使用双层tab样式(tab+tab)的样式。(PS.当然下图应该算是segment control+tab)
tab+列表式:
当产品不断的发展,功能结构愈发的复杂,过于扁平的tab已经无法满足筛选的需求。以看电影这个场景为例,用户的需求是找到合适的影片和电影院。对于用户来说,衡量一家电影院会从地址、票价、品牌和特色服务(支持改签、IMAX厅等)这四个角度入手。这些筛选需求很难通过tab来完成,我们需要列表式的协助。
tab+列表式+标签:
当产品的功能结构进一步复杂,这也给筛选功能增加了新的难题。以boss直聘来说,这里的筛选项主要分为四个:排序方式(推荐/)、工作地点、公司规模、岗位要求。其中后三个筛选项包含大量的条件,特别工作地点,需要进一步定位到街道或地铁站。对于这种多维度,深层级的筛选需求我们可以使用tab+列表式+标签的样式。
这里我选择boss直聘的另一个原因在于它的tab数用户是可以自己增减的,每一个tab代表一条求职意向,最多可以添加3条求职意向。
筛选体系的容器
筛选体系是由众多筛选项组成的,这些筛选项需要一个“容器”来承载。上面说的boss直聘用的是下拉列表,这种样式其实还比较简单的,我们可以看一些功能更加复杂一点的产品,比如各大电商平台。这里使用的是抽屉式筛选框,说它是抽屉式,因为它跟抽屉一样,用的时候可以拉出来,不用的时候可以关起来,节省了空间。从某个角度来说,我们可以把抽屉式看成列表式的一个放大版。抽屉式筛选框可以容纳更多的筛选条件,像我在上面提到的输入框,多选按钮都可以在这里使用。
从底部弹出的动作栏也比较常见,这里使用了滑块和单选按钮。
Airbnb的筛选功能以浮层为载体,还使用比较少见的switch和stepper。
当然Airbnb筛选功能最大的亮点在于可以向用户即时反馈筛选结果的数目,用户不太可能会进入搜索结果为0的空页面,避免无效操作。
以上说的筛选体系都比较传统,大部分都是基于对现有结果进行筛选,其实我们可以对筛选功能进行前置。例如,我们可以在用户进行搜索之前就对结果进行筛选。
甚至在新用户第一次使用产品的时候,可以让用户填写一些个人信息以便进行个性化推送。
筛选功能的存在意义在于帮助用户对功能信息进行快速的定位,对筛选功能进行适度的前置可以简化用户的操作流程,同样可以达到节省用户时间的目的。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
2、读取json文件的service层实现
3、controller对应的代码片段
4、html页面 将jsonarray转换成js对象
5、对js对象遍历 $.append动态添加到对应页面
6、效果如下图
社交软件已然成为现今人们沟通交流的主要媒介,那什么样的对话页面更大家受欢迎呢?对话页面的ui要怎么设计呢?下面列举12个国外社交app ui设计案例供设计师盆友们参考。
jquery是一个轻量级的JS框架,这点相信大部分人都听过,而jquery之所以有这样一个称呼,就是因为它悄悄披了一件外衣,将自己给隐藏了起来。
/以下截取自jquery源码片段
(function( window, undefined ) {
/* 源码内容 */
})( window );
上面这一小段代码来自于1.9.0当中jquery的源码,它是一个无污染的JS插件的标准写法,专业名词叫闭包。可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行,就像下面这样,会直接弹出字符串。
(function( window, undefined ) {
alert("Hello World!");
})( window );
可以看出来这样写的直接效果,就相当于我们直接弹出一个字符串。但是不同的是,我们将里面的变量变成了局域变量,这不仅可以提高运行速度,更重要的是我们在引用jquery的JS文件时,不会因为jquery当中的变量太多,而与其它的JS框架的变量命名产生冲突。对于这一点,我们拿以下这一小段代码来说明。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
})( window );
alert(temp);
这段代码的运行结果是Hello而不是ByeBye,也就是说闭包中的变量声明没有污染到外面的全局变量,倘若我们去掉闭包,则最终的结果会是ByeBye,就像下面这样。
var temp = "Hello World!";
// (function( window, undefined ) {
var temp = "ByeBye World!";
// })( window );
alert(temp);
由此就可以看出来,jquery的外衣就是这一层闭包,它是很重要的一个内容,是编写JS框架必须知道的知识,它可以帮助我们隐藏我们的临时变量,降低污染。
刚才我们说了,jquery将自己声明的变量全部都用外衣遮盖起来了,而我们平时使用的Jquery和$,却是真真实实的全局变量,这个是从何而来,谜底就在jquery的某一行代码,一般是在文件的末尾。
window.jQuery = window.$ = jQuery;
这一句话将我们在闭包当中定义的jQuery对象导出为全局变量jQuery和$,因此我们才可以在外部直接使用jQuery和$。window是默认的JS上下文环境,因此将对象绑定到window上面,就相当于变成了传统意义上的全局变量,就像下面这一小段代码的效果一样。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
window.temp = temp;
})( window );
alert(temp);
很明显,它的结果应该是ByeBye,而不是Hello。因为我们在闭包中导出了temp局部变量为全局变量,从而覆盖了第一行声明的全局变量temp。
jquery最核心的功能,就是选择器。而选择器简单理解的话,其实就是在DOM文档中,寻找一个DOM对象的工具。
首先我们进入jquery源码中,可以很容易的找到jquery对象的声明,看过以后会发现,原来我们的jquery对象就是init对象。
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
jQuery.fn = jQuery.prototype;
jQuery.fn.init.prototype = jQuery.fn;
这两句话,第一句把jQuery对象的原型赋给了fn属性,第二句把jQuery对象的原型又赋给了init对象的原型。也就是说,init对象和jQuery具有相同的原型,因此我们在上面返回的init对象,就与jQuery对象有一样的属性和方法。
很多时候,我们在jQuery和DOM对象之间切换时需要用到[0]这个属性。从截图也可以看出,jQuery对象其实主要就是把原生的DOM对象存在了[0]的位置,并给它加了一系列简便的方法。这个索引0的属性我们可以从一小段代码简单的看一下它的由来,下面是init方法中的一小段对DOMElement对象作为选择器的源码。
// Handle $(DOMElement)
if ( selector.nodeType ) {
/* 可以看到,这里将DOM对象赋给了jQuery对象的[0]这个位置 */
this.context = this[0] = selector;
this.length = 1;
return this;
}
这一小段代码可以在jquery源码中找到,它是处理传入的选择参数是一个DOM对象的情况。可以看到,里面很明显的将jQuery对象索引0的位置以及context属性,都赋予了DOM对象。代码不仅说明了这一点,也同时说明了,我们使用$(DOMElement)可以将一个DOM对象转换为jQuery对象,从而通过转换获得jQuery对象的简便方法。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
目前做的项目是ionic3和angular4.0的结合,所以用到了很多关于ionic3中封装好的标签,例如具有轮播效果的ion-slides和ion-slide等。那么这次就要总结一下另外一个标签ion-segment的用法了。
Segment 在头部使用
Segment 在内容里面使用
Segment 在表单里面使用
ion-segment这个标签以前用的很少,几乎没有用过。它主要是一组按钮,有时称为分段控件,之前都是用button按钮,现在知道了,开始用ion-segment,因为它有自带的样式,这样就可节省很多时间,同时呢允许用户与许多控件的紧凑组进行交互。 分段提供与标签相似的功能,选择一个将取消选择所有其他选项。 当您希望让用户在应用程序的不同页面之间来回移动时,应使用选项卡栏而不是分段控件。 您可以使用Angular的ngModel或FormBuilder API。
下面来看一段代码:
<ion-header> <ion-toolbar> <ion-segment [(ngModel)]="icons" color="secondary"> <ion-segment-button value="camera"> <ion-icon name="camera">带iocn</ion-icon> </ion-segment-button> <ion-segment-button value="bookmark"> 头部使用Segment <ion-icon name="bookmark"></ion-icon> </ion-segment-button> </ion-segment> </ion-toolbar> </ion-header>
<ion-segment [(ngModel)]="relationship" color="primary" (ionChange)="segmentChanged($event)"> <ion-segment-button value="friends"> Segment 在内容里面使用 </ion-segment-button> <ion-segment-button value="enemies"> 可以绑定一个事件(ionChange) </ion-segment-button> </ion-segment>
<form [formGroup]="myForm"> <ion-segment formControlName="mapStyle" color="danger"> <ion-segment-button value="standard"> Standard </ion-segment-button> <ion-segment-button value="hybrid"> 表单内使用 </ion-segment-button> <ion-segment-button value="sat"> Satellite </ion-segment-button> </ion-segment> </form>
Segment 配合ngSwitch使用
<ion-segment [(ngModel)]="change"> <ion-segment-button value="apple"> 苹果 </ion-segment-button> <ion-segment-button value="pie"> 梨 </ion-segment-button> </ion-segment> <div [ngSwitch]="change"> <div *ngSwitchCase="'apple'">
苹果显示,如果要默认显示一个就把默认的那个设置一个初始值比如要默认显示苹果就把苹果的value值设置成change也就是说,在定义change变量的时候,需要把哪个设置为默认显示就把哪个的value值赋值给change作为初始值 public change=”pie”;
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
蓝蓝设计的小编 http://www.lanlanwork.com