<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一次令人窒息的百度面試

          共 29502字,需瀏覽 60分鐘

           ·

          2023-01-09 20:38

          最近接到了百度的面試,個人覺得基礎(chǔ)知識準(zhǔn)備的比較充分,就去網(wǎng)上找了一些百度的面經(jīng),冥冥之中我在眾多的面試題中打開了下邊兩個面試題:

          2021百度前端社招面經(jīng)

          百度前端面試題分享,帶答案

          看完之后我直呼“哇哦~”,全部在我的射程范圍之內(nèi)。我該不會如此幸運(yùn)到問的全會吧。

          是的,答案就是不會,我就是沒有幸運(yùn)到問的全會。

          話不多說,接下來就回顧下面試的問題。

          看簡歷

          上來首先是萬年不變的自我介紹,介紹完之后面試官就開始逐行看我的簡歷,并針對簡歷上的項(xiàng)目經(jīng)歷進(jìn)行詢問。詢問的十分詳細(xì)。

          如何實(shí)現(xiàn)新手指引

          問這個問題的原因是我簡歷上寫到了使用driver.js庫實(shí)現(xiàn)了新手指引。

          使用js實(shí)現(xiàn)如下:

          <!DOCTYPE html>
          <html lang="en">

          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>新手指引功能</title>
              <style>
                  * {
                      margin0;
                      padding0;
                  }

                  body {
                      box-sizing: border-box;
                  }

                  .stepBlock {
                      background-color: burlywood;
                      margin-right20px;
                  }

                  .positionStyle{
                      position: absolute;
                      z-index200;
                  }

                  /* 蒙層樣式 */
                  .overlay {
                      position: fixed;
                      top0;
                      left0;
                      right0;
                      bottom0;
                      background-colorrgba(000, .5);
                      z-index100;
                  }
              
          </style>
          </head>

          <body>
              <section id="mask">
                  <section class="positionStyle" id="tip"></section>
                  <section class="positionStyle" id="curStepMask"></section>
              </section>

              <section style="margin:200px;">
                  <span id="first" class="stepBlock">
                      第一步
                  </span>
                  <span id="second" class="stepBlock">
                      第二步
                  </span>
                  <span id="third" class="stepBlock">
                      第三步
                  </span>
              </section>

              <section style="margin-top:30px">
                  <button onclick="setMask()">開始指引</button>
              </section>

              <script>
                  const tipDict = [
                      { id'first'content'這里是第1步哦' },
                      { id'second'content'這里是第2步哦' },
                      { id'third'content'這里是最后一步哦,點(diǎn)擊完成按鈕結(jié)束新手指引' },
                  ]
                  let flag = 0;

                  function setMask() {
                      // 添加蒙層
                      let mask = document.getElementById('mask')
                      mask.setAttribute('class''overlay')
                      setTip()
                  }

                  function removeMask() {
                      // 移除蒙層
                      let mask = document.getElementById('mask')
                      mask.setAttribute('class''')

                      // 移除tip提示的子元素
                      removeTip()
                      removeStepMask()
                  }

                  function setTip() {
                      if (flag < tipDict.length) {
                          // 獲取當(dāng)前步驟的元素,以及元素的位置信息,供后續(xù)定位提示信息和覆蓋信息使用
                          const curStepEle = document.getElementById(tipDict[flag].id)
                          const bound = curStepEle.getBoundingClientRect()

                          // 找到id為tip的元素
                          let ele = document.getElementById("tip")

                          // 如果存在子元素,先移除
                          removeTip()
                          removeStepMask()

                          // 創(chuàng)建提示信息和下一步的統(tǒng)一父元素,方便后續(xù)移除元素
                          let node = document.createElement('div')
                          // 創(chuàng)建提示信息
                          let tipText = document.createTextNode(tipDict[flag].content)
                          // 將提示信息插入到父元素
                          node.appendChild(tipText)
                          // 創(chuàng)建“下一步”按鈕
                          let nextBtn = document.createElement('button')
                          nextBtn.innerHTML = flag === tipDict.length - 1 ? '完成' : '下一步';
                          nextBtn.onclick = setTip;
                          // 將按鈕插入到父元素
                          node.appendChild(nextBtn)
                          // 設(shè)置統(tǒng)一父元素的位置


                          ele.style.left = bound.x + 'px'
                          ele.style.top = bound.y + 20 + 'px'
                          // 將統(tǒng)一的父元素插入到id為tip的元素
                          ele.appendChild(node)

                          // 將當(dāng)前步驟高亮顯示
                          let tag = flag - 1
                          if (tag >= 0) {
                              document.getElementById(tipDict[tag].id).style = ''
                          }
                          // const curStepEle = document.getElementById(tipDict[flag].id)
                          // const bound = curStepEle.getBoundingClientRect()

                          const curStepMask = document.getElementById('curStepMask')
                          curStepMask.style.left = bound.x + 'px'
                          curStepMask.style.top = bound.y + 'px'

                          const curStepEleClone = curStepEle.cloneNode(true)
                          curStepMask.appendChild(curStepEleClone)

                          flag++
                      } else {
                          flag = 0;
                          removeMask()
                      }
                  }
                  function removeStepMask() {
                      let ele = document.getElementById('curStepMask')
                      let child = ele.lastElementChild
                      if (child) {
                          ele.removeChild(child)
                      }
                  }
                  function removeTip() {
                      let ele = document.getElementById("tip")
                      let child = ele.lastElementChild
                      if (child) {
                          ele.removeChild(child)
                      }
                  }
              
          </script>
          </body>

          </html>
          復(fù)制代碼

          注意元素中包含如下結(jié)構(gòu):

          <section id="mask"> 
              <section class="positionStyle" id="tip"></section> 
              <section class="positionStyle" id="curStepMask"></section>
          </section>
          復(fù)制代碼

          實(shí)現(xiàn)思路是:

          • 點(diǎn)擊“開始指引”:找到id為mask的元素,為該元素添加蒙層樣式(setMask)
          • 添加提示信息:找到id為tip的元素,將提示信息添加為該元素的子元素(setTip)
          • 高亮當(dāng)前步驟元素:找到當(dāng)前目標(biāo)元素,克隆目標(biāo)元素,然后將克隆后的目標(biāo)元素添加為curStepMask的子元素(setTip)
          • 定位tip和curStepMask的元素:curStepMask元素在當(dāng)前目標(biāo)元素的正上方,tip元素根據(jù)情況而定
          • 每次添加當(dāng)前提示信息時要移除上一次添加的提示信息和覆蓋元素(removeTip,removeStepMask)

          getBoundingClientRect

          返回值是一個 `DOMRect`[3] 對象,是包含整個元素的最小矩形(包括 padding 和 border-width)。該對象使用 left、topright、bottom、x、y、width 和 height 這幾個以像素為單位的只讀屬性描述整個矩形的位置和大小。除了 width 和 height 以外的屬性是相對于視圖窗口的左上角來計(jì)算的。--MDN

          image.png

          圖片上有一個人臉,除了臉部以外加上蒙層

          方案一:

          添加遮罩層,在圖片上方添加一張只有人臉的圖片:


          <!DOCTYPE html>
          <html lang="en">

          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>圖片添加蒙層</title>
              <style type="text/css">
                  img {
                      position: absolute;
                      top50%;
                      left50%;
                      width300px;
                  }

                  .overlay {
                      position: fixed;
                      top0;
                      right0;
                      bottom0;
                      left0;
                      background-colorrgba(000, .5);
                      z-index100;
                  }
              
          </style>
          </head>

          <body>
              <div class="overlay">
                  <img src="../images/mask.png" style="width:200px" />
              </div>
              <img src="../images/cat.png" />
          </body>

          </html>
          復(fù)制代碼

          最終實(shí)現(xiàn)效果:(沒有用一模一樣的圖片,只是模擬了類似的效果)

          image.png

          上述是在整個頁面添加蒙層,若想只在圖片部分添加蒙層:

          <!DOCTYPE html>
          <html lang="en">

          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>圖片添加蒙層</title>
              <style type="text/css">
                  img {
                      width300px;
                  }

                  .overlay {
                      position: absolute;
                      top0;
                      right0;
                      bottom0;
                      left0;
                      background-colorrgba(000, .5);
                      z-index100;
                  }
              
          </style>
          </head>

          <body>
              <div style="position: relative;width: 300px;">
                  <div class="overlay">
                      <img src="../images/kid.png" style="width:200px" />
                  </div>
                  <img src="../images/cat.png" />
              </div>
          </body>

          </html>
          復(fù)制代碼

          效果:

          image.png

          echarts動畫實(shí)現(xiàn)原理

          對Echarts目前處于使用的水平,原理后續(xù)學(xué)習(xí)的話再補(bǔ)上吧~~~

          了解canvas嗎

          HTML5 <canvas> 元素用于圖形的繪制,通過腳本 (通常是JavaScript)來完成。

          <canvas> 標(biāo)簽只是圖形容器,必須使用腳本來繪制圖形。

          可以通過多種方法使用 canvas 繪制路徑,盒、圓、字符以及添加圖像。

          canvas教程傳送門[4]

          如何實(shí)現(xiàn)組件滑動切換效果

          不使用react-transition-group

          對語義化的理解

          語義化就是正確的標(biāo)簽做正確的事。語義化的好處在于:

          • 對于開發(fā)團(tuán)隊(duì)而言,代碼更加容易維護(hù)
          • 在css沒有加載出來的情況下也能很好的展示結(jié)構(gòu)
          • 有利于SEO優(yōu)化
          • 更好地支持各種終端,例如無障礙閱讀和有聲小說等

          HTML5有哪些語義化標(biāo)簽

          常用的語義化標(biāo)簽有:

          • header:定義頁眉信息
          • nav:導(dǎo)航欄
          • section:頁面的組成部分
          • footer:腳注信息
          • aside:側(cè)邊欄信息,比如菜單或者廣告等

          less 多處用到px轉(zhuǎn)換為vw 如何實(shí)現(xiàn)

          sass中可以定義函數(shù),接收參數(shù)并且返回計(jì)算值:

          /*比如:在父元素字體大小為 12px 的容器內(nèi)繪制圖形交互*/
          @function pxToEm ($px) {
          @return ($px/12) + em;
          }

          # Sass
          .box {
          width: pxToEm(36);
          }

          # CSS
          .box {
          width: 3em;
          }
          復(fù)制代碼

          less中函數(shù)是內(nèi)置的不能夠自定義,所以可以使用混入:

          /*
          將寬度為 375px 的 UI 設(shè)計(jì)稿轉(zhuǎn)換成使用單位 vw 來適配移動端的網(wǎng)頁。
          避免編譯:~' 值 '
          */

          .pxToVW (@px, @attr: width) {
          @vw: (@px / 375) * 100;
          @{attr}: ~"@{vw}vw";
          }

          # Less
          .box {
          .pxToVW(75);
          .pxToVW(150, height);
          }

          # CSS
          .box {
          width: 20vw;
          height: 40vw;
          }
          復(fù)制代碼

          less傳送門[5]

          vue-router中router和route的區(qū)別

          router是路由實(shí)例對象,包含一些路由跳轉(zhuǎn)方法,比如push。

          route是路由信息對象,包含和路由相關(guān)的一些信息,比如params,location等。

          vue單頁面應(yīng)用無刷新更新組件怎么實(shí)現(xiàn)的

          我理解面試官詢問的點(diǎn)在于vue-router兩種模式下如何實(shí)現(xiàn)的url到組件的映射。

          hash模式

          hash模式是vue-router的默認(rèn)模式。hash指的是url描點(diǎn),當(dāng)描點(diǎn)發(fā)生變化的時候,瀏覽器只會修改訪問歷史記錄,不會訪問服務(wù)器重新獲取頁面。因此可以監(jiān)聽描點(diǎn)值的變化,根據(jù)描點(diǎn)值渲染指定dom。

          • 改變描點(diǎn)

          可以通過location.hash = "/hashpath"的方式修改瀏覽器的hash值。

          • 監(jiān)聽描點(diǎn)變化

          可以通過監(jiān)聽hashchange事件監(jiān)聽hash值的變化。

          window.addEventListener('hashchange', () => {
             const hash = window.location.hash.substr(1)
             // 根據(jù)hash值渲染不同的dom
          })
          復(fù)制代碼

          history模式

          通過mode選項(xiàng)開啟history模式,history 模式和 hash 模式的區(qū)別在于:

          1. history模式中不帶有“#”,更加美觀
          2. history模式當(dāng)用戶刷新或直接輸入地址時會向服務(wù)器發(fā)送一個請求,所以history模式需要服務(wù)端同學(xué)進(jìn)行支持,將路由都重定向到根路由
          • 改變url

          H5的history對象提供了pushState和replaceState兩個方法,當(dāng)調(diào)用這兩個方法的時候,url會發(fā)生變化,瀏覽器訪問歷史也會發(fā)生變化,但是瀏覽器不會向后臺發(fā)送請求。

          // 第一個參數(shù):data對象,在監(jiān)聽變化的事件中能夠獲取到
          // 第二個參數(shù):title標(biāo)題
          // 第三個參數(shù):跳轉(zhuǎn)地址
          history.pushState({}, "", '/a')
          復(fù)制代碼
          • 監(jiān)聽url變化

          可以通過監(jiān)聽popstate事件監(jiān)聽history變化,也就是點(diǎn)擊瀏覽器的前進(jìn)或者后退功能時觸發(fā)。

          window.addEventListener("popstate", () => {
              const path = window.location.pathname
              // 根據(jù)path不同可渲染不同的dom
          })
          復(fù)制代碼

          從某種程度來說,調(diào)用 pushState() 和 window.location = "#foo"基本上一樣,他們都會在當(dāng)前的 document 中創(chuàng)建和激活一個新的歷史記錄。但是 pushState() 有以下優(yōu)勢:

          • 新的 URL 可以是任何和當(dāng)前 URL 同源的 URL。但是設(shè)置 `window.location`[6] 只會在你只設(shè)置錨的時候才會使當(dāng)前的 URL。
          • 非強(qiáng)制修改 URL。相反,設(shè)置 window.location = "#foo"; 僅僅會在錨的值不是 #foo 情況下創(chuàng)建一條新的歷史記錄。
          • 可以在新的歷史記錄中關(guān)聯(lián)任何數(shù)據(jù)。window.location = "#foo"形式的操作,你只可以將所需數(shù)據(jù)寫入錨的字符串中。

          注意: pushState() 不會造成 `hashchange`[7] 事件調(diào)用,即使新的 URL 和之前的 URL 只是錨的數(shù)據(jù)不同。----MDN

          vue在頁面中如何監(jiān)聽回到上一步的操作

          掛載完成后,判斷瀏覽器是否支持popstate

          mounted(){
            if (window.history && window.history.pushState) {
              history.pushState(nullnulldocument.URL);
              window.addEventListener('popstate'this.goBack, false);
            }
          },
          復(fù)制代碼

          頁面銷毀時,取消監(jiān)聽。否則其他vue路由頁面也會被監(jiān)聽

          destroyed(){
            window.removeEventListener('popstate'this.goBack, false);
          },
          復(fù)制代碼

          頁面跳轉(zhuǎn)函數(shù)

          methods:{
            goBack(){
              this.$router.replace({path'/'});
              //replace替換原路由,作用是避免回退死循環(huán)
            }
          }
          復(fù)制代碼

          代碼題:回文字符串

          function checkStr(str{
              return str === str.split('').reverse().join('')
          }
          復(fù)制代碼

          場景提:一個公告欄,每一天都可以展示,當(dāng)用戶點(diǎn)擊關(guān)閉后今天不顯示,明天(過了今天零點(diǎn))還會顯示

          我給出的方案就是在localStorage中存儲用戶關(guān)閉公告欄的時間戳,等再次進(jìn)入頁面的時候判斷是不是存在localStorage:

          • 若不存在則證明從來沒有關(guān)閉過公告欄,那就顯示;
          • 若存在,就判斷時間戳和當(dāng)前時間是否是同一天,不是同一天就顯示

          代碼題:命名方式中劃線改小駝峰

          方案一:

          function transName(arr{
              let res = arr.map(e => {
                  let items = e.split('-').map((item, index) => {
                      if (index) {
                          let first = item.substring(0,1)
                          let rest = item.substring(1)
                          return first.toUpperCase()+rest
                      }else{
                          return item.toLowerCase()
                      }
                  })
                  return items.join('')
              })
              return res
          }
          console.log(transName(['A-b-cee''ca-de-ea''e-fe-eaa','f-g','mn']))

          復(fù)制代碼

          方案二:

          function turnName(str){
              return str.replace(/-[a-zA-Z]/g,match=>match.replace('-','').toUpperCase())
          }
          復(fù)制代碼

          代碼題:命名方式小駝峰改中劃線

          let s1 = 'aBBcdE';

          let t = s1.replace( /[A-Z]/g, match=>'-'+match.toLowerCase());
          console.log(t);
          復(fù)制代碼

          git commit之后修改上一次commit的信息

          剛commit還沒有push

          git commit --amend

          會進(jìn)入vim編輯器,點(diǎn)擊i,修改commit信息后,點(diǎn)擊esc,輸入ZZ退出。

          git log 可以看見最近c(diǎn)ommit信息

          剛push,修改最近一次commit

          git commit --amend

          會進(jìn)入vim編輯器,點(diǎn)擊i,修改commit信息后,點(diǎn)擊esc,輸入ZZ退出。

          git log 可以看見最近c(diǎn)ommit信息,pull后再push到遠(yuǎn)程(但是每次pull后再push會導(dǎo)致覆蓋原來的更改,后來直接強(qiáng)制推送成功了:git push origin HEAD:master --force)

          修改歷史push的commit信息

          git rebase -i HEAD~3

          表示要修改當(dāng)前版本的倒數(shù)第三次狀態(tài).

          這個命令出來之后,會出來三行東東:

          pick:*******

          pick:*******

          pick:*******
          復(fù)制代碼

          如果你要修改哪個,就把那行的pick改成edit,然后保存退出(點(diǎn)擊esc,輸入ZZ退出)

          這時通過git log你可以發(fā)現(xiàn),git的最后一次提交已經(jīng)變成你選的那個了,這時再使用:

          git commit --amend 來對commit進(jìn)行修改。

          修改完成后使用git rebase --continue

          然后將變化push到遠(yuǎn)程:git push origin HEAD:master --force

          webpack優(yōu)化構(gòu)建速度

          直接參考這篇文章[8]

          前端性能優(yōu)化

          頁面渲染優(yōu)化

          Webkit 渲染引擎流程:

          • 處理 HTML 并構(gòu)建 DOM 樹
          • 處理 CSS 構(gòu)建 CSS 規(guī)則樹(CSSOM)
          • DOM Tree 和 CSSOM Tree 合成一棵渲染樹 Render Tree。
          • 根據(jù)渲染樹來布局,計(jì)算每個節(jié)點(diǎn)的位置
          • 調(diào)用 GPU 繪制,合成圖層,顯示在屏幕上
          1. 避免css阻塞:css影響renderTree的構(gòu)建,會阻塞頁面的渲染,因此應(yīng)該盡早(將 CSS 放在 head 標(biāo)簽里)和盡快(啟用 CDN 實(shí)現(xiàn)靜態(tài)資源加載速度的優(yōu)化)的將css資源加載

          2. 避免js阻塞:js可以修改CSSOM和DOM,因此js會阻塞頁面的解析和渲染,并且會等待css資源的加載。也就是說js會搶走渲染引擎的控制權(quán)。所以我們需要給js資源添加defer或者async,延遲js腳本的執(zhí)行。

          3. 使用字體圖標(biāo) iconfont 代替圖片圖標(biāo):

            • 圖片會增加網(wǎng)絡(luò)請求次數(shù),從而拖慢頁面加載時間
            • iconfont可以很好的縮放并且不會添加額外的請求
          4. 降低css選擇器的復(fù)雜度:瀏覽器讀取選擇器,遵循的原則是從選擇器的右邊到左邊讀取。

            • 減少嵌套:最多不要超過三層,并且后代選擇器的開銷較高,慎重使用
            • 避免使用通配符,對用到的元素進(jìn)行匹配即可
            • 利用繼承,避免重復(fù)匹配和定義
            • 正確使用類選擇器和id選擇器
          5. 減少重繪和回流:

            CSS

            JavaScript

            • 避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。
            • 避免頻繁操作DOM,創(chuàng)建一個documentFragment,在它上面應(yīng)用所有DOM操作,最后再把它添加到文檔中。
            • 為元素設(shè)置display: none,操作結(jié)束后再把它顯示出來。因?yàn)樵赿isplay屬性為none的元素上進(jìn)行的DOM操作不會引發(fā)回流和重繪。用一次回流替代多次回流
            • 避免頻繁讀取會引發(fā)回流/重繪的屬性,如果確實(shí)需要多次使用,就用一個變量緩存起來。
            • 對具有復(fù)雜動畫的元素生成一個新圖層
            • 避免使用table布局。
            • 盡可能在DOM樹的最末端改變class。
            • 避免設(shè)置多層內(nèi)聯(lián)樣式。
            • 將動畫效果應(yīng)用到position屬性為absolute或fixed的元素上。
            • 避免使用CSS表達(dá)式(例如:calc())。

          JS中的性能優(yōu)化

          1. 使用事件委托
          2. 防抖和節(jié)流
          3. 盡量不要使用JS動畫[9],css3動畫[10]canvas動畫[11]都比JS動畫性能好

          圖片的優(yōu)化

          1. 雪碧圖:借助減少http請求次數(shù)來進(jìn)行優(yōu)化
          2. 圖片懶加載:在圖片即將進(jìn)入可視區(qū)域的時候進(jìn)行加載(后邊有判斷即將進(jìn)入可視區(qū)域的方法)
          3. 使用CSS3代替圖片:有很多圖片使用 CSS 效果(漸變、陰影等)就能畫出來,這種情況選擇 CSS3 效果更好

          webpack優(yōu)化

          1. 代碼壓縮:html,css,js文件壓縮
          2. Tree shaking 去除死代碼
          3. babel-plugin-transform-runtime減少ES6轉(zhuǎn)化ES5的冗余
          4. 提升打包速度

          vue

          1. 路由懶加載
          2. 合理使用computed和watch
          3. v-for添加key
          4. v-for的同時避免使用v-if
          5. destory時銷毀事件:比如addEventListener添加的事件、setTimeout、setInterval、bus.$on綁定的監(jiān)聽事件等
          6. 第三方插件按需引入

          react

          1. map循環(huán)展示添加key
          2. 路由懶加載
          3. 使用scu,memo或者pureComponent避免不必要的渲染

          前端的緩存機(jī)制

          分為強(qiáng)緩存和協(xié)商緩存。

          強(qiáng)緩存不需要客戶端向服務(wù)端發(fā)送請求,有兩種響應(yīng)頭實(shí)現(xiàn)方案:

          • Expires:值是一個絕時間,在這個時間前緩存有效,但是如果本地時間被修改,會導(dǎo)致緩存失效
          • Cache-control:值是一個相對時間,單位為秒,資源在這個時間內(nèi)有效

          強(qiáng)緩存過期之后會使用協(xié)商緩存,協(xié)商緩存需要客戶端向服務(wù)端發(fā)送請求,資源未過期則服務(wù)端返回304否則返回新的資源。協(xié)商緩存也有兩種實(shí)現(xiàn)方案:

          • Last-Modified 和 If-Modified-Since:Last-Modified 表示本地文件最后修改日期,If-Modified-Since 會將 Last-Modified 的值發(fā)送給服務(wù)器,詢問服務(wù)器在該日期后資源是否有更新,有更新的話就會將新的資源發(fā)送回來。但是如果本地文件被打開,會導(dǎo)致Last-Modified 被修改。
          • ETag 和 If-None-Match:ETag 類似于文件指紋,If-None-Match 會將當(dāng)前 ETag 發(fā)送給服務(wù)器,詢問該資源 ETag 是否變動,有變動的話就將新的資源發(fā)送回來。并且 ETag 優(yōu)先級比 Last-Modified 高。

          如何判斷圖片即將進(jìn)入可視區(qū)域

          方案1:clientHeight+scroolTop>offsetTop

          <!DOCTYPE html>
          <html lang="en">

          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>圖片加載優(yōu)化</title>
          </head>

          <body>
              <div style="background-color: green;width:100vw;height:8000px">
              </div>
              <div id="yellow" style="background-color: yellow;width:100vw;height:800px">
              </div>

              <script>
                  document.addEventListener('scroll', () => {
                      const clientH = document.documentElement.clientHeight//獲取屏幕可視區(qū)域的高度
                      const scrollT = document.documentElement.scrollTop//獲取瀏覽器窗口頂部與文檔頂部之間的距離,也就是滾動條滾動的距離
                      const offsetTop = document.getElementById('yellow').offsetTop//獲取元素相對于文檔頂部的高度
                      if (clientH + scrollT > offsetTop) {
                          console.log('進(jìn)入可視區(qū)域啦??!')
                      }
                  })
              
          </script>
          </body>

          </html>
          復(fù)制代碼

          方案2:下滑過程中bound.top會越來越小

          <!DOCTYPE html>
          <html lang="en">

          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <title>圖片加載優(yōu)化</title>
          </head>

          <body>
              <div style="background-color: green;width:100vw;height:8000px">
              </div>
              <div id="yellow" style="background-color: yellow;width:100vw;height:800px">
              </div>

              <script>
                  document.addEventListener('scroll', () => {
                      var bound = document.getElementById('yellow').getBoundingClientRect(); ////獲取元素的大小及位置
                      var clientHeight = window.innerHeight;
                      if (bound.top <= clientHeight) {
                          console.log('進(jìn)入可視區(qū)域啦')
                      }
                  })
              
          </script>
          </body>

          </html>
          復(fù)制代碼

          關(guān)于本文

          來自:let_code

          https://juejin.cn/post/7178783712363708475

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
           》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持


          瀏覽 68
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕成人在线观看 | 91麻豆精品国产91久久久熟女 | 欧美人操B视频免费观看 | 欧美操逼高清视频 | 天天综合视频老女人 |