### 網頁加載渲染過程
#### 加載資源的過程
* DNS 解析:域名 -> IP 地址
* 瀏覽器根據 IP 地址向服務器發起 http 請求
* 服務器處理 http 請求,并返回給瀏覽器
#### 渲染過程
* 根據 HTML 代碼生成 DOM Tree;DOM:document object model
* 根據 CSS 代碼生成 CSSOM
* 將 DOM Tree 和 CSSOM 整合形成 Render Tree(渲染樹)
* 根據 Render Tree 渲染頁面
* 遇到 `<script>` 則暫停渲染,優先加載并執行 JS 代碼,完成在繼續
* 直至 Render Tree 渲染完成
##### window.onload 和 DOMContentLoaded區別
```javascript
document.addEventListener('DOMContentLoaded', function () {
// DOM 渲染完即可執行,此時圖片、視頻可能還沒有加載完成
console.log('1')
})
window.addEventListener('load', function () {
// 頁面的全部資源加載完,才會執行,包括圖片、視頻等
console.log('2')
})
```
### 性能優化
#### 性能優化原則
* 多使用內存、緩存或其他方法
* 減少 CPU 計算量,減少網絡加載耗時
* (適用于所有編程的性能優化---空間換時間)
#### 從何入手
* 讓加載更快
* 減少資源代碼:壓縮代碼
* 減少訪問次數:合并代碼,SSR 服務端渲染,緩存
* 使用更快的網絡:CDN
* 讓渲染更快
* CSS 放 head ,JS 放在 body 最下面
* 今早開始執行 JS ,用 DOMContentLoaded 觸發
* 懶加載(圖片懶加載,上滑加載更多)
* 對 DOM 查詢進行緩存
* 頻繁 DOM 操作,合并到一起插入 DOM 結構
* 節流 throttle 防抖 debounce
* SSR--Server-Side Rendering
* 服務端渲染:將網頁和數據一起加載,一起渲染
* 非 SSR (前后端分離):先加載網頁,再加載數據,再渲染數據
#### 防抖 debounce
> 監聽一個輸入框,文字變化后觸發 change 事件;直接用 keyup 事件,則會頻繁觸發 change 事件;
>
> 防抖:用戶輸入結束或暫停時,才會觸發 change 事件。
>
> 擴展閱讀:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/5
```javascript
// 純 JS 中寫法
let timer = null
function debounce() { // debounce 函數會被快速多次執行
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(()=>{
// 業務代碼
// 清空定時器
timeer = null
},500)
}
```
```javascript
// 封裝一下,使其實用性更強
function debounce(fn, dealy = 500) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, dealy)
}
}
// 使用
function demo() {
// 業務函數
console.log('業務函數')
}
input1.addEventListener('keyup', debounce(demo, 300))
```
#### 節流 throttle
> 拖拽一個元素時,要隨時按到該元素被拖拽的位置;直接用 drag 事件,則會頻繁觸發,很容易導致卡頓;節流:無論拖拽速度多快,都會每隔 100ms 觸發一次
```html
<!-- 基礎寫法 -->
<div id="div1" draggable="true">可拖拽</div>
<script>
const div1 = document.getElementById('div1')
let timer = null
div1.addEventListener('drag', function (event) {
if (timer) {
return
}
timer = setTimeout(() => {
console.log(event.offsetX, event.offsetY)
timer = null
}, 100)
})
</script>
```
```javascript
// 封裝一下
function throttle(fn, frequency = 100) {
let timer = null
return function () {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, frequency)
}
}
// 使用
const div1 = document.getElementById('div1')
div1.addEventListener(
'drag',
throttle((event) => {
console.log(event.offsetX, event.offsetY)
})
)
```
### 安全
擴展閱讀:[前端安全系列(一):如何防止XSS攻擊?](https://tech.meituan.com/2018/09/27/fe-security.html)
#### XSS 跨站請求攻擊
> 一個博客網站,我發表一篇博客,其中嵌入 `<script>` 腳本;腳本內容:獲取 cookie,發送到我的服務器(服務器 配合跨域);發布這篇博客,有人查看它,我輕松收割訪問者的 cookie
* XSS 預防

#### XSRF 跨站請求偽造


* XSRF 預防
