前幾日去B站面試了一次前端,不算資深B站使用者,平常也蠻喜歡在B站觀看視訊的,能獲得這樣的面試機會,實在是受寵若驚。但無奈實力有限加上瑣事纏身,並沒有做好充足的準備,導致面試失敗。
(ps:屬實還是有點緊張,發揮也受到影響)
這次面試過程我思前想後覺得有必要總結一下,希望自己下次再有這樣的機會的時候能夠把握的更好。
因內容比較多,所以準備可能分多篇部落格更新內容,這裡給出傳送門
- HTML佈局、CSS選擇器及JS基礎綜合能力知識點
- 演算法基礎:陣列 flat、去重及排序
- react vue 理解及基礎知識
- 跨域問題解決方案
- http協議狀態碼
- 快取及更新問題
- webview與原生應用互動
- 伺服器端知識
ps:這是大綱,後續可能有變化。比如伺服器端知識,我沒有接觸過,面試官就沒問,但確實是面試過程中的一個大類的問題。
面試感受
面試過程整體感覺很舒服,面試官很有耐心,面試題由淺入深,面試打分的話,我會給5顆星。
HTML佈局、CSS選擇器及JS基礎綜合能力知識點
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body,
#app {
margin: 0;
padding: 0;
height: 100%;
}
#header, #footer {
height: 50px;
line-height: 50px;
text-align: center;
background: #555;
color: #fff;
}
#side {
width: 200px;
background: #eee;
}
/* css here */
</style>
</head>
<body>
<div id="app">
<header id="header">header</header>
<aside id="side">side</aside>
<div id="main">
<ul>
<li><a href="https://www.bilibili.com/1">Link1</a></li>
<li><a href="https://www.bilibili.com/1">Link2</a></li>
<li><a href="https://www.bilibili.com/1">Link3</a></li>
<br>
<li><a href="https://www.bilibili.com/1">Link4</a></li>
<li><a href="https://www.bilibili.com/1">Link5</a></li>
</ul>
</div>
<footer id="footer">footer</footer>
</div>
<script>
// JS here
</script>
</body>
</html>
複製程式碼
不考慮相容性且不能更改dom結構,需求如下:
- 完成經典的上 header ,下 footer ,左邊是側邊欄,右邊是內容。
- 去掉列表前面的 · ,列表項水平排列,注意裡面的br標籤需要換行,同時每兩個li後有一條豎線。
- 點選列表項不跳轉,彈出href內的內容。
ANSWER 1:
時光回溯:
這道面試題是基礎題,我應該要多向面試官展示一下我的基本功,同時也要告訴面試官,我是有關注前端最新的動態的,既然不考慮相容性,我得先用 Grid 的方案實現一遍,然後在告訴面試官我大概還有108種不同的解法,?哈哈哈...。然後 Grid 除了 display: grid 外,好久沒有寫了,我都忘記的差不多了吧。在思考 Grid 的時候,時間浪費了太久,我得趕緊找個簡單的寫法先提交,不然基礎題都得做這麼久,印象肯定不行。
浮動解決方案:
/**
* calc 是 css的一個函式
* 不明白的同學我附上鍊接
* https://developer.mozilla.org/zh-CN/docs/Web/CSS/calc
*/
#side {
/* 設定 側邊欄 左浮動 */
float: left;
height: calc(100% - 100px);
}
#main {
height: calc(100% - 100px);
}
複製程式碼
position 解決方案:
#app {
/* 父級元素 設定 相對定位 */
position: relative;
}
#side {
/* 左邊欄 設定 絕對定位 */
position: absolute;
top: 50px;
bottom: 50px;
left: 0;
}
#main {
/* 內容區 設定 絕對定位 */
position: absolute;
top: 50px;
right: 0;
bottom: 50px;
left: 200px;
}
#footer {
/* footer 設定 絕對定位 */
position: absolute;
bottom: 0;
width: 100%; /* 設定浮動後,補上寬度 */
}
複製程式碼
Flex 解決方案:
❌受限於無法更改 DOM 結構,我覺得難以使用 Flex 去實現這個需求。或者請求高人指點一二。
晚上吃飯的時候突然有了 Flex 解決這個問題的思路,感謝評論區同學給的幫助。
#app {
display: flex;
flex-wrap: wrap;
}
#header {
flex-basis: 100%;
}
#side {
height: calc(100% - 100px);
}
#main {
flex: 1;
height: calc(100% - 100px);
}
#footer {
flex-basis: 100%;
}
複製程式碼
Grid 解決方案:
參考資料
本文不贅述Grid的所有內容,有需要的朋友可以傳送門詳細瞭解。下面我會介紹我用到的部分。
#app {
/* app 為 grid 佈局的容器,所以在此處建立 grid 佈局 */
display: grid;
/**
這是一種縮略的寫法 等價於
grid-template-rows: 50px auto 50px;
grid-template-columns: 200px auto;
建立了一個 3 * 2 的格子
高度是 50px 自動 50px
寬度是 200px 自動
*/
grid: 50px auto 50px / 200px auto;
}
/* 這個時候其實開啟頁面看著很奇怪,header 縮在角落,等等 */
#header, #footer {
/**
-*- 重要 -*-
下面的寫法 等價於
grid-column-star: 1;
grid-column-end: 3;
該 grid 的子項
開始與 第一根 column 線
結束與 第三根 column 線
*/
grid-column: 1 / 3;
}
複製程式碼
#app {
display: grid;
/**
等價於
grid-template-rows: 50px auto 50px;
grid-template-columns: 200px auto;
grid-template-areas:
"header header"
"side main"
"footer footer";
注意: 每一 row 只是一個字串
*/
grid: "header header" 50px "side main" auto "footer footer" 50px / 200px auto;
}
#header {
/* 注意: header 沒有雙引號 */
grid-area: header;
}
#footer {
grid-area: footer;
}
複製程式碼
ANSWER 2:
時間回溯:
取消 · 沒有難度。這個題目的難點就在這個 br 標籤,本來可以直接使用 flex 佈局,現在的話看情況應該只能使用 inline 或者 inline-block 的方式進行水平排列了。加豎線可以用偽類選擇器和偽類元素選擇器組合實現,但是我忘記了 :nth-of-type 偽類選擇器。
ul {
/* 去掉 · */
list-style: none;
}
ul li {
/* 水平排列,兩個都行*/
display: inline;
/* display: inline-block; */
}
複製程式碼
當時最後一個加豎線的需求,我是這樣寫的。
/* 偽類選擇器 + 偽類元素選擇器 */
ul li:nth-child(2n)::after {
content: '|';
}
複製程式碼
但是隻有 Link2 Link5 後面會出現 "|",因為 br 標籤的緣故,失敗。
但只需要稍加修改就可以完成,但面試的時候沒有完成。
/* 偽類選擇器 + 偽類元素選擇器 */
ul li:nth-of-type(2n)::after {
content: '|';
}
複製程式碼
後來詢問了面試官這個應該如何解決,得知可以考慮兄弟選擇器試試。
TODO: 我目前還沒有想出來如何處理。Help!
ANSWER 3:
沒啥好說的。把事件繫結在父元素上,節約記憶體。考察點就是原生dom的一些操作吧。
document.querySelectorAll('ul')[0].addEventListener('click',event => {
if(event.target.tagName === 'A') {
event.preventDefault(); // 阻止預設行為
alert(event.target.getAttribute('href'));
}
});
複製程式碼
總結:
- 前三種方式都是比較傳統的佈局方式,確實能解決問題,但是比較抽象。
- Grid 的佈局方式是一個二維的基於網格的佈局系統,它的目標是完全改變我們基於網格的使用者介面的佈局方式。當使用這種佈局方式的時候,在chrome中開啟除錯,能很清晰的看見網格的存在。相對於前三種,直觀方便快捷。
- 偽類選擇器這種日常可能不常用的東西可能就是面試的盲點。
- javascript 工程化之後,輪子用的多了,但是也得了解底層才行啊。