360前端星计划—JavaScript 从入门到放弃

JavaScript 从入门到放弃

一、遵守各司其职的原则

不要在js代码里控制样式

二、复杂的UI组件的设计(轮播图的实现)

step1. 结构设计
<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;
}
step2. API设计

对于一个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);
step3. 控制结构设计

到这里基本完成了四张图片的自动跳转的功能,但是还缺少了交互的效果,比如说图片两边的向左向右的箭头以及下方中间的圆点。所以还需要添加控制结构的部件。

/*左右箭头的结构*/
<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();

三、优化局部的API

提交一次:

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);
        }
    }
}

Web标准:前端的原力

  • HTTP/0.9

    并不是标准,只是一个文档。并且在那时候只有get方法。

  • HTTP/1.0

    一份参考文档,还不是IETF的标准。总结和记录了当时浏览器有代表性的实现。

    增加了headpost方法

    增加了可选择的版本号

    增加了头部字段描述和响应

    增加了三位数的响应码

  • HTTP/1.1

    增加了持久连接

    强制性服务器头部

    更好的缓存

    分块编码

  • HTTP/2

    增加了多路复用

Web标准介绍

BOM

浏览器对象模型。HTML5规范中有一部分涵盖了BOM的主要内容,因为W3C希望将JavaScript在浏览器中最基础的部分标准化。

主要涉及的对象有

  • window对象
  • location对象
  • navigator对象
  • screen对象
  • history对象
DOM

HTML和XML文档的编程接口。DOM表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。

前端常用的HTTP知识

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:作为网关或者代理服务器时,上游服务器处理超时

Header的分类

通用:

  • Date: Tue, 3 Oct 2019 02:16:00 GMT
  • Connection: close

请求:

  • User-Agent: Mozilla/5.0
  • Accept: */*

响应:

  • Server: Nginx
  • Last-Modified: Thu, 16 Oct 2019 10:15:16 GMT

实体:

  • Content-Type: text/html; charset=utf-8
  • Content-Length: 100
cookie

通常请求报文中会含有cookie首部字段,响应报文中会含有Set-Cookie字段,响应头可以含有多个Set-Cookie

cookie的常用的安全策略有

  • 设置httpOnly属性,使浏览器不可以通过js来读取cookie,防止XSS攻击
  • 设置sameSite属性或者添加token,防止CSRF攻击
session

在服务器端对应的保存的信息称为session,是基于cookie存放用户信息

Content-Type

表示了内容的类型

text/html; charset=urf-8表明是一个html文档

application/x-www-form-urlencoded表明了提交数据的类型

常见的有

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml
网络的性能优化方法
  1. 使用keep-alive,避免了大量的创建tcp连接与断开tcp连接的过程。

  2. 减少网络传输大小:使用gzip压缩

  3. 使用缓存:强缓存/协商缓存

    • 强缓存:ExpiresCache-Control

    • 协商缓存:Etaglast-modified,在请求报文中变为if-none-matchif-modified-since

    • LocalStorage

    • ServiceWorker

  4. 使用http2/http3

    http2的优点:

    • 多路复用
    • 二进制压缩
    • 头部压缩
    • server push 服务器推送

    http3

    • 基于QUIC协议(UDP)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值