7弥锄、手寫函數(shù)防抖和函數(shù)節(jié)流
函數(shù)節(jié)流
函數(shù)節(jié)流是讓這個(gè)函數(shù)在間隔某一段時(shí)間執(zhí)行一次
以輸入框?yàn)槔ッ遥僭O(shè)你想查詢xxxx,你想實(shí)現(xiàn)當(dāng)我開(kāi)始輸入多少秒之后,執(zhí)行查詢操作叉讥。(并不一定要輸入完畢)
核心是去判斷當(dāng)前時(shí)間和開(kāi)始時(shí)間的間隔是否到達(dá)了設(shè)置的delay值窘行,如果達(dá)到了饥追,就執(zhí)行一次回調(diào)图仓。沒(méi)有則不執(zhí)行。
函數(shù)防抖
讓這個(gè)函數(shù)在執(zhí)行上一次之后過(guò)了你規(guī)定的時(shí)間再執(zhí)行的一種方法
核心在于每次都去clear一個(gè)延時(shí)器但绕,然后每次執(zhí)行函數(shù)的時(shí)候救崔,都去clear以前的延時(shí)器。只有當(dāng)你中斷輸入的時(shí)候捏顺,才會(huì)去執(zhí)行相應(yīng)回調(diào)六孵。
function throttle(method,context){
clearTimeout(method.tId)
method.tId = setTimeout(function(){
method.call(context)
},1000)
}
封裝節(jié)流和防抖,通過(guò)第三參數(shù)來(lái)切換模式
const throttle = function(fn, delay, isDebounce) {
let timer
let lastCall = 0
return function (...args) {
if (isDebounce) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn(...args)
}, delay)
} else {
const now = new Date().getTime()
if (now - lastCall < delay) return
lastCall = now
fn(...args)
}
}
}
8幅骄、瀏覽器渲染過(guò)程
一圖勝千言
- 瀏覽器使用HTTP協(xié)議或者HTTPS協(xié)議劫窒,向服務(wù)端請(qǐng)求頁(yè)面
- 把請(qǐng)求回來(lái)的HTML代碼經(jīng)過(guò)解析,構(gòu)建成DOM樹(shù)
- 計(jì)算DOM樹(shù)上的CSS屬性
- 根據(jù)CSS屬性對(duì)元素逐個(gè)渲染拆座,得到內(nèi)存中的位圖
- 中間可能包括對(duì)位圖進(jìn)行合成主巍,極大地增加后續(xù)繪制的速度
- 合成后,在繪制到界面上
9挪凑、回流重繪是什么孕索?
HTML默認(rèn)是流式布局的,但CSS和JS會(huì)打破這種布局躏碳,改變DOM的外觀樣式以及大小和位置搞旭。
reflow(回流)
當(dāng)瀏覽器發(fā)現(xiàn)某個(gè)部分發(fā)生了變化從而影響了布局,這個(gè)時(shí)候就需要倒回去重新渲染
幾乎是無(wú)法避免的,因?yàn)橹灰脩暨M(jìn)行交互操作肄渗,就勢(shì)必會(huì)發(fā)生頁(yè)面的一部分的重新渲染镇眷,且通常我們也無(wú)法預(yù)估瀏覽器到底會(huì)reflow哪一部分的代碼,因?yàn)樗麄儠?huì)相互影響恳啥。
- display:none是回流
減少回流的方式
- 用transform做形變和位移.
- 通過(guò)絕對(duì)位移來(lái)脫離當(dāng)前層疊上下文偏灿,形成新的Render Layer。
repaint(重繪)
當(dāng)我們改變某個(gè)元素的背景色钝的、文字顏色翁垂、邊框顏色等等不影響它周圍或內(nèi)部布局的屬性時(shí),屏幕的一部分要重畫硝桩,但是元素的幾何尺寸和位置沒(méi)有發(fā)生改變沿猜。
- visibility: hidden是重繪
10、圖片懶加載怎么實(shí)現(xiàn)的碗脊?
先將img標(biāo)簽中的src鏈接設(shè)為同一張圖片(空白圖片)啼肩,將其真正的圖片地址存儲(chǔ)再img標(biāo)簽的自定義屬性中(比如data-src)。當(dāng)js監(jiān)聽(tīng)到該圖片元素進(jìn)入可視窗口時(shí)衙伶,即將自定義屬性中的地址存儲(chǔ)到src屬性中祈坠,達(dá)到懶加載的效果。
var viewheight = document.documentElement.clientHeight //可視區(qū)域高度
function lazyload(){
var eles = document.querySelectorAll('img[data-original][lazyload]')
Array.prototype.forEach.call(eles,function(item,index){
var rect;
if(item.dataset.original === '') return;
rect = item.getBoundingClientRect(); //返回元素的大小及其相對(duì)于視口的
if(rect.bottom >= 0 && rect.top < viewheight){
!function(){
var img = new Image();
img.src = item.dataset.url;
img.onload = function(){
item.src = img.src
}
item.removeAttribute('data-original');
item.removeAttribute('lazyload');
}()
}
})
}
11矢劲、vue-lazyloader的原理
一圖勝千言
- vue-lazyload是通過(guò)指令的方式實(shí)現(xiàn)的赦拘,定義的指令是v-lazy指令
- 指令被bind時(shí)會(huì)創(chuàng)建一個(gè)listener,并將其添加到listener queue里面芬沉, 并且搜索target dom節(jié)點(diǎn)躺同,為其注冊(cè)dom事件(如scroll事件)
- 上面的dom事件回調(diào)中,會(huì)遍歷 listener queue里的listener丸逸,判斷此listener綁定的dom是否處于頁(yè)面中perload的位置蹋艺,如果處于則加載異步加載當(dāng)前圖片的資源
- 同時(shí)listener會(huì)在當(dāng)前圖片加載的過(guò)程的loading,loaded黄刚,error三種狀態(tài)觸發(fā)當(dāng)前dom渲染的函數(shù)捎谨,分別渲染三種狀態(tài)下dom的內(nèi)容
原文鏈接,很詳細(xì)的源碼解析:Vue-lazyload原理詳解之源碼解析
12憔维、websocket握手過(guò)程
webstocket是html5的一種新的協(xié)議涛救,是一個(gè)持久化的協(xié)議,相對(duì)于HTTP這種非持久的協(xié)議來(lái)說(shuō)埋同。它實(shí)現(xiàn)了瀏覽器與服務(wù)器的雙向通道州叠,使得數(shù)據(jù)可以快速的雙向傳播
通過(guò)一次簡(jiǎn)單的握手,建立了客戶端和服務(wù)器的聯(lián)系后凶赁,服務(wù)器可以主動(dòng)推送信息給客戶端咧栗,而不需要客戶端的反復(fù)請(qǐng)求
優(yōu)點(diǎn)
- 客戶端和服務(wù)器端之間數(shù)據(jù)交流的表頭比較小逆甜。大概2個(gè)字節(jié)
- 服務(wù)器和客戶端可以主動(dòng)的發(fā)送數(shù)據(jù)給對(duì)方
- 不需要有頻率的創(chuàng)建TCP請(qǐng)求和銷毀,節(jié)約寬帶和服務(wù)器的資源
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
// 一個(gè)Base64 encode的值致板,這個(gè)是瀏覽器隨機(jī)生成的
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
// 一個(gè)用戶定義的字符串交煞,用來(lái)區(qū)分同URL下,不同的服務(wù)所需要的協(xié)議
Sec-WebSocket-Protocol: chat, superchat
// 告訴服務(wù)器所使用的Websocket Draft(協(xié)議版本)
Sec-WebSocket-Version: 13
Origin: http://example.com
服務(wù)器會(huì)返回下列東西
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
// 經(jīng)過(guò)服務(wù)器確認(rèn)斟或,并且加密過(guò)后的 Sec-WebSocket-Key
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
// 表示最終使用的協(xié)議
Sec-WebSocket-Protocol: chat
表示已經(jīng)接受到請(qǐng)求素征, 成功建立Websocket啦!