不要在js
代码里控制样式
<div id="my-slider" class="slider-list">
<ul>
<li class="slider-list__item--selected">
<img src="https://p5.ssl.qhimg.com/t0119c74624763dd070.png"/>
li>
<li class="slider-list__item">
<img src="https://p5.ssl.qhimg.com/t01adbe3351db853eb3.jpg"/>
li>
<li class="slider-list__item">
<img src="https://p5.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg"/>
li>
<li class="slider-list__item">
<img src="https://p5.ssl.qhimg.com/t01331ac159b58f5478.jpg"/>
li>
ul>
div>
#my-slider {
position: relative;
width: 790px;
}
.slider-list ul {
list-style-type: none;
position: relative;
padding: 0;
margin: 0;
}
.slider-list__item,
.slider-list__item--selected {
position: absolute; //通过绝对定位的方式来实现四张图的重叠。
transition: opacity 1s; //使用transition实现过渡的动画。
opacity: 0;
text-align: center;
}
.slider-list__item--selected {
transition: opacity 1s;
opacity: 1;
}
对于一个slider
组件,包含的API应该有
getSelectedItem(); //获取选中的元素
getSelectedItemIndex(); //获取选中的元素的索引值
slideTo(idx); //跳转到某个元素
slideNext(); //跳转到下一个元素
slidePreviouse(); //滑动到上一个元素
在具体的实现中,可以将slider
封装为类,创建相应的方法。
class Slider {
constructor(id) {
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll('.slider-list__item');
}
getSelectedItem() {
const selected = this.container.querySelector('.slider-list__item--selected');
return selected;
}
getSelectedItemIndex() {
return Array.from(this.items).indexOf(this.getSelectedItem());
}
slideTo(idx) {
const selected = this.getSelectedItem();
if(selected) {
selected.className = 'slider-list__item';
}
const item = this.items[idx];
if(item) {
item.className = 'slider-list__item--selected';
}
}
slideNext() {
const currentIdx = this.getSelectedItemIndex();
const nextIdx = (currentIdx + 1) % this.items.length;
slideTo(nextIdx);
}
slidePrevious() {
const currentIdx = this.getSelectedItemIndex();
const preIdx = (currentIdx + 1) % this.items.length;
slideTo(preIdx);
}
}
const slider = new Slider('my-slider');
setInterval(() => {
slider.slideNext();
}, 3000);
到这里基本完成了四张图片的自动跳转的功能,但是还缺少了交互的效果,比如说图片两边的向左向右的箭头以及下方中间的圆点。所以还需要添加控制结构的部件。
/*左右箭头的结构*/
<a class="slide-list__next">a>
<a class="slide-list__previous">a>
/*底部圆点的结构*/
<div class="slide-list__control">
<span class="slide-list__control-buttons--selected">span>
<span class="slide-list__control-buttons">span>
<span class="slide-list__control-buttons">span>
<span class="slide-list__control-buttons">span>
div>
添加了这两个控制结构之后,在之前的slider
类中也需要增加一些逻辑
class Slider {
//对构造函数进行修改
constructor(id, cycle = 3000) {
this.container = document.getElementById(id);
this.items = this.container.querySelectorAll('.slider-list__item');
this.cycle = cycle;
}
//添加一个注册插件的函数
registerPlugins(...plugins) {
//传入了this,也就是当前的对象,
plugins.forEach(plugin => plugin(this));
}
addEventListener(type, handler) {
this.container.addEventListener(type, handler);
}
//开启定时器
start() {
this.stop();
this._timer = setInterval(() => this.slideNext(), this.cycle);
}
//关闭定时器
stop() {
clearInterval(this._timer);
}
.....
//其余的和之前相同
}
function pluginController(slider) {
const controller = slider.container.querySelector('.slider-control');
if(controller) {
const buttons = controller.querySelectorAll('.slide-list__item');
controller.addEventListener('mouseover', evt => {
const idx = Array.from(buttons).indexOf(evt.target);
if(idx >= 0) {
slider.slideTo(idx);
slider.stop();
}
});
controller.addEventListener('mouseout', evt => {
slider.start();
});
slider.addEventListener('slide', evt => {
const idx = evt.detail.index;
const selected = controller.querySelector('.slide-list__conttrol--selected');
if(selected) {
selected.className = 'slide-list__control';
}
buttons[idx].className = 'slide-list__control-button'
});
}
}
function pluginPrevious(slider) {
const previous = slider.container.querySelector('.slide-list__controller');
if(previous) {
previous.addEventListener('click', evt => {
slider.stop();
slider.sliderPrevious();
slider.start();
evt.preventDefault();
});
}
}
function pluginNext(slider) {
const next = slider.container.querySelector('.slide-list__controller');
if(next) {
next.addEventListener('click', evt => {
slider.stop();
slider.sliderPrevious();
slider.start();
evt.preventDefault();
})
}
}
const slider = new Slider('my-slider');
slider.registerPlugins(pluginController, pluginPrevious, pluginNext);
slider.start();
提交一次:
function once(fn) {
return function (...args) {
if(fn) {
let ret = fn.apply(this, args);
fn = null;
return ret;
}
}
}
防抖函数:在相同的时间间隔内执行函数。
常用于scroll
事件,mouseover
事件
function throttle(fn, time = 500) {
let timer;
return function(...args) {
if(timer == null) {
fn.apply(this, args);
timer = setTimeout(() => {
timer = null;
}, time);
}
}
}
节流函数:执行最后一次的触发事件
function debounce(fn, dur) {
dur = dur || 100;
var timer ;
return function() {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, dur);
}
}
消费者
场景:连击的效果
function consumer(fn, time) {
let tasks = [],
timer;
return function(...args) {
tasks.push(fn.bind(this, ...args));
if(timer == null) {
timer = setInterval(() => {
tasks.shift().call(this);
if(tasks.length <= 0) {
clearInterval(timer);
timer = null;
}
}, time);
}
}
}
HTTP/0.9
并不是标准,只是一个文档。并且在那时候只有get方法。
HTTP/1.0
一份参考文档,还不是IETF的标准。总结和记录了当时浏览器有代表性的实现。
增加了head
、post
方法
增加了可选择的版本号
增加了头部字段描述和响应
增加了三位数的响应码
HTTP/1.1
增加了持久连接
强制性服务器头部
更好的缓存
分块编码
HTTP/2
增加了多路复用
Web标准介绍
浏览器对象模型。HTML5规范中有一部分涵盖了BOM的主要内容,因为W3C希望将JavaScript在浏览器中最基础的部分标准化。
主要涉及的对象有
HTML和XML文档的编程接口。DOM表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。
http
在浏览器网络中位于应用层。联网的细节交给了通用的传输协议: TCP/IP
请求/响应行 + 请求/响应头 + 请求/响应体
请求行的构成:请求类型 url 协议版本
响应行的构成:状态码 状态描述
GET: 获取一个资源内容
POST:新增一个资源
PUT:更新资源内容
DELETE:删除资源
OPTIONS:根据返回判断是否有对其请求的权限
HEAD:只返回head,不返回实体内容
PATCH:更新部分内容
1XX: 请求已接受,需要继续处理
2XX:请求已经正确处理
3XX:重定向
4XX:客户端错误
5XX:服务器错误
其中常见的状态码有
101:切换协议
200:成功
206:返回部分内容,比如大文件下载
301:永久重定向,比如资源更换路径或者改了名称
302:临时重定向,比如当前请求需要的登录,跳转到登录页面
304:资源未修改,不返回实体内容,客户端直接使用本地的缓存内容。协商缓存
400:错误请求
403:拒绝执行,比如没有访问权限
404:资源不存在,比如服务器已经删除了该资源
413:请求实体过大,比如服务器限制了上传文件的大小
500:服务器内部错误,比如数据处理异常导致报错
502:作为网关或者代理服务器时,上游服务器异常
504:作为网关或者代理服务器时,上游服务器处理超时
通用:
请求:
响应:
实体:
通常请求报文中会含有cookie
首部字段,响应报文中会含有Set-Cookie
字段,响应头可以含有多个Set-Cookie
cookie的常用的安全策略有
httpOnly
属性,使浏览器不可以通过js来读取cookie,防止XSS攻击sameSite
属性或者添加token
,防止CSRF攻击在服务器端对应的保存的信息称为session
,是基于cookie
存放用户信息
表示了内容的类型
如 text/html; charset=urf-8
表明是一个html
文档
application/x-www-form-urlencoded
表明了提交数据的类型
常见的有
application/x-www-form-urlencoded
multipart/form-data
application/json
text/xml
使用keep-alive
,避免了大量的创建tcp连接与断开tcp连接的过程。
减少网络传输大小:使用gzip
压缩
使用缓存:强缓存/协商缓存
强缓存:Expires
和Cache-Control
协商缓存:Etag
和last-modified
,在请求报文中变为if-none-match
、if-modified-since
LocalStorage
ServiceWorker
使用http2/http3
http2的优点:
http3