在前面的学习中我们了解到函数也是对象。注意:函数是对象,对象不一定是函数,对象中有__proto__原型,函数中有prototype原型,如果一个东西里面有prototype,又有__proto__,说明它是函数,也是对象。
对象都是由构造函数创建出来的,函数既然是对象,创建它的构造函数又是什么呢?事实上所有的函数实际上都是由Function构造函数创建出来的实例对象。
所以我们可以使用Function构造函数创建函数。
语法:newFunction(arg1,arg2,arg3..,body);arg是任意参数,字符串类型的。body是函数体。
3函数内this的指向函数的调用方式决定了this指向的不同:
了解了函数this的指向之后,我们知道在一些情况下我们为了使用某种特定环境的this引用,需要采用一些特殊手段来处理,例如我们经常在定时器外部备份this引用,然后在定时器函数内部使用外部this的引用。然而实际上JavaScript内部已经专门为我们提供了一些函数方法,用来帮我们更优雅的处理函数内部this指向问题。这就是接下来我们要学习的call、apply、bind三个函数方法。call()、apply()、bind()这三个方法都是是用来改变this的指向的。
call()方法调用一个函数,其具有一个指定的this值和分别地提供的参数(参数的列表)。apply()方法调用一个函数,其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数。
注意:call()和apply()方法类似,只有一个区别,就是call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组。
call语法:
fun.call(thisArg[,arg1[,arg2[,...]]])call参数:
apply语法:
fun.apply(thisArg,[argsArray])apply参数:
apply()与call()相似,不同之处在于提供参数的方式。apply()使用参数数组而不是一组参数列表。例如:
apply和call都可以改变this的指向。调用函数的时候,改变this的指向:
总结
apply的使用语法:1函数名字.apply(对象,[参数1,参数2,...]);2方法名字.apply(对象,[参数1,参数2,...]);call的使用语法1函数名字.call(对象,参数1,参数2,...);2方法名字.call(对象,参数1,参数2,...);它们的作用都是改变this的指向,不同的地方是参数传递的方式不一样。
如果想使用别的对象的方法,并且希望这个方法是当前对象的,就可以使用apply或者是call方法改变this的指向。
bind()函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体(在ECMAScript5规范中内置的call属性)。当目标函数被调用时this值绑定到bind()的第一个参数,该参数不能被重写。绑定函数被调用时,bind()也可以接受预设的参数提供给原函数。一个绑定函数也能使用new操作符创建对象:这种行为就像把原函数当成构造器。提供的this值被忽略,同时调用时的参数被提供给模拟函数。bind方法是复制的意思,本质是复制一个新函数,参数可以在复制的时候传进去,也可以在复制之后调用的时候传入进去。apply和call是调用的时候改变this指向,bind方法,是复制一份的时候,改变了this的指向。
语法:
fun.bind(thisArg[,arg1[,arg2[,...]]])参数:
返回值:
返回由指定的this值和初始化参数改造的原函数的拷贝。
示例1:
示例2:
函数可以作为参数,也可以作为返回值。
函数是可以作为参数使用,函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号。
作为返回值排序案例:
第一种方法是需要把所有图片一张张摆好,然后慢慢移动的,
但是我能不能直接不摆就硬移动呢?
如果你使用过vue的transition,我们是可以通过给每一张图片来添加入场动画和离场动画来模拟这个移动
这样看起来的效果就是图片从右边一直往左移动,但是这个不一样的地方是,我们每一个元素都有这个进场动画和离场动画,我们根本不用关心它是第几个元素,你只管轮播就是。
很简单,我们自己实现一个transtition的效果就好啦,主要做的是以下两点
functionhide(el){el.className=el.className.replace('slide-enter-active','')el.className+='slide-leave-active'el.addEventListener('animationend',animationEvent)}functionanimationEvent(e){e.target.className=e.target.className.replace('slide-leave-active','')e.target.style.display='none'e.target.removeEventListener('animationend',animationEvent)}functionshow(el){el.style.display='flex'el.className+='slide-enter-active'}这里我们使用了animationend来监听动画结束,注意这里每次从新添加类的时候需要重新添加监听器,不然会无法监听。如果不使用这个方法你可以使用定时器的方式来移除leave-active类。
functionhide(el){el.className=el.className.replace('slide-enter-active','')el.className+='slide-leave-active'setTimeout(()=>
{//动画结束后清除classel.className=el.className.replace('slide-leave-active','')
.slide-enter-active{position:absolute;animation:slideInease.5sforwards;}.slide-leave-active{position:absolute;animation:slideOutease.5sforwards;}@keyframesslideIn{0%{transform:translateX(100%);}100%{transform:translateX(0);}}@keyframesslideOut{0%{transform:translateX(0);}100%{transform:translateX(-100%);}}需要注意的是这里的forwards属性,这个属性表示你的元素状态将保持动画后的状态,如果不设置的话,动画跑完一遍,你的元素本来执行了离开动画,执行完以后会回来中央位置杵着。这个时候你会问了,上面的代码不是写了,动画执行完就隐藏元素吗?
很简单,我们进一个新元素的时候同时移除旧元素即可,两者同时执行进场和离场动画即可。
手机UI中的交互是保持产品鲜活生命力的源动力。好的交互可以帮助用户快速地获得反馈,认知布局,增强体验感和沉浸感。这里为大家整理了一些优秀并富有创意的交互作品,为你的产品设计注入灵感。
--手机appUI设计--
写在前面
在平时的设计过程当中,你可能会有这样的疑惑,为什么在大部分APP中,当单个按钮和多个按钮同时存在时,最重要的按钮一般都会放置在页面的右侧呢?如果最重要的按钮放在左侧又有什么问题呢?按钮放在右侧的原因是什么呢?它又有什么理论依据呢?接下来带着这些疑问,开始我们今天所要介绍的内容:交互心理学之古腾堡原则
古腾堡原则的起源
古腾堡原则是由14世纪西方活字印刷术的发明人约翰·古腾堡提出,早在20世纪50年代,他在设计报纸的过程中,提出了一项原则,认为人的阅读方式应该是遵循某种习惯进行的,就像读书一样,由左到右,从上到下。这其中蕴含着什么信息呢?经过研究最终得出被后人所熟知的结论:古腾堡原则,并附上了一张图,名为「古腾堡图」。古腾堡图将画面所呈现的内容分成四个象限:
1、第一视觉区(POA):左上方,用户首先注意到的地方
2、强休息区(SFA):右上方,较少被注意到
3、弱休息区(WFA):左下方,最少被注意到
4、终端视觉区(TA):右下方,视觉流终点
遵循古腾堡原则把关键信息放在左上角、中间和右下角,能够更好的体现元素的重要性。例如:我们平时所看到的页面弹窗、各种证明文件和合同文件等等。
古腾堡图通过对设计元素的重量与元素布局和组成方式进行调和,指导眼睛的运动轨迹。让用户迅速获取有价值的信息,同时用户对信息的熟悉程度也是影响眼睛运动轨迹的因素之一。
而随着互联网的兴起,古腾堡原则也逐渐被应用到APP设计和网页设计当中。接下来让我们来看看他在界面中的实际应用。
在设计中的应用
1.1底部单个按钮
这种形式在引导用户操作的页面中最为常见,为了能够保证用户对内容进行阅读,所以将按钮摆放在页面底部,内容放在顶部,这样的摆放即符合用户由上到下的阅读习惯又达到了产品预期的目标。
1.2底部垂直双按钮
那么,按照古腾堡原则,重要的按钮应该放在页面最底部,原则上它应该是这样的:
为了保证「同意」与「拒绝」这两个独立的按钮能够被用户足够的重视,并且其中的任意一个按钮不会被轻易的忽略掉,这里将「同意」按钮颜色加重,并且放在「拒绝」按钮之上,让眼睛原本垂直向下的运动轨迹产生回流的变化。
小结
原则是设计的基础,并非一成不变,要合理权衡设计原则与产品目标之间的关系。
2、顶部按钮分析
3、水平按钮分析
平常我们所看到的弹窗,推荐按钮都是在右侧,那么将推荐按钮放在左侧会怎么样?如下图所示:
不难看出推荐按钮放在右侧后,视觉在水平方向轴上产生了回流。
弹窗的目的是想让用户点击「确认」按钮,如果将「确认」放在左侧,根据古腾堡原则,用户的视线会不由自主的向右侧移动,也就是「取消」按钮的位置,想要回到左侧「确认」按钮位置就需要移动视线,并且眼睛的运动轨迹会在水平方向轴上来回的往复运动,无形中增加了用户选择时长。如果将「确认」放在右侧,「取消」放在左侧则可以为用户提高操作效率。
在实际产品中的应用案例:
当产品想要让用户进行某种操作时,主要按钮放在右边
1、古腾堡图第一视觉区,强休息区,弱休息区,终端视觉区
2、原则是设计的基础,并非一成不变,要合理权衡设计原则与产品目标之间的关系
4、当产品想要让用户进行某种操作时,主要按钮放在右边
垂直居中基本上是入门CSS必须要掌握的问题了,我们肯定在各种教程中都看到过“CSS垂直居中的N种方法”,通常来说,这些方法已经可以满足各种使用场景了,然而当我们碰到了需要使用某些特殊字体进行混排、或者使文字对齐图标的情况时,也许会发现,无论使用哪种垂直居中的方法,总是感觉文字向上或向下偏移了几像素,不得不专门对它们进行位移,为什么会出现这种情况呢?
对于中文字体,本身的设计上没有基线、升部、降部等说法,每个字都在一个方形盒子中。但是在计算机上显示时,也在一定程度上沿用了西文字体的概念,通常来说,中文字体的方形盒子中文字体底端在baseline和descender之间,顶端超出一点ascender,而标点符号正好在baseline上。
constemSize=2048;constascent=1854;constdescent=434;constcapitalHeight=1467;
//计算前需要已知给定的字体大小constfontSize=FONT_SIZE;//根据文字大小,求得文字的偏移constverticalAlign=((ascent-descent-capitalHeight)/emSize)*fontSize;return(
由此设置以后,外层span将表现得像一个普通的可替换元素参与行内的布局,在一定程度上无视字体metrics的差异,可以使用各种方法对其进行垂直居中。由于这种方案具有固定的计算步骤,因此可以根据具体的开发需求,将其封装为组件、使用CSS自定义属性或使用CSS预处理器对文本进行处理,通过传入字体信息,就能修正文字垂直偏移。
ECMAScript模块(简称ES模块)是一种JavaScript代码重用的机制,于2015年推出,一经推出就受到前端开发者的喜爱。在2015之年,JavaScript还没有一个代码重用的标准机制。多年来,人们对这方面的规范进行了很多尝试,导致现在有多种模块化的方式。
你可能听说过AMD模块,UMD,或CommonJS,这些没有孰优孰劣。最后,在ECMAScript2015中,ES模块出现了。
我们现在有了一个“正式的”模块系统。
理论上,ES模块应该在所有JavaScript环境中。实际上,ES模块的主要应用还是在浏览器上。
ECMAScript模块要想在任何JavaScript环境通用,可能还需要很长的路要走,但方向是正确的。
//utils.jsexportfunctionfuncA(){return"Hellonamedexport!";}exportdefaultfunctionfuncB(){return"Hellodefaultexport!";}这里有两个导出。
第一个是命名导出,后面是exportdefault,表示为默认导出。
假设我们的项目文件夹中有一个名为utils.js的文件,我们可以将这个模块提供的对象导入到另一个文件中。
假设我们在项目文中还有一个Consumer.js的文件。要导入utils.js公开的函数,我们可以这样做:
//consumer.jsimport{funcA}from"./util.js";这种对应我们的命名导入方式.
如果我们要导入utils.js中的默认导出也就是funcB方法,我们可以这样做:
//consumer.jsimport{funcA}from"./util.js";当然,我们可以导入同时导入命名和默认的:
//consumer.jsimportfuncB,{funcA}from"./util.js";funcB();funcA();我们也可以用星号导入整个模块:
import*asmyModulefrom'./util.js';myModule.funcA();myModule.default();注意,这里要使用默认到处的方法是使用default()而不是funcB()。
从远程模块导入:
myModule.js内容如下:
exportfunctionappendResult(element){constresult=Math.random();element.innerText+=result;}动态导入ES模块是静态的,这意味着我们不能在运行时更改导入。随着2020年推出的动态导入(dynamicimports),我们可以动态加载代码来响应用户交互(webpack早在ECMAScript2020推出这个特性之前就提供了动态导入)。
考虑下面的代码: