亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

九宮格經典面試題

1. 前言

其實面試有時候并不像大家想象的那樣問一些很基礎的問題,比如:

  • 請談一下你對CSS盒模型的理解
  • 你對flex布局了解的怎么樣
  • 了解過grid布局嗎
  • 當元素的外邊距為負值時會有什么樣的行為
  • 當元素重疊在一起時如何控制上下層級
  • 如何水平垂直居中
  • 什么是事件冒泡
  • 怎么控制特定位置的元素樣式(比如偶數位置的樣式)
  • 如何判斷事件是從哪個元素冒泡過來的
  • 哪個CSS屬性值可以減少重復定義顏色值

這樣問的話效率會比較低,而優秀的面試題只需要一道,就可以考察上述所有的這些問題。

2. 面試題

即使候選者對上面這些問題全部都對答如流,也不一定能夠靈活的運用這些知識。
而這道面試題不僅考察了候選人的基礎,更考察了候選者對基礎知識的靈活運用,來看看這道面試題:

(鼠標點擊可以互動)

要求如下:

  • 邊框九宮格的每個格子中的數字都要居中
  • 鼠標經過時邊框和數字都要變紅
  • 格子中的數字居中用flex實現
  • 點擊九宮格會彈出對應的數字

具體實現如下:

實例演示
預覽 復制
復制成功!
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 清除默認樣式 */
    * { padding: 0; margin: 0; }

    /* 全屏顯示 */
    html, body { height: 100% }

    body {
      /* 網格布局 */
      display: grid;

      /* 子元素居中 */
      place-items: center;
    }

    /* 父元素 */
    ul {
      width: 300px;
      
      /* 清除默認樣式 */
      list-style: none;

      /* 設置為flex布局 */
      display: flex;

      /* 設置換行 */
      flex-flow: wrap;
    }

    /* 子元素 */
    li {
      /* 顯示為網格布局 */
      display: grid;

      /* 子元素水平垂直居中 */
      place-items: center;

      /* 寬高都是100像素 */
      width: 100px;
      height: 100px;

      /* 設置盒模型 */
      box-sizing: border-box;

      /* 設置兩像素的邊框 */
      border: 2px solid black;

      /* 負邊距 */
      margin: -2px 0 0 -2px;
    }

    /* 第1、4、7個子元素 */
    li:nth-child(3n+1) {
      /* 取消左負邊距 */
      margin-left: 0
    }

    /* 前三個子元素 */
    li:first-child, li:nth-child(2), li:nth-child(3) {
      /* 取消上負邊距 */
      margin-top: 0
    }

    /* 當鼠標經過時 */
    li:hover {
      /* 紅色字體 */
      color: red;

      /* 紅色邊框 */
      border: 2px solid;

      /* 調高層級 */
      z-index: 1;
    }
  </style>
</head>
<body>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
  </ul>
  <script>
    // 選擇ul元素
    const ul = document.getElementsByTagName('ul')[0]

    // 監聽ul元素的點擊事件
    ul.addEventListener('click', e => alert(e.target.innerText))
  </script>
</body>
</html>
運行案例 點擊 "運行案例" 可查看在線運行效果

3. 面試題都考察了哪些上述知識呢

負邊距:

li {
	margin: -2px 0 0 -2px;
}
  • 利用負邊距可以消除邊框粗的bug

flex

ul {
	/* 設置為flex布局 */
    display: flex;

    /* 設置換行 */
    flex-flow: wrap;
} 

grid布局、水平垂直居中

li {
	  /* 網格布局 */
	  display: grid;

	  /* 子元素居中 */
	  place-items: center;
}

減少重復定義顏色值

li:hover {
      /* 紅色字體 */
      color: red;

      /* 紅色邊框 */
      border: 2px solid;
}

可以看到定義紅色邊框的時候并沒有寫紅色(red或#f00),那是因為如果你不寫的話,默認是currentColor,這個關鍵字代表的就是你當前的color值。
有些同學可能會覺得納悶:這單詞這么長,還不如直接寫個red多方便啊,其實這個單詞相當于一個變量,指向color值,而別忘了color是可以繼承的!
如果在一個外層元素中定義了一個顏色,里面的子元素都可以繼承,用JS來控制的話只需要獲取外層DOM元素然后修改它的color樣式即可,currentColor能做的事情很多,這里為了不跑題就先不展開講,有興趣的同學可以去搜一下。

CSS盒模型

li {
	/* 設置盒模型 */
    box-sizing: border-box;
}

如果不寫這個屬性的話,每個格子的邊框也會計算在內,最終會超過父元素的三分之一,導致提前換行。
大家可以在案例中去掉這個屬性,感受一下沒有了它會發生什么樣的后果。

上下層級

li:hover {
	z-index: 1;
}

如果沒有這個屬性,在鼠標經過時邊框的樣式會產生錯亂。

特定位置的元素樣式

/* 第1、4、7個子元素 */
li:nth-child(3n+1) {
	xxx: xxx;
}

/* 前三個子元素 */
li:first-child, li:nth-child(2), li:nth-child(3) {
  xxx: xxx;
}

事件冒泡

// 監聽ul元素的點擊事件
ul.addEventListener('click', e => alert(e.target.innerText))

4. 小結

怎么樣,沒想到就這一道九宮格居然能考察出這么多的基礎知識吧?
同學們課下一定要好好練習一下這道題,親自動手敲一遍代碼,看看能不能在不參照案例代碼的情況實現這個功能。