【面試總結】記一次失敗的 bilibili 面試總結(1)

一顆賽艇?發表於2019-03-12

前幾日去B站面試了一次前端,不算資深B站使用者,平常也蠻喜歡在B站觀看視訊的,能獲得這樣的面試機會,實在是受寵若驚。但無奈實力有限加上瑣事纏身,並沒有做好充足的準備,導致面試失敗。

(ps:屬實還是有點緊張,發揮也受到影響)

這次面試過程我思前想後覺得有必要總結一下,希望自己下次再有這樣的機會的時候能夠把握的更好。

因內容比較多,所以準備可能分多篇部落格更新內容,這裡給出傳送門

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結構,需求如下:

  1. 完成經典的上 header ,下 footer ,左邊是側邊欄,右邊是內容。
  2. 去掉列表前面的 · ,列表項水平排列,注意裡面的br標籤需要換行,同時每兩個li後有一條豎線。
  3. 點選列表項不跳轉,彈出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 工程化之後,輪子用的多了,但是也得了解底層才行啊。

相關文章