1. router兩種模式實現原理
****hash模式:****
在URL后添加#后面的字符稱之為hash,可以通過window.location.hash屬性讀取,它用來指導瀏覽器動作的,對服務端無用,因此修改hash不會重新加載頁面。
每一次改變hash(window.location.hash),都會在瀏覽器的訪問歷史中增加一個記錄。
通過hashchange( `window.addEventListener("hashchange", fn, false)`)監聽hash變化。
通過window.location.hash = path或者window.location.replace(url+'#'+path)改變。
```
function pushHash (path) {
window.location.hash = path
}
```
```
function replaceHash (path) {
const i = window.location.href.indexOf('#')
window.location.replace(
window.location.href.slice(0, i >= 0 ? i : 0) + '#' + path
)
}
```
****history模式:****
History interface是瀏覽器歷史記錄棧提供的接口,通過back(), forward(), go()等方法,我們可以讀取瀏覽器歷史記錄棧的信息,進行各種跳轉操作。
從HTML5開始,History interface提供了兩個新的方法:pushState(), replaceState()使得我們可以對瀏覽器歷史記錄棧進行修改:
```
window.history.pushState(stateObject, title, URL)
window.history.replaceState(stateObject, title, URL)
```
history的一些優勢:
* pushState設置的新URL可以是與當前URL同源的任意URL;而hash只可修改#后面的部分,故只可設置與當前同文檔的URL
* pushState設置的新URL可以與當前URL一模一樣,這樣也會把記錄添加到棧中;而hash設置的新值必須與原來不一樣才會觸發記錄添加到棧中
* pushState通過stateObject可以添加任意類型的數據到記錄中;而hash只可添加短字符串
* pushState可額外設置title屬性供后續使用
****區別:****
* 前面的hashchange,你只能改變#后面的url片段。而pushState設置的新URL可以是與當前URL同源的任意URL。
* history模式則會將URL修改得就和正常請求后端的URL一樣,如后端沒有配置對應/user/id的路由處理,則會返回404錯誤
****404錯誤****
* hash模式下,僅hash符號之前的內容會被包含在請求中,如 [http://www.abc.com](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.abc.com), 因此對于后端來說,即使沒有做到對路由的全覆蓋,也不會返回404錯誤;
* history模式下,前端的url必須和實際向后端發起請求的url 一致,如[http://www.abc.com/book/id](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.abc.com%2Fbook%2Fid) 。如果后端缺少對/book/id 的路由處理,將返回404錯誤。
2. 三次握手和四次揮手(瀏覽器輸入URL發生了什么),http1/1.1/2、https等,協商緩存與強緩存。
三次握手:
目的:同步序列號
(1)第一次握手:建立連接時,客戶端A發送SYN包(SYN=j)到服務器B,并進入SYN_SEND狀態,等待服務器B確認。
(2)第二次握手:服務器B收到SYN包,必須確認客戶A的SYN(ACK=j+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時服務器B進入SYN\_RECV狀態。
(3)第三次握手:客戶端A收到服務器B的SYN+ACK包,向服務器B發送確認包ACK(ACK=k+1),此包發送完畢,客戶端A和服務器B進入ESTABLISHED狀態,完成三次握手,客戶端與服務器開始傳送數據。
為什么要三次握手?
三次握手的**首要原因是為了防止舊的重復連接初始化造成混亂。**
客戶端連續發送多次 SYN 建立連接的報文,在網絡擁堵等情況下:
* 一個「舊 SYN 報文」比「最新的 SYN 」 報文早到達了服務端;
* 那么此時服務端就會回一個 `SYN + ACK` 報文給客戶端;
* 客戶端收到后可以根據自身的上下文,判斷這是一個歷史連接(序列號過期或超時),那么客戶端就會發送 `RST` 報文給服務端,表示中止這一次連接。

四次揮手
* 客戶端打算關閉連接,此時會發送一個 TCP 首部 `FIN` 標志位被置為 `1` 的報文,也即 `FIN` 報文,之后客戶端進入 `FIN_WAIT_1` 狀態。
* 服務端收到該報文后,就向客戶端發送 `ACK` 應答報文,接著服務端進入 `CLOSED_WAIT` 狀態。
* 客戶端收到服務端的 `ACK` 應答報文后,之后進入 `FIN_WAIT_2` 狀態。
* 等待服務端處理完數據后,也向客戶端發送 `FIN` 報文,之后服務端進入 `LAST_ACK` 狀態。
* 客戶端收到服務端的 `FIN` 報文后,回一個 `ACK` 應答報文,之后進入 `TIME_WAIT` 狀態
* 服務器收到了 `ACK` 應答報文后,就進入了 `CLOSE` 狀態,至此服務端已經完成連接的關閉。
* 客戶端在經過 `2MSL` 一段時間后,自動進入 `CLOSE` 狀態,至此客戶端也完成連接的關閉。

301:永久重定向
302:臨時重定向
強緩存:在請求頭設置cache-control,狀態:200。
協商緩存:如果資源沒有改變,**狀態為304**,瀏覽器讀取本地緩存資源即可;如果返回200,則是返回最新資源。在請求頭中設置last-modified和etag即可。etag是http1.1出現的,為解決last-modifed的缺點。
last-modified缺點:
1. 一些文件也許會周期性的更改,但是他的內容并不改變(僅僅改變的修改時間),這個時候我們并不希望客戶端認為這個文件被修改了,而重新get;
2. 某些文件修改非常頻繁,比如在秒以下的時間內進行修改,(比方說1s內修改了N次),if-modified-since能檢查到的粒度是秒級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);
3. 某些服務器不能精確的得到文件的最后修改時間。
3. Promise手寫、async/await知識
4. [apply、call、bind原理與手寫](http://www.hmoore.net/vvmily_king/vvmily/2667748)
5. css居中等布局,響應式布局,em、rem、rpx
6. 時間復雜度
7. 堆棧,隊列,事件循環
棧:后進先出,類似一個桶,先放下去的在底部,后放上去在上面,需要從上面往下拿,一直到底部。
堆:常是一個可以被看做一棵樹的數組對象。
隊列:先進先出,類似排隊,先來排隊的人,先到出口,后面來的人只能在隊尾疊加,既只能從隊頭刪除,隊尾插入。
主線程函數(任務)執行,遇到異步函數等,依次存放到棧中,而此時根據異步模塊的(條件)不同,進入不同的任務隊列中,此時微任務在執行至棧為空,在按照隊列先進先出的方式,在隊列中讀取任務,以此反復到結束,為時間循環。
8. 宏觀微觀任務(注意:瀏覽器環境和node環境執行存在差異)
宏任務一般是:包括整體代碼`script`,`setTimeout`,`setInterval`、`I/O`、`UI render`。
微任務主要是:`Promise`、`Object.observe`、`MutationObserver`、process.nextTick。
參考:https://segmentfault.com/a/1190000016278115
11. vue 父子組件渲染順序
當前組件渲染順序:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
父子組件渲染順序:父beforeCreate、父created、父beforeMount、子beforeCreate、子created、子beforeMount、子mounted、父mounted
父子更新渲染順序:父beforeUpdate、子beforeUpdate、子updated、父updated
12. vue2和vue3的區別 (vue3快在哪)
* diff算法增加patchFlag靜態標識,只對比有靜態標識的dom元素
* 事件增加緩存
* 很多文本節點提升 只定義一次,渲染時不需要再次定義,vue2每次都需要重新定義
* ssr渲染 以字符串方式渲染
* proxy替換了之前的defineProterty
* vite
* ts
13. 性能優化?https://juejin.cn/post/7026947170683076621
14. 不建議index作為key值原因
* 用 index 作為 key 時,在對數據進行,逆序添加,逆序刪除等破壞順序的操作時,會產生沒必要的真實 DOM更新,從而導致效率低
* 用 index 作為 key 時,如果結構中包含輸入類的 DOM,會產生錯誤的 DOM 更新
* 在開發中最好每條數據使用唯一標識固定的數據作為 key,比如后臺返回的 ID,手機號,身份證號等唯一值
* 如果不存在對數據逆序添加,逆序刪除等破壞順序的操作時,僅用于渲染展示用時,使用 index 作為 key 也是可以的(但是還是不建議使用,養成良好開發習慣)。
12. 構造函數與原型鏈繼承
13. 狀態管理:vuex4.x / vuex5.x(pinia) / mitt.js,本地持久化?
15. vite/webpack等優化,配置
16. git:常用那些命令,對git rebase有使用嗎?提交規范有約束嗎?
17. 本地存貯:cookie、localStore、sessionStore
18. 跨域
* iframe + document.domain location.hash window.name等三種
* postMessage
* proxyTable
* nodejs 中間件
* cors
* websocket
* jsonp
* nginx反向代理
19. 設計模式有哪些?
20. 小程序相關問題
21. 移動端相關問題
22. ts相關問題
- 首頁
- 2021年
- 基礎知識
- 同源策略
- 跨域
- css
- less
- scss
- reset
- 超出文本顯示省略號
- 默認滾動條
- 清除浮動
- line-height與vertical-align
- box-sizing
- 動畫
- 布局
- JavaScript
- 設計模式
- 深淺拷貝
- 排序
- canvas
- 防抖節流
- 獲取屏幕/可視區域寬高
- 正則
- 重繪重排
- rem換算
- 手寫算法
- apply、call和bind原理與實現
- this的理解-普通函數、箭頭函數
- node
- nodejs
- express
- koa
- egg
- 基于nodeJS的全棧項目
- 小程序
- 常見問題
- ec-canvas之橫豎屏切換重繪
- 公眾號后臺基本配置
- 小程序發布協議更新
- 小程序引入iconfont字體
- Uni-app
- 環境搭建
- 項目搭建
- 數據庫
- MySQL數據庫安裝
- 數據庫圖形化界面常用命令行
- cmd命令行操作數據庫
- Redis安裝
- APP
- 控制縮放meta
- GIT
- 常用命令
- vsCode
- 常用插件
- Ajax
- axios-services
- 文章
- 如何讓代碼更加優雅
- 虛擬滾動
- 網站收藏
- 防抖節流之定時器清除問題
- 號稱破解全網會員的腳本
- 資料筆記
- 資料筆記2
- 公司面試題
- 服務器相關
- 前端自動化部署-jenkins
- nginx.conf配置
- https添加證書
- shell基本命令
- 微型ssh-deploy前端部署插件
- webpack
- 深入理解loader
- 深入理解plugin
- webpack注意事項
- vite和webpack區別
- React
- react+antd搭建
- Vue
- vue-cli
- vue.config.js
- 面板分割左右拖動
- vvmily-admin-template
- v-if與v-for那個優先級高?
- 下載excel
- 導入excel
- Echart-China-Map
- vue-xlsx(解析excel)
- 給elementUI的el-table添加骨架
- cdn引入配置
- Vue2.x之defineProperty應用
- 徹底弄懂diff算法的key作用
- 復制模板內容
- 表格操作按鈕太多
- element常用組件二次封裝
- Vue3.x
- Vue3快速上手(第一天)
- Vue3.x快速上手(第二天)
- Vue3.x快速上手(第三天)
- vue3+element-plus搭建項目
- vue3
- 腳手架
- vvmily-cli
- TS
- ts筆記
- common
- Date
- utils
- axios封裝
- 2022年
- HTML
- CSS基礎
- JavaScript 基礎
- 前端框架Vue
- 計算機網絡
- 瀏覽器相關
- 性能優化
- js手寫代碼
- 前端安全
- 前端算法
- 前端構建與編譯
- 操作系統
- Node.js
- 一些開放問題、智力題