混合指令的出现使你可以定义在样式表中重复使用的样式,这可以使你免去编写过多重复的样式,而且在混合指令 @mixin 中你也可以做一些逻辑处理。混合指令是一个很好用的指令,它将帮你更合理的维护样式代码,学会这种方式写起样式来也很便利,下面我们开始详细的讲解它。
我们可以混合使用这些命令,比如查找文件后定位到某个关键字处。比如base.js@xx,就可以跳转到base.js的一个函数里。
混合指令的定义是在 @mixin 后跟指令名字和 {} ,在 {} 中你可以写一些样式,同时也可以用一些函数或者前面章节讲的控制指令,现在我们定义一个不接收参数的混合指令和一个接收参数的混合指令:// 不接收参数的混合指令@mixin border { border: { width: 1px; color: #cccccc; style: solid; }}// 接收参数的混合指令@mixin font($size: 12px, $weight: 100) { font: { family: "Myfont"; weight: $weight; size: $size; }}.box { // 引用混合指令 @include border;}.item { // 引用混合指令并传参 @include font(20px, 500);}上面的代码中我们分别定义了两个简单的混合指令,然后在 .box 和 .item 的样式中通过 @include 引用混合指令,在 @include 后直接跟混合指令的名称就可以引用了,传参如上面代码所示,那么上面这段代码将会转换为如下的 CSS 代码:.box { border-width: 1px; border-color: #cccccc; border-style: solid;}.item { font-family: "Myfont"; font-weight: 500; font-size: 20px;}看到转换后的 CSS 代码是不是感觉混合指令很强大,我们把指令写好后,可以在任何需要它的地方来使用,而且我们只需要传参就可以生成各种各样的样式代码。还有一点需要注意的是,在 Sass 中,@minxin 后面的名字将连字符和下划线视为是相同的!
在学习混合开发之前,我们先来了解一下混合开发的含义,帮助大家更好的理解。
以本小节所有数据全部连接查询为例:SELECT * FROM student a LEFT JOIN student_course b ON a.id=b.student_id RIGHT JOIN course c ON b.course_id=c.id INNER JOIN teacher d ON c.teacher_id=d.id;执行结果如下图:Tips:多表混合连接查询时,后面可以把前面执行的结果集整体当成一个表,例如 SELECT * FROM student a LEFT JOIN student_course b ON a.id=b.student_id RIGHT JOIN course c ON b.course_id=c.id 可以理解为 student 和 student_course 左连接查询之后的结果集再对 course 右连接查询。
2.1.1 原生开发原生开发一般是指用原生语言进行开发,原生开发语言就是官方提供的开发语言,比如 IOS 是利用 Objective-C 和 Xcode 进行开发、小程序是用微信小程序原生语言和微信开发者工具进行开发。2.1.2 混合开发混合开发是指开发一个项目应用时,为了提高运行效率或者开发效率,将各种开发技术进行混合应用的开发形式。混合开发将各种开发方式取长补短,虽然比原生开发更难上手,但是架不住开发效率和运行效率的优势,现在比较大型的应用项目都会用混合开发来进行项目开发。uni-app 的混合开发主要是为了实现一些 uni-app 框架无法实现的功能,或者扩展接入一些第三方的 SDK。
再来看看帧动画是什么样的效果:896运行结果:可以看到是一帧帧播放的,帧数低的时候有种卡卡的感觉,好像一下一下的分步骤从黄色变成绿色的。那我们把帧数提高一下不就看不到一卡一卡的感觉了吗?来试试看:897运行结果:虽然效果一样了,但是怎么感觉更麻烦了呢?还要自己去指定帧数,而过渡动画都是全自动的,帧动画是不是不如过渡动画呢?实际上并不是这样的,帧动画有着自己的适用场景。接下来我们就来探讨一下何时适合帧动画,何时又适合过渡动画。
首先使用过渡动画看看会是什么效果:900运行结果:过渡动画确实是好,但是在这种情况下真的不适合用它。
要使用 uni-app 和原生 App 进行混合开发之前,要先确认要用 uni-app 还是原生 App 代码作为主体。
在前面已经介绍,接口可以描述函数、对象的方法或者对象的属性。有时希望一个对象同时具有上面提到多种类型,比如一个对象可以当做函数使用,同时又具有属性和方法。interface Counter { (start: number): string; interval: number; reset(): void;}function getCounter(): Counter { let counter = function (start: number) { } as Counter; counter.interval = 123; counter.reset = function () { }; return counter;}let c = getCounter();c(10);c.reset();c.interval = 5.0;代码解释:第 1 行,声明一个接口,如果只有 (start: number): string 一个成员,那么这个接口就是函数接口,同时还具有其他两个成员,可以用来描述对象的属性和方法,这样就构成了一个混合接口。第 7 行,创建一个 getCounter() 函数,它的返回值是 Counter 类型的。let counter = function (start: number) { } as Counter;第 8 行,通过类型断言,将函数对象转换为 Counter 类型,转换后的对象不但实现了函数接口的描述,使之成为一个函数,还具有 interval 属性和 reset() 方法。断言成功的条件是,两个数据类型只要有一方可以赋值给另一方,这里函数类型数据不能赋值给接口类型的变量,因为它不具有 interval 属性和 reset() 方法。类型断言在之后的小节也会单节介绍。
在上面的代码中我们已经知道了混合指令是可以传参数的,参数是在指令名后面由括号括起来的变量名列表,混合指令每次调用都可以操作这些传入的参数。这些参数只要声明了就必须传入,如果你想让某个参数成为可选的,你需要为这个参数赋一个默认值,赋默认值的方法就像变量声明赋值一样,直接在变量名后面加冒号然后跟默认值。我们举例看下:// 没有赋默认值的参数@mixin font-one($size, $weight) { font: { family: "Myfont"; weight: $weight; size: $size; }}// 赋默认值的参数@mixin font($size: 12px, $weight: 100) { font: { family: "Myfont"; weight: $weight; size: $size; }}从上面的代码中可以看出是否赋默认值的区别,默认值还可以引用前面的参数。除了默认值,在传入参数的时候我们还可以按名称传入参数,什么意思呢,我们直接举例看下:@mixin font($size: 12px, $weight: 100) { font: { family: "Myfont"; weight: $weight; size: $size; }}.item { // 按名称传入参数 @include font-one(20px, $weight: 800);}上面这段代码将会转换为如下的 CSS 代码:.item { font-family: "Myfont"; font-weight: 800; font-size: 20px;}按名称传入参数使我们可以更好的控制混合指令接收的参数,但这个方法还是尽量少用,因为参数名有时在多人开发的时候可能不是一成不变的!有时候 @mixin 接收的参数个数你可能不不清楚有多少个,那么你可以将最后一个参数以 … 结尾,那么所有额外的参数都将传给该参数,然后在 @mixin 里来获取所有参数,我们举个例子直观的感受下:@mixin fonts($s, $familys...) { font:{ size: $s; family: $familys; }}.p { @include fonts(12px, "one", "two", "three")}上面这段代码转换为 CSS 代码如下:.p { font-size: 12px; font-family: "one", "two", "three";}除此之外,@mixin 还可以通过参数列表接收任意参数,然后通过 meta.keywords() 这个函数来使用传入的这些参数,我们下面举例看下:@mixin args($args...) { @each $key, $val in keywords($args) { font: $key $val; }}.p { @include args($one: 1, $two: 2, $three: 3)}上面这个例子是为了让你更直观的看到这种传参方式,实际样式中不会这么写,上面这段代码我们通过循环 keywords() 函数返回的值来使用传入的参数,它将会被转化成如下的 CSS 代码:.p { font: one 1; font: two 2; font: three 3;}混合指令在传参这块还是有挺多方式的,你可以根据实际的需求来自行选择上面的传参方式,这使得我们用起它来很灵活。
开始之前,我先拿现实生活中画一条线段的流程来类比我们在 canvas 中绘制线段。在现实中,我们如何去画一条线段呢?我们暂且就按下面的流程来做一遍:拿到一张白纸(画布);铅笔移动到起点;开始描线到终点(类似于素描中的打线);选择一种有颜色的画笔;开始描边(画出轮廓线)。在 canvas 中,我们也是按这个流程来绘制一条线段的。先看整体案例:1410运行结果:我们将上面的例子类比现实中画线的流程拆分讲解:拿到一张白纸类比我们获取到 canvas 的渲染上下文。const canvas = document.getElementById('imooc');const ctx = canvas.getContext('2d');我们开始铅笔打线,先把铅笔移动到 (100,100) 这个点,这里使用的方法是:moveTo(x,y),参数为起点坐标。ctx.moveTo(100, 100)我们用铅笔从起点画一个路径到终点,也就是 (200,300) 这个点,这里使用的方法是:lineTo(x, y),参数为终点坐标。ctx.lineTo(200,300)选择一个画笔,这里我们设定为绿色的画笔,这是使用了 strokeStyle 属性,这里需要注意属性和方法的区别,直观的理解就是:属性是一个变量,方法是一个函数。ctx.strokeStyle = "green"开始用画笔描边,这里使用的方法是:stroke(),这个方法没有参数。ctx.stroke()到这里,我们就完成了一条线段的绘制。
uni-app 和原生小程序混合开发问题 uni-app 官网已经描述的很清楚了,我们直接查看官网资料就可以。参考资料:https://uniapp.dcloud.io/hybrid
目前大部分的互联网公司都支持远程笔试和面试,具体的流程如下:笔试流程在候选人投递简历之后,企业会提前发送笔试邮件告知候选人。因为候选人投递简历的时间比较分散,所以互联网企业一般会将候选人分为不同的批次,被分到同一批次的用户参加同一场笔试,笔试题型一般分为选择题、问答题、编程题,笔试时间一般是一个半小时到两个小时。因为问答题需要人为改卷,选择题和编程题都可以系统自动判定分数,所以选择题+编程题的出题方式比较常见,其中编程题大多是2到4道,主要都是算法题,完成语言不限制(一般都支持C++、Java、Python、Javascript这几种语言)。
柱状图支持动画效果,只需设置 animation = true 即可启动动画功能。与动画相关配置包括:配置名类型默认值说明animationbooleanfalse是否启动动画效果animationThresholdnumber2000关闭动画的阈值,在 animation = true 的情况下,若数据量超过该值则关闭动画效果animationDurationnumber | function1000初始动画的时长animationEasingstringcubicOut初始动画的缓动效果animationDelaynumber | function初始动画的延迟animationDurationUpdatenumber300数据更新动画时长animationEasingUpdatestringcubicOut数据更新动画的缓动效果animationDelayUpdatenumber | function数据更新动画的延迟默认配置下,只需设置 animation = true 即可启动动画效果,简单示例:1361示例效果:与 CSS3 动画类似,下列属性可以微调动画执行的细节:animationDuration: 初始动画执行周期;animationEasing: 初始动画的缓动效果,只能使用内置的缓动函数,可选值请参考 缓动示例;animationDelay: 初始动画延迟时间,支持数值或函数类型。通过设置,可以调整出更加生动的动画效果,例如在上例基础上设置如下属性:{ animation: true, animationEasing: 'elasticOut', animationDuration: function(index) { return index * 300; },}示例效果如下:细心的读者应该已经注意到,上述配置表中存在两类属性,一是初始动画,即图表首次渲染动画;二是数据更新动画,即在图表初始化后,通过调用 setOption 或 appendData 函数促使数据发生变化时执行的动画效果,相关属性包括:animationDurationUpdate:数据更新动画执行周期;animationEasingUpdate:数据更新动画的缓动效果,只能使用内置的缓动函数,可选值请参考 缓动示例;animationDelayUpdate:数据更新动画延迟时间。例如在上例基础上,动画配置修改为:{ animation: true, animationEasingUpdate: 'elasticOut', animationDurationUpdate: function(index) { return index * 100; },}注意初始化与插入数据时,动画效果的差异:
本章节我们主要介绍 Vue.js 的过渡效果与动画效果。包括如何编写自定义 CSS 动画、如何配合第三方 CSS 动画库、过渡钩子函数的使用、如何使用第三方 JavaScript 动画库。本小节的内容相对之前有些难度,同学们在阅读一遍之后如果不能完全掌握,建议反复阅读,并把本小节的所有案例自己实现一遍,相信通过多次的练习一定可以掌握。
我们需要的是一张图片一张图片的去显示,也就是一帧代表一张图片,我们换成帧动画再来试一下:901运行结果:这次看起来是不是就是我们想要的结果了呢。帧动画有些类似于我们小时候翻书,翻书翻得快了里面的图案似乎就动起来了:所以设置一个合理的翻书时间是很有必要的,翻书时间太长就代表翻的慢了,图像就不会那么的连贯。
画布元素最早是 Safari 浏览器在 1.3 版本引入的,为了解决在 dashboard 组件中支持脚本控制的图形,之后 Firefox1.5 和 Opera9 先后支持了画布元素,目前画布已经是 HTML5 中正式的标签元素了。
有时候想要的动画并不是缩小、放大或者变个颜色之类的这么简单,比如我们需要一个复杂的形变加上复杂的运动轨迹,此时过渡动画就有些相形见绌了。虽然 Canvas 或 SVG 能够实现复杂逻辑的动画效果,但是毕竟不是人人都会这种技术。而且有时候开发时间有限,没有时间用代码来绘制一个炫酷动画,所以这个时候帧动画,配上雪碧图就是最完美的选择。我们用一张条形雪碧图来试一下:
上例的问题是从 init 到 setOption 这段时间内,图表容器没有内容,一片空白,可能会让用户误解为 bug,因此需要给容器加上 loading 效果以提示用户正在加载数据。echarts 内置了一套简单的加载动画效果,通过 echartInstance.showLoading 方法触发;通过 echartInstance.hideLoading 方法关闭,例如:1303示例效果:echartInstance.showLoading 函数签名如下:(type?: string, opts?: Object) => void参数:type:可选,加载动画类型,目前只支持 ‘default’;opts:可选,加载动画配置项,默认配置项:{ text: 'loading', color: '#c23531', textColor: '#000', maskColor: 'rgba(255, 255, 255, 0.8)', zlevel: 0}提示:echarts 目前只提供了一种加载动画样式,而且没有对外暴露加载动画的扩展接口。如果应用场景要求使用自定义动画,可以自行实现,在图表容器上覆盖一层遮罩层,并在遮罩层上叠加加载动画效果。
本章介绍 HTML 中用来绘图的元素画布。它是 HTML5 中新增的元素,通过使用 JavaScript 调用画布的函数可以控制画布中的每个像素,用来生成图形、字符或者图像。画布元素本身没有绘图功能,初始化定义的画布没有任何视觉效果,必须通过 JavaScript 拿到画布的 id,然后控制画布的绘制功能。所以想要使用画布,必须对 JavaScript 有一定的了解。画布牵涉到很多知识点,本章介绍简单的画布创建以及几种简单的基础形状绘制。
2.2.1 原生开发优缺点有过开发经验的小伙伴看到版本问题应该非常感同深受吧,经常会冷不丁的出现版本不兼容的问题。只要出现版本问题,重新布置开发环境是常有的事情。而原生开发受到版本问题限制会比较小,官方的代码和开发工具都是定时更新,兼容性、安全性、维护性也会更高一些。而原生开发普遍存在着开发时间长、效率低、成本高的问题。相比 uni-app,适用性也比较差,一款原生的 App,不同平台上面发布同样的项目,需要开发几套不同的代码,这样对我们开发的限制也很大。2.2.2 混合开发优缺点采用混合开发,我们可以采取各开发技术的优点,取长补短,可以提高代码的运行效率,功能扩展性上也会更好一些。混合开发是缺点就是对开发人员技术要求比较高,需要花更多时间熟悉。并且因为涉及到多种开发方式,维护会更加麻烦一些,版本兼容问题也会比较多。
结构体最为一种变量的集合,可以将各种类型的变量组成一个集合。方便我们完成需要多种变量组合才能完成的操作。其实几个的应用非常的广泛,除了通讯录,还有比如系统存储鼠标位置,画笔,一些常见的数据结构等等。
重点是如何进行调用,先来看一下语法:/* 清除浏览器默认边距 */* { padding: 0; margin: 0; }body { /* 这段代码是为了居中显示,不是重点,看不懂的话可以无视 */ height: 100vh; display: flex; align-items: center; justify-content: center; /* 添加背景图 */ background: url(../img/bg.jpg) center / cover;}.animate { width: 130px; height: 130px; background: url(../img/rect.png); /* 动画: 动画名(loading) 时长(0.6秒) 运行方式(step-end) 动画次数(3次) 填充模式(双向) */ animation: loading .6s step-end 3 both, /* 动画可以定义多个,每个动画用逗号分隔。*/ /* 第二个动画的动画名(animate) 时长(0.8秒) 运行方式(step-end) 延时(1.8秒) 动画次数(无限) */ animate .8s steps(12) 1.8s infinite;}/* 定义动画:动画名(loading) */@keyframes loading { from { background-position: 0 0 } /* 第一个数字代表x轴坐标,第二个数字代表y轴坐标 */ 10% { background-position: -130px 0 } /* x坐标:-130 y坐标:0 */ 20% { background-position: -260px 0 } /* x坐标:-260 y坐标:0 */ 30% { background-position: -390px 0 } /* x坐标:-390 y坐标:0 */ 40% { background-position: -520px 0 } /* x坐标:-520 y坐标:0 */ 50% { background-position: 0 -130px } /* x坐标:0 y坐标:-130 */ 60% { background-position: -130px -130px } /* x坐标:-130 y坐标:-130 */ 70% { background-position: -260px -130px } /* x坐标:-260 y坐标:-130 */ 80% { background-position: -390px -130px } /* x坐标:-390 y坐标:-130 */ 90% { background-position: -520px -130px } /* x坐标:-520 y坐标:-130 */ /* 修改最后一帧,以便动画结束后盒子就应用最后一帧的样式 */ to { /* 下一个动画的宽高 */ width: 216px; height: 300px; /* 下一个动画的雪碧图 */ background-image: url(../img/animate.png); }}/* 定义动画:动画名(animate) */@keyframes animate { from { background-position: 0 } to { background-position: -2600px }}运行结果:这是怎么个原理呢?原来调用动画的时候可以一次性调用多个动画,动画与动画直接用逗号进行分隔。第一个加载动画我们让他重复运行 3 次,由于下一个动画的背景图和宽高都和加载动画不同,所以调用第一个动画时用填充模式将最后一帧定义的样式应用到下个动画上。
声明完画布之后,画布标签本身除了高度和宽度之外基本上不再包含其他可以用于绘图的属性,所以想要操控画布必须获取到它提供的绘图 SDK 对象。var context = a.getContext(contextID)通过 getContext 函数可以获取画布的 SDK 对象,在 HTML 中它被称为 CanvasRenderingContext2D 对象。CanvasRenderingContext2D 提供了一系列用于绘图的函数,其中包含以下几大类。颜色、样式、阴影线条样式矩形路径转换文本图像绘制像素操作合成其他
混入(Mixins)是面向对象编程中的一个比较重要的概念。本节将会通过一个实例逐步介绍混入是如何在 TypeScript 中使用的。
animation 是动画,而 transition 是过渡,它们用法很相似,但实际又不大相同,可以说 animation 是 transition 的升级版,它可以创建一个持续的自动执行动画。
在这里老师要先给大家介绍一种在 Dreamweaver CC 2018 中插入动画的方式,下面老师先简要介绍一种方式,这种方式其实在 Dreamweaver CC 2018 中很显眼,很容易被看到。第一步:我们还是新建一个空白的 HTML 文档。详细步骤不在此赘述,请大家主动翻阅前几节的慕课 wiki 文档自行学习。第二步:我们在右侧的面板中,选择动画合成,然后会弹出选择文件的画面,大家只要选择制作好的文件就可以了。由于资源需要到互联网上搜集,大家在互联网上很容易找到相关的资源,由于版权的问题,老师不方便在此处给大家展示选择后的动画效果。同学们应该课下自己多多练习。体会这种动画插入方式的便捷之处。下图是对 Dreamweaver CC 2018 右侧面板的展示。插入完成后,点击插入好的动画,我们依然可以在属性面板中看到长宽高的编辑界面,具体界面大家可以参考上一节的多媒体文件长宽的设置,那里有更详细的说明和指引。在这里我们只需要掌握一个简单动画的插入流程就可以,需要用的时候知道到哪里去寻找快捷操作方式即可。以上便是我们完完全全通过 Dreamweaver CC 2018 来为网页插入简单动画的基本过程!当然,由于大家的素材复杂程度不同,我们做出来的网页最终会因为动画效果的不同而内容大不相同,其实在这里老师要强调的是,动画素材的选择和内容的设计,要比动画的位置重要,合适的位置要比如何插入动画重要。所以大家要在网页中使用动画时素材的选择严加把控,符合网页的主题,不能顾此失彼,忙东忙西之间失去了网页的主题和设计目标。
想要混入定义好的 mixin,只需要通过组件的 mixins 属性传入想要混入的 mixin 数组即可:var vm = new Vue({ el: '#app', mixins:[myMixin]})代码解释:上述代码中,我们定义了一个 Vue 实例,并在实例上混入 myMixin。接下来我们看一个简单的示例:686代码解释:JS 代码第 3-17 行,定义了一个混入对象 myMixin,并定义了数据 data、钩子函数 created、方法 mixinFun。JS 代码第 20 行,通过组件实例上的 mixins 属性引入 myMixin。运行程序可以看到,在 myMixin 中定义的数据 name 渲染到页面上。同时打开控制台可以看到 ‘mixin function’ 被打印出来,说明 created 钩子函数被执行。
选择题一般是考察候选人的计算机基础知识,包含计算机网络、操作系统、计算机组成等。如果是特定的面试岗位,例如Java后端工程师,也可能会涉及到特定语法,例如考察 Java 的多线程相关知识。选择题一般靠看书,例如通过阅读《计算机网络:自顶向下方法》等教科书,况且目前网上有诸多已经整理好的开源题库,例如慕课网的相关教程。算法题则比较特殊,就笔者的观察,大部分的候选人在不做准备的情况下都缺乏解决困难笔试题的能力。因为即使是计算机专业的同学,所接受的大学编程通识教育,一般只涉及基础的数据结构教程。在约定的笔试时间内,对于没有经过特定训练的候选人,还可能受到紧张等心理因素的影响,往往会难以编写无误的代码,最终结果只能无缘面试。笔试考察的算法题难度浮动比较大,涵盖的知识也从基础的数据结构,例如堆栈和二叉树,到比较复杂的算法过程,例如深度优先查找算法、广度优先查找算法、动态规划算法等。但是我们从整体上分析,就不难发现这些题目大部分都具有固定的解题模板以及解题思路。大厂面试官的笔试题来源,可以肯定90%来自 LeetCode 算法网站以及《剑指offer》这本算法书籍,所以候选人应该将关注的重点放在这两块内容。本章后续的小节会给出一些经典的数据结构和算法解题模板和思路。