原生javascript手写一个丝滑的轮播图
通过本文,你将学到:
- html
- css
- js
没错,就是html,css,js,现在是框架盛行的时代,所以很少会有人在意原生三件套,通过本文实现一个丝滑的轮播图,带你重温html,css和js基础知识。
为什么选用轮播图做示例?有如下几点:
- 业务当中最常用
- 轮播图说简单也不简单,说复杂也不复杂,可以说是一切项目的基石
- 轮播图更适合考察你对html,css,js的基础掌握
废话不多说,让我们先来看一下效果图,如下:
通过上图,我们可以知道,一个轮播图包含了三大部分,第一部分是轮播图的部分,第二部分则是轮播翻页部分,第三部分则是上一页和下一页。
所以一个轮播图的结构我们基本上就清晰了,让我们来详细看一下吧。
html文档结构
首先我们要有一个容器元素,如下:
<!--容器元素-->
<div class="carousel-box"></div>
然后,我们第一部分轮播图也需要一个容器元素,随后就是轮播图的元素列表,结构如下:
<div class="carousel-content"><div class="carousel-item active"><img src="https://www.eveningwater.com/img/segmentfault/1.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/2.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/3.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/4.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/5.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/6.png" alt="" class="carousel-item-img"></div><div class="carousel-item"><img src="https://www.eveningwater.com/img/segmentfault/7.png" alt="" class="carousel-item-img"></div>
</div>
分析下来就三个,容器元素,每一个轮播图元素里面再套一个图片元素。
接下来是第二部分,同样的也是一个容器元素,套每一个轮播点元素,如下:
<div class="carousel-sign"><div class="carousel-sign-item active">0</div><div class="carousel-sign-item">1</div><div class="carousel-sign-item">2</div><div class="carousel-sign-item">3</div><div class="carousel-sign-item">4</div><div class="carousel-sign-item">5</div><div class="carousel-sign-item">6</div>
</div>
无论是轮播图部分还是轮播分页部分,都加了一个active类名,作为默认显示和选中的轮播图和轮播分页按钮。
第三部分,则是上一页和下一页按钮,这里如果我们将最外层的轮播容器元素设置了定位,这里也就不需要一个容器元素了,我们直接用定位,下一节写样式会详细说明。我们还是来看结构,如下:
<div class="carousel-ctrl carousel-left-ctrl"><</div>
<div class="carousel-ctrl carousel-right-ctrl">></div>
这里采用了html字符实体用作上一页和下一页文本,关于什么是html字符实体,可以参考相关文章,这里不做详解。
通过以上的分析,我们一个轮播图的文档结构就完成了,接下来,让我们编写样式。
编写样式
首先我们根据效果图可以知道,容器元素,轮播图部分容器元素以及每一个轮播图元素都是百分之百宽高的,样式如下:
.carousel-box,.carousel-content,.carousel-item ,.carousel-item-img {width: 100%;height: 100%;
}
其次,容器元素和轮播图元素,我们需要设置成相对定位,为什么轮播图也要设置成相对定位?因为我们这里是使用的绝对定位加left和right偏移从而实现的滑动轮播效果。
.carousel-box,.carousel-item {position: relative;
}
然后,由于轮播图只显示当前的轮播图,而超出的部分也就是溢出部分我们需要截断隐藏,因此为容器元素设置截断隐藏。
.carousel-box {overflow: hidden;
}
接着,每一个轮播图元素默认都是隐藏的,只有加了active类名,才显示。
.carousel-item {display: none;
}
.carousel-item.active {display: block;left: 0;
}
再然后分别是向左还是向右,这里我们是通过添加类名的方式来实现滑动,所以我们在这里额外为轮播元素增加了left和right类名,如下:
.carousel-item.active.left {left: -100%;
}
.carousel-item.active.right {left: 100%;
}
有意思的点还在这里,就是每一个轮播图元素还额外的增加了next和prev类名,为什么要增加这两个类名?试想我们当前轮播图显示的时候,前面的是不是应该被隐藏,而后面的下一个应该是紧紧排在当前轮播图之后,然后做准备,而这两个类名的目的就是在这里,让效果看起来更加丝滑一些。
.carousel-item.next,
.carousel-item.prev {display: block;position: absolute;top: 0;
}
.carousel-item.next {left: 100%;
}
.carousel-item.prev {left: -100%;
}
.carousel-item.next.left,
.carousel-item.prev.right {left: 0%;
}
最后补充一个轮播图片元素的样式,如下:
.carousel-item-img {object-fit: cover;
}
到了这里,其实轮播图的核心思路已经出现了,就是利用的绝对定位加left偏移来实现,而在javascript逻辑中,我们只需要操作类名就可以了。
这样做的好处很显然,我们将动画的逻辑包装在css中,因此轮播的动画逻辑也比较好修改,修改css代码总比修改js代码简单吧?
到了这里,轮播部分的样式我们就已经完成了,接下来看分页按钮组的样式。
根据图片示例,分页按钮组元素是在底部的,其实分页按钮组也可以说是很常规的按钮布局,所以样式都是一些很基础的,也没有必要做太多的详解。
.carousel-sign {position: absolute;bottom: 10px;left: 50%;transform: translateX(-50%);padding: 5px 3px;border-radius: 6px;user-select: none;background: linear-gradient(135deg,#73a0e4 10%,#1467e4 90%);
}.carousel-sign-item {width: 22px;height: 20px;font-size: 14px;font-weight: 500;line-height: 20px;text-align: center;float: left;color:#f2f3f4;margin: auto 4px;cursor: pointer;border-radius: 4px;
}
.carousel-sign-item:hover {color:#fff;
}
.carousel-sign-item.active {color:#535455;background-color: #ebebeb;
}
最后就是上一页下一页的样式,有意思的是上一页下一页默认是不应该显示的,鼠标悬浮到轮播图容器元素上,才会显示,所以这里也用到了定位。
.carousel-ctrl {position: absolute;top: 50%;transform: translateY(-50%);font-size: 30px;font-weight: 300;user-select: none;background: linear-gradient(135deg,#73a0e4 10%,#1467e4 90%);color: #fff;border-radius: 5px;cursor: pointer;transition: all .1s cubic-bezier(0.075, 0.82, 0.165, 1);text-align: center;padding: 1rem;
}
.carousel-ctrl.carousel-left-ctrl {left: -50px;
}
.carousel-ctrl.carousel-right-ctrl {right: -50px;
}
.carousel-box:hover .carousel-ctrl.carousel-left-ctrl {left: 10px;
}
.carousel-box:hover .carousel-ctrl.carousel-right-ctrl {right: 10px;
}
.carousel-ctrl:hover {background-color: rgba(0,0,0,.8);
}
到了这里,样式的布局就完成了,接下来是javascript核心逻辑,让我们一起来看一下吧。
轮播图的核心逻辑
我们将轮播图封装在一个类当中,然后通过构造函数调用的方式来使用它,我们先来看使用方式,如下:
const options = {el: '.carousel-box',speed: 1000, // 轮播速度(ms)delay: 0, // 轮播延迟(ms)direction: 'left', // 图片滑动方向monitorKeyEvent: true, // 是否监听键盘事件monitorTouchEvent: true // 是否监听屏幕滑动事件
}
const carouselInstance = new Carousel(options);
carouselInstance.start();
通过使用方式,我们得到了什么?
- 轮播图的配置对象* el: 容器元素* speed: 轮播速度* delay: 轮播执行延迟时间* direction: 滑动方向,主要有left和right两个值* monitorKeyEvent: 是否监听键盘事件,也就是说是否可以通过点击键盘上的左右来切换轮播图* monitorTouchEvent: 是否监听屏幕滑动事件,也就是说是否可以通过滑动屏幕来切换图片* Carousel是一个构造函数* carousel构造函数内部提供了一个start方法用来开始轮播,很显然这里是开始自动轮播根据以上的分析,让我们来一步步实现Carousel这个东西吧。
首先它是一个构造函数,支持传入配置对象,所以,我们定义一个类,并且这个类还有一个start方法也初始化,如下:
class Carousel {constructor(options){//核心代码}start(){//核心代码}
}
在初始化的时候我们需要做什么?
首先我们要获取到轮播元素,还有上一页下一页按钮以及我们的分页按钮元素。如下:
class Carousel {constructor(options){// 容器元素this.container = $(options.el);// 轮播图元素this.carouselItems = this.container.querySelectorAll('.carousel-item');// 分页按钮元素组this.carouselSigns = $$(('.carousel-sign .carousel-sign-item'),this.container);// 上一页与下一页this.carouselCtrlL = $$(('.carousel-ctrl'),this.container)[0];this.carouselCtrlR = $$(('.carousel-ctrl'),this.container)[1];}start(){//核心代码}
}
这里用到了和和和$方法,看起来和jQuery的获取DOM很像,用到了jQuery?那当然不是了,我们来看这2个方法的实现。
const $ = (v,el = document) => el.querySelector(v);
const $$ = (v,el = document) => el.querySelectorAll(v);
也就是获取dom元素的简易封装啦。
- document.querySelector API
- document.querySelectorAll API
就是基于以上两个dom查询节点的方法封装的,让我们来看下一步,首先我们需要有一个确定当前轮播图的索引值,然后获取所有轮播图元素的长度,然后就是初始化配置对象。代码如下:
class Carousel {constructor(options){//省略了代码// 当前图片索引this.curIndex = 0;// 轮播盒内图片数量this.numItems = this.carouselItems.length;// 是否可以滑动this.status = true;// 轮播速度this.speed = options.speed || 600;// 等待延时this.delay = options.delay || 3000;// 轮播方向this.direction = options.direction || 'left';// 是否监听键盘事件this.monitorKeyEvent = options.monitorKeyEvent || false;// 是否监听屏幕滑动事件this.monitorTouchEvent = options.monitorTouchEvent || false;}//省略了代码
}
初始化完成之后,接下来我们有两个逻辑还需要在初始化里面完成,第一个逻辑是添加动画过渡效果,也就是让动画看起来更丝滑一些,第二个就是添加事件逻辑。继续在构造函数中调用2个方法,代码如下:
class Carousel {constructor(options){//省略了代码// 添加了事件this.handleEvents();// 设置过渡效果this.setTransition();}//省略了代码
}
我们先来看最简单的setTransition方法,其实这个方法很简单,就是通过在head标签内添加一个style标签,通过insertRule方法添加样式。代码如下:
setTransition() {const styleElement = document.createElement('style');document.head.appendChild(styleElement);const styleRule = `.carousel-item {transition: left ${this.speed}ms ease-in-out}`styleElement.sheet.insertRule(styleRule, 0);
}
很显然这里是为每个轮播图元素添加过渡效果,接下来我们来看绑定事件方法内部,我们可以尝试思考一下,都有哪些事件呢?总结如下:
- 上一页与下一页
- 分页按钮组
- 滑动事件
- 键盘事件
- 轮播盒子元素的鼠标悬浮与鼠标移出事件
根据以上分析,我们的handleEvents方法就很好实现了,如下:
handleEvents() {// 鼠标从轮播盒上移开时继续轮播this.container.addEventListener('mouseleave', this.start.bind(this));// 鼠标移动到轮播盒上暂停轮播this.container.addEventListener('mouseover', this.pause.bind(this));// 点击左侧控件向右滑动图片this.carouselCtrlL.addEventListener('click', this.clickCtrl.bind(this));// 点击右侧控件向左滑动图片this.carouselCtrlR.addEventListener('click', this.clickCtrl.bind(this));// 点击分页按钮组后滑动到对应的图片for (let i = 0; i < this.carouselSigns.length; i++) {this.carouselSigns[i].setAttribute('slide-to', i);this.carouselSigns[i].addEventListener('click', this.clickSign.bind(this));}// 监听键盘事件if (this.monitorKeyEvent) {document.addEventListener('keydown', this.keyDown.bind(this));}// 监听屏幕滑动事件if (this.monitorTouchEvent) {this.container.addEventListener('touchstart', this.touchScreen.bind(this));this.container.addEventListener('touchend', this.touchScreen.bind(this));}
}
这里有意思的点在于bind方法更改this对象,使得this对象指向当前轮播实例元素,还有一点就是我们为每个分页按钮设置了一个slide-to的索引值,后续我们就可以根据这个索引值来切换轮播图。
接下来,让我们看看每一个事件对应的回调方法,首先是start方法,其实很容易就想到,start方法就是开始轮播,开始轮播也就是自动轮播,自动轮播我们需要用到定时器,因此我们的start函数就很好实现了,代码如下:
start() {const event = {srcElement: this.direction == 'left' ? this.carouselCtrlR : this.carouselCtrlL};const clickCtrl = this.clickCtrl.bind(this);// 每隔一段时间模拟点击控件this.interval = setInterval(clickCtrl, this.delay, event);
}
这里有意思的点在于我们的自动轮播,是直接去模拟点击上一页下一页进行切换的,除此之外,这里根据方向将srcElement元素作为事件对象传递,也就是说后面我们会根据这个元素来做方向上的判断。
接下来我们来看暂停函数,很简单,就是清除定时器即可,如下:
// 暂停轮播
pause() {clearInterval(this.interval);
}
接下来,让我们来看clickCtrl方法,思考一下,我们是如何修改当前轮播图的索引值的,正常情况下,比如说,我们是向左滑动,索引值实际上就是将当前索引值相加,然后再判断是否超出了轮播图元素组的长度,重置索引值。
但是这里有一个更为巧妙的实现方式,那就是取模,将当前索引值加1然后与轮播图元素组的长度取模,这样也就保证了我们的索引值始终不会超过轮播图元素组的长度。
如果是向右滑动,那么我们应该是加上轮播图元素组的长度 - 1再取模,也就是与向左方向相反,根据以上分析,我们的代码就好实现了,如下:
// 处理点击控件事件
clickCtrl(event) {if (!this.status) return;this.status = false;let fromIndex = this.curIndex, toIndex, direction;if (event.srcElement == this.carouselCtrlR) {toIndex = (this.curIndex + 1) % this.numItems;direction = 'left';} else {toIndex = (this.curIndex + this.numItems - 1) % this.numItems;direction = 'right';}this.slide(fromIndex, toIndex, direction);this.curIndex = toIndex;
}
在这个方法里面还有一个slide方法,顾名思义就是轮播图的滑动方法,其实通篇下来,最核心的就是这个slide方法,这个方法主要做的逻辑就是根据索引值来切换class。代码如下:
slide(fromIndex, toIndex, direction) {let fromClass, toClass;if (direction == 'left') {this.carouselItems[toIndex].className = "carousel-item next";fromClass = 'carousel-item active left';toClass = 'carousel-item next left';} else {this.carouselItems[toIndex].className = "carousel-item prev";fromClass = 'carousel-item active right';toClass = 'carousel-item prev right';}this.carouselSigns[fromIndex].className = "carousel-sign-item";this.carouselSigns[toIndex].className = "carousel-sign-item active";setTimeout((() => {this.carouselItems[fromIndex].className = fromClass;this.carouselItems[toIndex].className = toClass;}).bind(this), 50);setTimeout((() => {this.carouselItems[fromIndex].className = 'carousel-item';this.carouselItems[toIndex].className = 'carousel-item active';this.status = true;// 设置为可以滑动}).bind(this), this.speed + 50);
}
这里分成了两块替换类名的逻辑,第一块是轮播图元素的替换类名,需要判断方向,第二块则是分页按钮组的类名替换逻辑,当然分页按钮组的逻辑是不需要替换类名的。
其实分析到这里,这个轮播图的核心基本已经完成了,接下来就是完善了,让我们继续看分页按钮组的事件回调逻辑。
其实这里的逻辑也就是拿到索引值,前面为每个分页按钮组设置了一个slide-to属性,这里很显然就通过获取这个属性,然后生成slide方法所需要的参数,最后调用slide方法就行了。代码如下:
clickSign(event) {if (!this.status) return;this.status = false;const fromIndex = this.curIndex;const toIndex = parseInt(event.srcElement.getAttribute('slide-to'));const direction = fromIndex < toIndex ? 'left' : 'right';this.slide(fromIndex, toIndex, direction);this.curIndex = toIndex;
}
最后还剩两个逻辑,一个是键盘事件,另一个是滑动事件逻辑,我们先来看键盘事件逻辑,键盘事件逻辑无非就是利用keyCode判断用户是否点击的是上一页和下一页,然后像自动开始轮播那样模拟调用上一页下一页按钮事件逻辑即可。代码如下:
keyDown(event) {if (event && event.keyCode == 37) {this.carouselCtrlL.click();} else if (event && event.keyCode == 39) {this.carouselCtrlR.click();}
}
最后就是滑动事件了,滑动事件最难的点在于如何判断用户滑动的方向,其实我们可以通过计算滑动角度来判断,这里的计算逻辑是来自网上的一个公式,感兴趣的可以查阅相关资料了解。我们来看代码如下:
touchScreen(event) {if (event.type == 'touchstart') {this.startX = event.touches[0].pageX;this.startY = event.touches[0].pageY;} else {// touchendthis.endX = event.changedTouches[0].pageX;this.endY = event.changedTouches[0].pageY;// 计算滑动方向的角度const dx = this.endX - this.startXconst dy = this.startY - this.endY;const angle = Math.abs(Math.atan2(dy, dx) * 180 / Math.PI);// 滑动距离太短if (Math.abs(dx) < 10 || Math.abs(dy) < 10) return;if (angle >= 0 && angle <= 45) {// 向右侧滑动屏幕,模拟点击左控件this.carouselCtrlL.click();} else if (angle >= 135 && angle <= 180) {// 向左侧滑动屏幕,模拟点击右控件this.carouselCtrlR.click();}}
}
到此为止,我们的一个轮播图就完成了,总结一下我们学到了什么?
- CSS过渡效果
- CSS基本布局
- javascript事件* 鼠标悬浮与移出事件* 滑动事件* 键盘事件* 元素点击事件
- javascript定时器
PS: 以后再也不用自己写轮播了,业务当中遇到,可以直接拿去用了,😄。
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取
相关文章:
原生javascript手写一个丝滑的轮播图
通过本文,你将学到: htmlcssjs 没错,就是html,css,js,现在是框架盛行的时代,所以很少会有人在意原生三件套,通过本文实现一个丝滑的轮播图,带你重温html,css和js基础知识。 为什么选用轮播图做示例&…...
【Linux】进程优先级(进程优先级 Linux下优先级 用top命令更改已存在进程的nice 其他概念 进程切换)
文章目录进程优先级Linux下优先级用top命令更改已存在进程的nice:其他概念进程切换进程优先级 我们作为使用者一般不关心优先级,它跟我们的调度器有很大的关系,调度器是为了跟均衡的调度进程。 什么叫做优先级? 优先级和权限是两…...
2016年chatGPT之父Altman与马斯克的深度对话(值得一看)
2016年9月,现今OpenAI CEO,ChatGPT之父,时任创投公司Y Combinator的总裁Sam Altman在特斯拉加州弗里蒙特工厂采访了埃隆马斯克。马斯克阐述了创建OpenAI的初衷,以及就他而言,对于未来最为重要的五件事。这是OpenAI的两…...
基于vscode开发vue3项目的详细步骤教程 3 前端路由vue-router
1、Vue下载安装步骤的详细教程(亲测有效) 1_水w的博客-CSDN博客 2、Vue下载安装步骤的详细教程(亲测有效) 2 安装与创建默认项目_水w的博客-CSDN博客 3、基于vscode开发vue项目的详细步骤教程_水w的博客-CSDN博客 4、基于vscode开发vue项目的详细步骤教程 2 第三方图标库FontAw…...
【C语言】每日刷题 —— 牛客语法篇(5)
前言 大家好,继续更新专栏 c_牛客,不出意外的话每天更新十道题,难度也是从易到难,自己复习的同时也希望能帮助到大家,题目答案会根据我所学到的知识提供最优解。 🏡个人主页:悲伤的猪大肠9的博…...
操作系统(2.1)--进程的描述与控制
目录 一、前驱图和程序执行 1.前驱图 2.程序顺序执行 2.1 程序的顺序执行 2.2 程序顺序执行时的特征 3. 程序并发执行 3.1程序的并发执行 3.2 程序并发执行时的特征 一、前驱图和程序执行 1.前驱图 前趋图:是一个有向无循环图,用于描述进程之间执行的前后…...
JAVA查看动态代理类
JAVA查看代理类 1. 代理类 class 生成 System.setProperty // jdk8及之前的设置System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");// or System.getProperties().put("sun.misc.ProxyGenerator.saveGenerated…...
Chapter2 : SpringBoot配置
尚硅谷SpringBoot顶尖教程 1. 全局配置文件 SpringBoot使用一个全局的配置文件 application.properties 或者 application.yml ,该配置文件放在src/main/resources目录或者类路径/config目录下面, 可以用来修改SpringBoot自动配置的默认值。 yml是YA…...
手撕单链表练习
Topic 1:LeetCode——203. 移除链表元素203. 移除链表元素 - 力扣(LeetCode)移除链表中的数字6操作很简单,我们只需要把2的指向地址修改就好了,原来的指向地址是6现在改为3这个思路是完全正确的,但是在链表…...
Kubuntu安装教程
文章目录Kubuntu介绍下载Kubuntu在VMware虚拟机中安装Kubuntu1. 点击“创建新的虚拟机”2. 选择“自定义(高级)”3. 按照下图所示进行设置设置网络4. 点击“自定义硬件”5. 开启虚拟机6. 进入安装界面,选择中文,之后点击“安装Kub…...
[蓝桥杯] 树状数组与线段树问题(C/C++)
文章目录 一、动态求连续区间和 1、1 题目描述 1、2 题解关键思路与解答 二、数星星 2、1 题目描述 2、2 题解关键思路与解答 三、数列区间最大值 3、1 题目描述 3、2 题解关键思路与解答 标题:树状数组与线段树问题 作者:Ggggggtm 寄语:与其…...
Matlab-Loma Prieta 地震分析
此示例说明如何将带时间戳的地震数据存储在时间表中以及如何使用时间表函数来分析和可视化数据。 加载地震数据 示例文件quake.mat包含 1989 年 10 月 17 日圣克鲁斯山脉 Loma Prieta 地震的 200 Hz 数据。这些数据由加州大学圣克鲁斯分校查尔斯F里希特地震实验室的 Joel Yelli…...
Spring Boot全局异常处理
使用注解方式处理全局异常使用 ControllerAdvice (RestControllerAdvice) 配合 ExceptionHandler适用于返回数据的请求(一般是RESTful接口规范下的JSON报文)package com.example.exception;import org.slf4j.Logger; import org.s…...
websocket每隔5秒给服务端send一次信息
websocket轮询每隔5秒给服务端send一次信息,主要功能点如下:socket 采用了定时器 setInterval() 需要清除定时器否则会报错监听了突然关闭浏览器窗口,destroyed里面直接监听 window.removeEventListener("beforeu…...
2023年中职网络安全——SQL注入测试(PL)解析
SQL注入测试(PL) 任务环境说明: 服务器场景:Server2312服务器场景操作系统:未知(关闭链接)已知靶机存在网站系统,使用Nmap工具扫描靶机端口,并将网站服务的端口号作为Flag(形式:Flag字符串)值提交。访问网站/admin/pinglun.asp页面,此页面存在SQL注入漏洞,使用排…...
利用蜜罐捕捉攻击实验(31)
预备知识 1、蜜罐的含义和作用 蜜罐(Honeypot)是一种在互联网上运行的计算机系统。它是专门为吸引并诱骗那些试图非法闯入他人计算机系统的人(如电脑黑客)而设计的,蜜罐系统是一个包含漏洞的诱骗系统,它通过模拟一个或多个易受攻击的主机ÿ…...
PyTorch深度学习实战 | 自然语言处理与强化学习
PyTorch是当前主流深度学习框架之一,其设计追求最少的封装、最直观的设计,其简洁优美的特性使得PyTorch代码更易理解,对新手非常友好。本文主要介绍深度学习领域中自然语言处理与强化学习部分。自然语言区别于计算机所使用的机器语言和程序语…...
测牛学堂:接口测试基础理论和工具的使用
接口测试流程总结 1 需求分析,看产品经理的需求文档 2 接口文档解析,开发编写的api接口文档 3 设计测试用例 4脚本开发 5 执行及缺陷跟踪 6 生成测试报告 7接口自动化持续集成 测试解析接口文档 接口文档,又称为api文档,是由后…...
定长内存池的实现
解决的是固定大小的内存申请释放需求: 性能达到极致不考虑内存碎片问题(统一使用自由链表管理还回来的空间) 为了避免命名污染,不要直接using namespace std;只展开常用的。 #include <iostream> using std::cout; using std::endl;申请空间时有…...
三更草堂springSecurity的学习
源码地址:学习springSecurity (gitee.com) git:https://gitee.com/misszyg/spring-security.git 一,认证流程 1,经过UsernamePasswordAuthenticationFilter (1)传入了用户的账号,密码 源码&a…...
【C语言】指针的深度理解(一)
前言 我们已经了解了指针的概念,一是指针变量是用来存放地址的,每个地址都对应着唯一的内存空间。二是指针的大小是固定的4或8个字节(取决于操作系统,32位的占4个字节,64位的占8个字节)。三是指针是有类型…...
Kafka最佳实践
前言 Kafka 最佳实践,涉及 典型使用场景Kafka 使用的最佳实践 Kafka 典型使用场景 Data Streaming Kafka 能够对接到 Spark、Flink、Flume 等多个主流的流数据处理技术。利用 Kafka 高吞吐量的特点,客户可以通过 Kafka 建立传输通道,把应…...
入门教程: 认识 React用于构建用户界面的 JavaScript 库
课前准备 我们将会在这个教程中开发一个小游戏。你可能并不打算做游戏开发,然后就直接跳过了这个教程——但是不妨尝试一下!你将在该教程中学到关于构建 React 应用的基础知识,掌握这些知识后,你将会对 React 有更加深刻的理解。 这篇教程分为以下几个部分: 环境准备是学…...
极紫外光源高次谐波发生腔不同区域真空度精密控制解决方案
摘要:在高次谐波发生器中一般包含两个不同真空区域,一个是1~100Torr绝压范围的气池内部的低真空区域,一个是高阶谐波光路上的绝压为0.001Pa量级的高真空区域。本文针对此两个区域的真空度控制提出了相应的解决方案,特别是详细介绍…...
「Vue面试题」在vue中为什么data属性是一个函数而不是一个对象
文章目录一、实例和组件定义data的区别二、组件data定义函数与对象的区别三、原理分析四、结论一、实例和组件定义data的区别 vue实例的时候定义data属性既可以是一个对象,也可以是一个函数 const app new Vue({el:"#app",// 对象格式data:{foo:"…...
如何使用 ChatGPT 编写 SQL JOIN 查询
通过清晰的示例和解释,本文展示了 ChatGPT 如何简化和简化创建复杂 MySQL 查询的过程,使用户更容易与数据库交互并检索他们需要的数据。无论您是初学者还是经验丰富的开发人员,本文都提供了有关如何利用 ChatGPT 来增强您的 MySQL 查询编写技…...
vue2+elementUI完成添加学生删除学生案列
效果图: 点击添加学生按钮,弹出Dialog,收集用户信息: el-table中自定义复选框,选中一行,可以点击删除 代码区域:就一个HTML文件 <!DOCTYPE html> <html lang"en"> <head>&…...
对void的深度理解
作者:小树苗渴望变成参天大树 作者宣言:认真写好每一篇博客 作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧! void前言一、 void 关键字二、 void修饰函数返回值和参数三、void指针3.1void * 定义的…...
哪款游戏蓝牙耳机好用?好用的游戏蓝牙耳机推荐
现在,不少人喜欢戴蓝牙耳机玩游戏,而在戴蓝牙耳机玩游戏时难免会产生音画不同步的问题。现在越来越多的蓝牙耳机支持游戏模式,那么,哪款游戏蓝牙耳机好用?接下来,我来给大家推荐几款好用的游戏蓝牙耳机&…...
求职(怎么才算精通JAVA开发)
在找工作的的时候,有时候我们需要对自己的技术水平做一个评估。特别是Java工程师,我们该怎么去表达自己的能力和正确认识自己所处的技术水平呢。技术一般的人,一般都不敢说自己精通JAVA,因为你说了精通JAVA几乎就给了面试官一个可以随便往死里问的理由了。很多不自信的一般…...
曲靖网站建设公司/五八精准恶意点击软件
this.getWindow().getDecorView()...
the7企业中 英文wordpress模板/前端seo主要优化哪些
Pod调度 在默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。但是在实际使用中,这并不满足的需求,因为很多情况下,我们想控制某些Pod到达某…...
无锡装饰网站建设/如何优化网站推广
#!/bin/bash for file in *.zip dofolder$(echo $file | cut -c 1-10)mkdir $folderunzip -q $file -d $folder doneecho "All zip files have been extracted." # 说明: # 1. for循环遍历当前目录下的所有zip文件 # 2. 使用cut命令提取zip文件名前10个字…...
广东seo站外推广折扣/百度搜索关键词推广
随着现在网络化的越来越普及,人们对随时应用网络的需求明显高涨。近年来手机平板等移动终端普及使用,网络已经深入到我们的日常生活与工作,越来越多的企业、媒体机构在举行新品发布会、大型博览会、新闻发布会、推广会等会选择会向客户提供无…...
学校网站建设团队/百度seo优化方法
Equivalent Strings 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid84562#problem/E 题意: 给出两个字符串,确定是否相等。一个字符串分割成相同大小的两半a1和a2,另一个字符串分割成相同大小的成两半b1和b2。 以下是正确…...
建站平台步骤详解/优化方案的格式及范文
首先分析内部类:ThreadPoolExecutor$Worker //Worker对线程和任务做了一个封装,同时它又实现了Runnable接口, //所以Worker类的线程跑的是自身的run方法 private final class Workerextends AbstractQueuedSynchronizer implements Runnable …...