加載過程
- DNS 解析:域名→IP 地址
- 瀏覽器根據(jù) IP 地址向服務(wù)器發(fā)起 http 請(qǐng)求
- 服務(wù)器處理 http 請(qǐng)求耽梅,并返回給瀏覽器
渲染過程
- 根據(jù) HTML 代碼生成 DOM Tree
- 根據(jù) CSS 代碼生成 CSSOM
- 將 DOM Tree 和 CSSOM 整合成 Render Tree
- 根據(jù) Render Tree 渲染頁面
- 遇到<script>則暫停渲染,優(yōu)先加載并執(zhí)行 js 代碼眼姐,完成再繼續(xù)
- 直到 Render Tree 渲染完成
windows.onload 和 DOMContentLoaded 的區(qū)別
- windows.onload 資源全部加載完才能執(zhí)行,包括圖片視頻等
- DOMContentLoaded DOM 渲染完成就執(zhí)行众旗,圖片視頻可能還未下載
性能優(yōu)化原則
- 多使用內(nèi)存、緩存或其他方法
- 減少 CPU 計(jì)算量贡歧,減少網(wǎng)絡(luò)加載耗時(shí)
- (適用于所有的編程性能優(yōu)化——空間換時(shí)間)
讓加載得更快
- 減少資源體積:壓縮代碼
- 減少訪問次數(shù):合并代碼,SSR 服務(wù)端渲染(將網(wǎng)頁和數(shù)據(jù)一起加載利朵,一起渲染),緩存
- 使用更快的網(wǎng)絡(luò):CDN
讓渲染的更快
- CSS 放在 head绍弟,JS 放在 body 最下面
- 盡早開始執(zhí)行 JS,用 DOMContentLoaded 觸發(fā)
- 懶加載(圖片懶加載)
- 對(duì) DOM 查詢進(jìn)行緩存
- 頻繁 DOM 操作的晌柬,合并到一起插入 DOM 結(jié)構(gòu)
- 節(jié)流 throttle 防抖 debounce
防抖 debounce
- 監(jiān)聽一個(gè)輸入框的文字變化后觸發(fā) change 事件
- 直接監(jiān)聽郭脂,會(huì)頻繁觸發(fā)
- 防抖,當(dāng)用戶輸入結(jié)束或者暫停輸入是展鸡,才會(huì)觸發(fā)change 事件
function debounce(fn, delay = 500) {
let timer = null;
return function() {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
let input1 = document.getElementById('input1')
input1.addEventListener('keyup', debounce(() => {
console.log(input1.value);
}))
節(jié)流 throttle
使用場(chǎng)景:
- 拖拽一個(gè)元素時(shí),要隨時(shí)拿到該元素被拖拽的位置
- 直接使用drag事件涤久,則會(huì)頻繁觸發(fā),容易導(dǎo)致卡頓
- 節(jié)流响迂,無論速度多快,每隔 100ms 觸發(fā)一次
function throttle (fn, delay = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
let drag1 = document.getElementById('drag1')
drag1.addEventListener('drag', throttle((e) => {
console.log(e.offsetX, e.offsetY)
}))
安全
XSS 攻擊
場(chǎng)景:一個(gè)博客網(wǎng)站蔗彤,被人嵌入<script>腳本疯兼,腳本內(nèi)容然遏,獲取 cookie吧彪,發(fā)送到攻擊者的服務(wù)器
預(yù)防:替換特殊字符,如 < 變?yōu)?< > 變?yōu)?>
XSRF 攻擊
場(chǎng)景:商品購(gòu)買鏈接姨裸,沒有任何驗(yàn)證怨酝,則可以偽造該鏈接誘導(dǎo)用戶點(diǎn)擊
預(yù)防:使用 post 接口,增加驗(yàn)證凫碌,如密碼胃榕、驗(yàn)證碼