【面试总结】记一次失败的 bilibili 面试总结(1)

26,475 阅读6分钟

前几日去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 工程化之后,轮子用的多了,但是也得了解底层才行啊。