Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 日本福利视频在线观看,国产小视频在线观看,亚洲国产系列久久精品99人人

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          D3.js實戰(zhàn)教程:1 D3.js簡介


          章涵蓋

          • 了解 D3.js 的作用及其背后的理念
          • 認識與 D3 結(jié)合使用來創(chuàng)建數(shù)據(jù)可視化的工具
          • 使用代碼創(chuàng)建可縮放矢量圖形 (SVG) 并為其設(shè)計樣式
          • 了解數(shù)據(jù)可視化最佳實踐如何支持您作為 D3 開發(fā)人員的旅程

          D3.js 是網(wǎng)絡(luò)上幾乎所有最具創(chuàng)新性和令人興奮的信息可視化的幕后黑手。D3 代表數(shù)據(jù)驅(qū)動文檔,它是一個品牌名稱,也是多年來以某種形式提供的一類應(yīng)用程序。我們可以使用這個庫來構(gòu)建各種數(shù)據(jù)驅(qū)動的項目,從簡單的條形圖到動態(tài)地圖,再到復(fù)雜的空間和時間探索。當您希望在數(shù)據(jù)可視化方面獲得完全的創(chuàng)意和技術(shù)自由時,無論您是構(gòu)建用于研究的交互式原型、頂級科技公司廣泛且完全響應(yīng)的數(shù)據(jù)儀表板,還是揭示數(shù)據(jù)故事的長篇文章,D3 都是您的首選工具當用戶滾動時。

          1.1 什么是D3.js

          D3 是一個開源 JavaScript 庫,由 Mike Bostock 于 2011 年創(chuàng)建,用于為 Web 生成動態(tài)和交互式數(shù)據(jù)可視化。盡管過去幾年推出了許多新的數(shù)據(jù)可視化庫,但它們通常在底層使用 D3。這是因為 D3 與 JavaScript 一樣,非常靈活且強大。




          圖 1.1 漢密爾頓中每條線的交互式可視化,這是Shirley Wu創(chuàng)建的 D3 項目


          1.1.1 對可通過網(wǎng)絡(luò)訪問的數(shù)據(jù)可視化的需求

          D3.js 的創(chuàng)建是為了滿足對可通過網(wǎng)絡(luò)訪問的復(fù)雜數(shù)據(jù)可視化的迫切需求。假設(shè)您的公司正在使用商業(yè)智能工具,但它沒有顯示您的團隊所需的數(shù)據(jù)模式。您必須構(gòu)建一個自定義儀表板,根據(jù)您的特定領(lǐng)域量身定制,準確顯示客戶的行為方式。該儀表板需要快速、交互式且可在整個組織內(nèi)共享。D3 將是此類項目的自然選擇。

          或者想象一下,您被雇用來實現(xiàn)一個網(wǎng)頁,該網(wǎng)頁以可視化方式展示 LGBTQ+ 群體(女同性戀、男同性戀、雙性戀、跨性別者、酷兒等)的權(quán)利在過去幾十年和全世界的演變情況。此頁面包含許多隨著用戶滾動而變化的創(chuàng)意可視化效果。它們通過鼠標事件顯示更多信息并適應(yīng)屏幕大小。D3 將是構(gòu)建此類項目的首選工具。

          Mike Bostock 最初創(chuàng)建 D3 是為了利用新興的 Web 標準,正如他所說,“避免了專有表示并提供了非凡的靈活性,暴露了 CSS3、HTML5 和 SVG 等 Web 標準的全部功能”(http: // d3js.org)。D3.js 版本 7 是這個流行庫的最新版本,它通過模塊化 D3 的各個部分來延續(xù)這一趨勢,使其與 ECMAScript 模塊(一種基于 JavaScript 的腳本語言)和現(xiàn)代應(yīng)用程序開發(fā)完全兼容。

          D3.js 使開發(fā)人員不僅能夠制作豐富的交互式應(yīng)用程序,而且能夠制作樣式和服務(wù)類似于傳統(tǒng) Web 內(nèi)容的應(yīng)用程序。這使得它們更可移植,更適合增長,并且更容易由其他團隊成員可能不知道 D3 的具體語法的大型團體維護。

          圖 1.2 D3 開發(fā)人員可以訪問各種數(shù)據(jù)表示形式,地圖就是一個例子。這是由Christophe Viau創(chuàng)建的數(shù)字高程模型 (DEM) 地圖。


          Bostock 決定廣泛處理數(shù)據(jù)并創(chuàng)建一個能夠像圖表一樣簡單、像網(wǎng)絡(luò)一樣簡單、像列表一樣簡單地呈現(xiàn)地圖的庫,這也意味著開發(fā)人員不需要了解以下內(nèi)容的抽象和語法:一個用于地圖的庫,另一個用于動態(tài)文本內(nèi)容的庫,還有另一個用于傳統(tǒng)圖形的庫。相反,用于運行交互式網(wǎng)絡(luò)可視化的代碼接近于純 JavaScript,并且也類似于表示 D3 地圖上的動態(tài)點的代碼。方法是相同的,但數(shù)據(jù)也可以是相同的,以一種方式制定用于網(wǎng)絡(luò)的節(jié)點和鏈路,而以另一種方式制定用于地圖上的地理空間表示。

          D3 不僅可以創(chuàng)建復(fù)雜多樣的圖形,還可以嵌入用戶期望的高水平交互性,這對于現(xiàn)代 Web 開發(fā)至關(guān)重要。使用 D3,每個圖表的每個元素(從旋轉(zhuǎn)的地球儀到餅圖的切片)都以相同的方式進行交互。由于 D3 是由精通數(shù)據(jù)可視化實踐的人編寫的,因此它包含數(shù)據(jù)可視化和 Web 開發(fā)中標準的交互式組件和行為。

          圖 1.3 交互性是 D3 的核心。在此網(wǎng)絡(luò)可視化中,鼠標交互揭示了不同組織之間的關(guān)系以及特定于所選節(jié)點的信息(https://amdufour.github.io/organizations-against-polization)。



          1.1.2 什么時候使用D3.js?

          數(shù)據(jù)可視化領(lǐng)域正在蓬勃發(fā)展,可用于生成數(shù)據(jù)綁定圖形的工具數(shù)量在過去十年中呈爆炸式增長。我們擁有 Excel(數(shù)據(jù)可視化的常用入口)和 Power BI(用于構(gòu)建儀表板的 Microsoft 解決方案)等商業(yè)智能工具。另一方面,更有經(jīng)驗的數(shù)據(jù)科學(xué)家通常會轉(zhuǎn)向 R 的 ggplot2 或 Python 的 matplotlib。

          基于瀏覽器的點擊式工具(例如 Tableau、Flourish、DataWrapper、RAWGraphs 和 Google 圖表)也占據(jù)了主導(dǎo)地位,允許用最少的技術(shù)知識創(chuàng)建令人驚嘆的作品。

          最后,HighCharts、Chart.js 和 D3.js 等 JavaScript 庫專門用于開發(fā)基于 Web 的交互式可視化。

          而且這個列表遠非詳盡無遺......

          那么,D3 在數(shù)據(jù)可視化工具的海洋中處于什么位置呢?我們何時以及如何使用它?我們可以說,雖然 D3 完全可以構(gòu)建此處列出的數(shù)據(jù)可視化庫提供的任何圖表,但它通常不是構(gòu)建簡單的傳統(tǒng)圖表或探索階段(我們調(diào)查哪種類型的可視化是)的首選選項。最適合代表我們的數(shù)據(jù)。構(gòu)建 D3 項目需要時間,而 D3 在復(fù)雜、交互式和定制的項目中真正表現(xiàn)出色。數(shù)據(jù)可視化不僅僅是折線圖和散點圖!雖然上面提到的工具通常專注于預(yù)定義的圖表,但 D3 允許我們將數(shù)據(jù)綁定到任何圖形元素,并通過以獨特的方式組合這些視覺元素來打破常規(guī)。

          圖 1.4 D3 具有 SVG 和畫布繪圖功能,允許開發(fā)人員構(gòu)建自定義可視化效果,例如Elijah Meeks的樂譜表示形式。


          以下是我們?nèi)绾卧跀?shù)據(jù)可視化項目范圍內(nèi)使用 D3 的示例。首先,我們從預(yù)先存在的數(shù)據(jù)集或手動收集的數(shù)據(jù)開始。在開始數(shù)據(jù)分析過程之前,我們通常會花費大量時間清理、格式化和準備數(shù)據(jù)。Python 和 R 等數(shù)據(jù)科學(xué)工具在這方面功能強大,可以幫助我們識別隱藏在數(shù)據(jù)中的故事。Excel 還可以完成簡單的數(shù)據(jù)整理和數(shù)據(jù)分析工作,并且需要較少的技術(shù)背景。我們甚至可以使用 JavaScript 和 D3 進行基本數(shù)據(jù)探索,因為它們提供了我們將在本書后面討論的統(tǒng)計方法。

          一旦數(shù)據(jù)分析開始,通常會創(chuàng)建一些原型來幫助完善我們的故事。Tableau 和 RawGraphs 等工具使我們能夠快速生成此類圖表。這是非常重要的一步,在此階段創(chuàng)建的可視化通常并不花哨或精致。我們不想在原型設(shè)計階段過于執(zhí)著于我們的想法,花費大量時間。我們可能會發(fā)現(xiàn)自己必須“殺死我們的寶貝”并重新開始幾次,直到我們找到最適合我們想要講述的故事的可視化效果。網(wǎng)絡(luò)圖可能是一個例外,直接跳到 D3 對于這些項目通常是有意義的。

          最后,一旦我們知道要創(chuàng)建的可視化類型,就該卷起袖子,對其進行編碼,并使用 D3 對其進行完善。如今,編碼步驟通常發(fā)生在單頁應(yīng)用程序 (SPA) 中,使用 React 或 Svelte 等框架。

          圖 1.5 使用 D3 構(gòu)建的自定義可視化的另一個示例,其中形狀與每首歌曲的不同屬性(例如持續(xù)時間、流派和節(jié)奏)成比例(https://amdufour.github.io/spotify-hits)。



          1.1.3 D3.js 的工作原理

          您可能已經(jīng)嘗試過 D3,并發(fā)現(xiàn)它并不容易上手。也許那是因為您希望它是一個簡單的圖表庫。一個恰當?shù)睦邮莿?chuàng)建條形圖,我們將在第 2 章和第 3 章中進行此操作。D3 沒有一個函數(shù)來創(chuàng)建條形圖。相反,它有一個將<svg>容器附加到文檔對象模型 (DOM) 的函數(shù),以及另一組附加容器的函數(shù)。<rect>每個數(shù)據(jù)點的元素。然后,我們使用比例來計算構(gòu)成直方圖的矩形的長度并設(shè)置它們的屬性。最后,我們調(diào)用另一組函數(shù),將 x 軸和 y 軸添加到條形圖中。如圖 1.6 所示,這個過程比使用 Highcharts 等專用圖表庫要長得多。但 D3 處理數(shù)據(jù)和圖形的明確方式也是它的優(yōu)勢。盡管其他圖表庫允許您方便地制作折線圖和餅圖,但當您想要創(chuàng)建不屬于傳統(tǒng)圖表范圍的可視化效果或?qū)崿F(xiàn)自定義交互時,它們很快就會崩潰。不是D3。D3 允許您構(gòu)建您可以想象的任何數(shù)據(jù)驅(qū)動圖形和交互性。

          圖 1.6 使用 Highcharts 與 D3.js 生成的條形圖。Highcharts 的代碼更簡單、更短,但 D3.js 更通用。



          在圖 1.7 中,您可以看到我們通常如何使用 D3 進行數(shù)據(jù)可視化編碼的地圖。我們從一個數(shù)據(jù)集(通常是 CSV 或 JSON 文件)開始,然后使用 d3-fetch 模塊將此數(shù)據(jù)集加載到我們的項目中。我們通常需要執(zhí)行一些操作來格式化數(shù)據(jù)。例如,我們確保數(shù)字和日期的格式正確。如果我們之前沒有這樣做,我們可能還想詢問我們的數(shù)據(jù)集以找到其主要特征。例如,提前知道其最大值和最小值通常很有幫助。然后我們準備開始構(gòu)建可視化,為此我們將結(jié)合我們將在本書中學(xué)習(xí)的不同 D3 函數(shù)。最后,我們通過監(jiān)聽鼠標事件來添加交互性,允許用戶過濾數(shù)據(jù)或放大可視化。

          圖 1.7 如何使用 D3.js 實現(xiàn)數(shù)據(jù)可視化



          1.2 D3 生態(tài)系統(tǒng) - 入門所需了解的內(nèi)容

          D3.js 從來不會單獨使用,而是我們結(jié)合起來創(chuàng)建豐富的 Web 界面的技術(shù)和工具生態(tài)系統(tǒng)的一部分。與任何網(wǎng)頁一樣,D3 項目是在 DOM(文檔對象模型)內(nèi)構(gòu)建的,并利用 HTML5 的強大功能。盡管 D3 可以創(chuàng)建和操作傳統(tǒng)的 HTML 元素,例如分區(qū) ( <div>) 和列表 ( <ul>, <ol>),但我們主要使用 SVG 圖形或在畫布(從腳本渲染位圖圖像的 HTML 元素)內(nèi)生成可視化效果。然后,我們還可以使用舊的 CSS 樣式表,它可以增強 D3 項目并使其設(shè)計更易于維護,尤其是在廣泛的團隊中。

          鑒于 D3 是一個 JavaScript 庫,我們自然傾向于將 D3 方法與本機 JavaScript 函數(shù)結(jié)合起來來訪問和操作數(shù)據(jù)。D3 現(xiàn)在完全支持 JavaScript 的 ECMAScript 2015 或 ES6 修訂版以及大多數(shù)最新更新。D3 還作為模塊提供,可以集成到我們構(gòu)建 Web 項目所用的最新框架和庫中。使用這些模塊通常是首選方法,因為它不會污染我們應(yīng)用程序的全局范圍。

          在本節(jié)中,我們將簡要討論這些技術(shù)及其在 D3 生態(tài)系統(tǒng)中的作用。由于 SVG 知識是理解 D3 的基礎(chǔ),因此我們將花時間更詳細地解釋您開始構(gòu)建可視化所需理解的基礎(chǔ)知識。如果您已經(jīng)熟悉 HTML、SVG 元素、CSS、JavaScript 和 JavaScript 模塊,請隨意瀏覽或跳至第 1.3 節(jié)。

          1.2.1 HTML 和 DOM

          與 GIF 動畫和框架成為網(wǎng)絡(luò)動態(tài)內(nèi)容頂峰的時代相比,我們已經(jīng)走過了很長一段路。在圖 1.8 中,您可以看到為什么 GIF 從未在強大的基于 Web 的數(shù)據(jù)可視化中流行起來。GIF 與設(shè)計用于使用 VML(矢量標記語言)的 infoviz 庫一樣,對于早期瀏覽器來說是必需的,但 D3 是為不再需要向后兼容性的現(xiàn)代瀏覽器而設(shè)計的。

          圖 1.8 20 世紀 90 年代的一些例子,比如dpgraph.com,仍然存在,讓我們想起動畫 GIF 無處不在的時代。



          當您登陸網(wǎng)頁時,要加載的第一個文件是超文本標記語言或 HTML 文件,如下例所示。瀏覽器解析 HTML 文件以構(gòu)建文檔對象模型或 DOM,這是用于 Web 文檔的編程接口。我們經(jīng)常將其稱為 DOM 樹,因為它由一組嵌套元素(也稱為節(jié)點或標簽)組成。在我們的示例中,<head>和 the<body>元素是<html>父元素的子元素。同樣,標簽是、the和標簽<body>的父標簽。標題也是該元素的同級元素。當您加載網(wǎng)頁時,您在屏幕上看到的是標記中包含的元素。

          <!DOCTYPE#nbsp;html>
          <html>
            <head>
              <meta charset="UTF-8">  
              <title>A simple HTML file | D3.js in Action</title>
            </head>
            <body>
              <h1>I am a title</h1>
              <div>
                <p>I am a paragraph.</p>
                <p>I am another paragraph.</p>
              </div>
            </body>
          </html>

          在 DOM 中,每個元素的三類信息定義了其行為和外觀:樣式、屬性和特性。樣式?jīng)Q定顏色、大小、邊框、不透明度等。屬性包括類、id 和交互行為,盡管某些屬性也可以確定外觀,具體取決于您正在處理的元素類型。對于 SVG 元素,屬性用于設(shè)置不同形狀的位置、大小和比例。屬性通常指的是狀態(tài),例如復(fù)選框的“checked”屬性,如果該框被選中,則該屬性為 true;如果該框未被選中,則該屬性為 false。盡管術(shù)語“屬性”和“屬性”經(jīng)常互換使用,但它們是兩個不同的東西。呈現(xiàn) DOM 時,屬性顯示為初始狀態(tài)。屬性是元素的當前狀態(tài),并且可以隨著用戶與界面交互而改變。在第2章中,我們將討論用于生成或修改HTML和SVG元素的樣式和屬性的D3方法。

          DOM 還決定元素在屏幕上的繪制順序,子元素在父元素之后和內(nèi)部繪制。盡管 CSS 屬性z-index使我們能夠部分控制傳統(tǒng) HTML 元素繪制到屏幕上的順序,但 SVG 元素嚴格遵循它們在 DOM 中出現(xiàn)的順序。根據(jù)畫家的模型,之后繪制的內(nèi)容出現(xiàn)在之前繪制的內(nèi)容之上。

          1.2.2 SVG——可縮放矢量圖形

          可擴展矢量圖形 (SVG) 的引入確實改變了網(wǎng)絡(luò)的面貌。幾年之內(nèi),SVG 圖形成為主要的 Web 開發(fā)工具。光柵圖形(PNG 和 JPG)由微小的像素組成,當我們放大得太近時,這些像素就會變得可見,而矢量圖形則是通過數(shù)學(xué)和幾何圖形構(gòu)建的。它們在任何尺寸和任何屏幕分辨率下都能保持清晰的外觀。SVG 圖形的另一個顯著優(yōu)勢是它們可以直接注入 DOM,允許開發(fā)人員操縱其元素并為其設(shè)置動畫,并使屏幕閱讀器可以訪問它們。如果構(gòu)建正確,SVG 也具有高性能,其文件大小僅為等效光柵圖像的一小部分。

          當使用 D3 創(chuàng)建數(shù)據(jù)可視化時,我們通常將 SVG 形狀注入 DOM 并修改其屬性以生成組成可視化的視覺元素。了解 SVG 的工作原理、主要 SVG 形狀及其表示屬性對于大多數(shù) D3 項目至關(guān)重要。

          如何訪問代碼文件

          本書的每一章都包含旨在支持您的學(xué)習(xí)體驗的代碼練習(xí)。我們強烈建議您“做”這本書,而不僅僅是“讀”這本書,這意味著在閱讀章節(jié)時完成練習(xí)。通過這種方式,您將保留更多信息,并很快就能構(gòu)建自己的 D3 項目!

          對于每個練習(xí)和項目,您都可以訪問現(xiàn)成的代碼文件。您可以在本書的 Github 存儲庫(https://github.com/d3js-in-action-third-edition/code-files)上找到它們。如果您熟悉 Git,則可以將存儲庫克隆到您的計算機上。您還可以下載壓縮文件。

          從 Github 存儲庫下載代碼文件


          每一章都有自己的文件夾,其中包含一個或多個練習(xí),按照每章中的部分編號。練習(xí)包括一個start文件夾,其中包含入門所需的所有文件。您將在文件夾中找到練習(xí)的完整解決方案end。當您完成一章的各個部分時,您可以繼續(xù)在上一部分使用的文件中進行編碼,或者使用專用于該部分的文件夾重新開始。兩種選擇都會導(dǎo)致相同的結(jié)果。

          讓我們開始探索矢量圖形。轉(zhuǎn)到本書提供的代碼文件。找到end中的文件夾chapter_01/SVG_Shapes_Gallery并右鍵單擊該文件index.html。在菜單中,轉(zhuǎn)到打開方式并選擇瀏覽器。我們建議使用 Chrome 或 Firefox,因為它們具有出色的檢查器工具。該文件將在新的瀏覽器選項卡中打開,并且將出現(xiàn)您在圖 1.9 中看到的矢量圖形。您還可以在 Github 托管項目 ( https://d3js-in-action-third-edition.github.io/svg-shapes-gallery ) 上查看這些 SVG 形狀。

          圖 1.9 我們將在本節(jié)中構(gòu)建的基本 SVG 形狀圖庫。


          您正在查看的 SVG 圖形包含創(chuàng)建 D3 可視化時最常使用的形狀:線條、矩形、圓形、橢圓形、路徑和文本。

          使用 D3 時,您通常會告訴庫應(yīng)將哪些形狀附加到 DOM。您還負責(zé)了解需要計算哪些表示屬性才能使形狀具有您正在尋找的尺寸、顏色和位置。在下面的練習(xí)中,您將編寫創(chuàng)建圖 1.9 中每個 SVG 元素的代碼。我們將此練習(xí)稱為SVG 形狀圖庫。之后,您將了解入門所需的所有 SVG 基礎(chǔ)知識。

          在您選擇的代碼編輯器中打開練習(xí)文件夾index.html中的文件。我們推薦VS Code,這是一個免費、易于使用的代碼編輯器,并且具有多種功能,對前端開發(fā)很有幫助。startSVG_Shapes_Gallery

          正如您所看到的,index.html是一個簡單的 HTML 文件。如果您在瀏覽器中打開此文件(右鍵單擊該文件并在“打開方式”菜單中選擇瀏覽器),您將只會看到一個空白頁面。這是因為該<body>元素為空。在接下來的小節(jié)中,我們將向此<body>元素添加 SVG 形狀。

          清單 1.1.a SVG 形狀庫練習(xí)的起始 HTML 文件

          <!DOCTYPE html>
          <html>
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">  
            <title>SVG Shapes Gallery | D3.js in Action</title>
          </head>
          <body>
            
          </body>
          </html>

          哪里可以找到更多信息

          以下部分將介紹多個 SVG 元素及其屬性。作為開發(fā)人員,我們在構(gòu)建項目、使用我們不熟悉的 SVG 元素或?qū)ふ?JavaScript 函數(shù)來執(zhí)行特定操作時嚴重依賴在線資源。在前端開發(fā)中,MDN Web Docs ( https://developer.mozilla.org/ ) 始終是可靠且全面的資源。它包含 HTML 元素及其屬性、CSS 屬性和 JavaScript 函數(shù)的易于理解且通常可編輯的示例。

          響應(yīng)式 svg 容器

          在 SVG 圖形的世界中,<svg></svg>容器是在其上繪制所有內(nèi)容的白板。每個 SVG 形狀都嵌套在<svg>父級中。要查看其實際效果,請在元素index.html內(nèi)編輯并添加 SVG 容器<body>。在瀏覽器中重新加載頁面。目前還看不到任何東西。

          <body>
            <svg></svg>
          </body>

          打開瀏覽器的檢查器工具(在瀏覽器窗口中右鍵單擊并選擇“檢查”)。在檢查器窗口中,您將看到組成頁面的 DOM。找到<svg></svg>容器,也稱為 SVG 節(jié)點。當您在檢查器中將鼠標移到它上面時,SVG 元素會在頁面上突出顯示。您可以在圖 1.5 中看到此效果。

          圖 1.10 在 DOM 樹中選擇并在視口中突出顯示的 SVG 節(jié)點


          默認情況下,瀏覽器為 SVG 容器提供寬度300px和高度。150px但我們也可以使用屬性來分配這些值。屬性用于提供有關(guān) HTML 元素的附加信息。對于內(nèi)聯(lián) SVG,我們主要使用屬性來設(shè)置組成 SVG 圖形的元素和形狀的大小和位置。

          例如,我們可以設(shè)置SVG 容器的寬度和高度屬性。返回到文本編輯器,并將 awidth和 aheight屬性添加到 SVG 容器。將它們的值設(shè)置為900和300并保存文件。

          <svg width="900" height="300"></svg>

          在瀏覽器中重新加載項目并在檢查工具中找到 SVG 節(jié)點。請注意,寬度和高度屬性現(xiàn)在顯示在 SVG 容器的括號內(nèi)。如果將鼠標移到檢查工具 DOM 樹中的 SVG 節(jié)點上,您還會看到視口中的 SVG 容器現(xiàn)在的大小為 900 像素 x 300 像素。

          圖1.11 SVG節(jié)點采用其屬性指定的大小


          為了幫助我們查看 SVG 容器,而不必從檢查器中突出顯示它,讓我們給它一個邊框。向 SVG 容器添加樣式屬性并插入 CSS 邊框?qū)傩浴T谙乱粋€代碼片段中,我們使用 border 速記屬性創(chuàng)建一個寬度為 1px 的黑色實心邊框。

          <svg width="900" height="300" style="border:1px solid black;"></svg>

          保存文件,重新加載頁面并確認 SVG 容器周圍有邊框。現(xiàn)在,調(diào)整瀏覽器窗口的大小,直到它小于 SVG 容器。您將觀察到 SVG 容器保持固定的寬度和高度,并且不適應(yīng)瀏覽器窗口的大小。讓我們嘗試使 SVG 容器具有響應(yīng)能力。

          之前,我們將 SVG 屬性設(shè)置為絕對值 (900和300),瀏覽器將它們解釋為以像素為單位的測量值 (900px和300px)。但我們也可以使用百分比。在文本編輯器中,將寬度屬性更改為相對值“ 100%”,保存文件并重新加載頁面。

          <svg width="100%" height="300" style="border:1px solid black;"></svg>

          再次調(diào)整瀏覽器大小,并注意 SVG 如何獲取可用的完整寬度并保持 300 像素的固定高度。這更好,但我們失去了原來的縱橫比。

          為了使內(nèi)聯(lián) SVG 具有響應(yīng)能力,我們可以使用viewBox 屬性。在代碼編輯器中,從 SVG 容器中刪除width和屬性,并將它們替換為屬性。給它一個值。heightviewBox"0 0 900 300"

          <svg viewBox="0 0 900 300" style="border:1px solid black;"></svg>

          再次調(diào)整瀏覽器窗口的大小。你注意到了什么?SVG 容器現(xiàn)在可以適應(yīng)任何屏幕尺寸,同時保持其縱橫比為 900:300。我們有一個響應(yīng)式 SVG!

          正如您所注意到的,viewBox 屬性由四個值的列表組成。前兩個數(shù)字指定 viewBox 坐標系的原點(x 和 y)。在本書中,我們將始終使用0 0,但很高興知道這些值可用于更改 SVG 容器的哪一部分在屏幕上可見。viewBox 屬性的最后兩個數(shù)字是其寬度和高度。它們定義 SVG 的縱橫比,并確保其完美縮放以適合任何容器而不變形。

          安裝在容器內(nèi)是這里的關(guān)鍵。到目前為止,我們的內(nèi)聯(lián) SVG 的容器是 HTML<body>元素,它通常會擴展以適應(yīng)瀏覽器的視口。如果視口變得非常大,SVG 也會變得非常大。通常,我們希望 SVG 具有最大寬度,以便它不會大于頁面上的其余內(nèi)容。為此,請將 SVG 容器包裝在寬度為 100%、最大寬度為 1200px 的 div 內(nèi)。為簡單起見,我們將這些屬性設(shè)置為內(nèi)聯(lián)樣式,但在實際項目中,這些屬性將來自 CSS 文件。請注意,我們還添加了值邊距“ 0 auto”,以使 SVG 在頁面上水平居中。

          <div style="width:100%; max-width:1200px; margin:0 auto;">
            <svg viewBox="0 0 900 300" style="border:1px solid black;"> ... </svg>
          </div>

          嘗試再次調(diào)整瀏覽器的大小,看看我們的 SVG 如何優(yōu)雅地適應(yīng)任何屏幕尺寸,同時尊重其容器的最大寬度。該策略有助于將 D3 可視化注入響應(yīng)式網(wǎng)頁,我們將在本書中使用它。

          svg坐標系

          既然我們知道了如何使內(nèi)聯(lián) SVG 具有響應(yīng)性,那么解決 SVG 形狀在 SVG 容器內(nèi)的定位方式就很重要了。SVG 容器就像一張白紙,我們可以在上面繪制矢量形狀。矢量形狀是根據(jù)基本幾何原理定義的,并參考 SVG 容器的坐標系進行定位。

          SVG 坐標系與笛卡爾坐標系類似。其 2D 平面使用兩個垂直軸來確定元素的位置,稱為 x 和 y。這兩個軸源自SVG 容器的左上角,如圖 1.12 所示。意思是y軸的正方向是從上到下。記住這一點可以讓你避免一些頭痛!

          圖1.12 SVG容器的坐標系和元素的位置


          為了在 SVG 容器內(nèi)定位元素,我們從左上角的原點開始向右移動。這將為我們提供元素的水平 (x) 位置。對于垂直 (y) 位置,我們從頂部開始向下移動。這些位置由每個 SVG 形狀的表示屬性定義。

          現(xiàn)在,我們將了解您在構(gòu)建 D3 項目時經(jīng)常遇到的 SVG 形狀。我們還將討論它們的主要表現(xiàn)屬性。這里的目標絕不是編寫 SVG 提供的所有形狀和功能的綜合指南,而是涵蓋支持您的 D3 之旅的基礎(chǔ)知識。

          數(shù)據(jù)可視化技巧:幾何基元

          出色的藝術(shù)家可以用矢量圖形繪制任何東西,但您可能不會因為您是一名藝術(shù)家而關(guān)注 D3。相反,您正在處理圖形并考慮更務(wù)實的目標。從這個角度來看,理解幾何基元(也稱為圖形基元)的概念至關(guān)重要。幾何基元是簡單的形狀,例如點、線、圓和矩形。這些形狀可以組合成更復(fù)雜的圖形,特別方便直觀地顯示信息。

          基元對于理解您在現(xiàn)實世界中看到的復(fù)雜信息可視化也很有用。樹形布局,就像我們將在第 10 章中構(gòu)建的那樣,當您意識到它們只是圓形和直線時,它們就不那么令人生畏了。當您將交互式時間線視為矩形和點的集合時,它們更容易理解和創(chuàng)建。即使是主要以多邊形、點和線形式出現(xiàn)的地理數(shù)據(jù),當您將其分解為最基本的圖形結(jié)構(gòu)時,也不會那么混亂。

          線條元素可能是所有 SVG 形狀中最簡單的。它獲取兩個點的位置,設(shè)置為屬性,并在它們之間繪制一條直線。返回到該index.html文件,并在 SVG 容器內(nèi)添加一個<line />元素。聲明其屬性x1和y1并分別賦予它們值 50 和 45。這意味著我們的線的起點位于(50, 45)SVG 容器的坐標系中。如果從 SVG 容器的左上角開始,向右移動 50 像素,向下移動 45 像素,您將遇到線條的起點。(140, 225)同樣,使用屬性x2和y2將線的端點設(shè)置為。

          <svg>
            <line x1="50" y1="45" x2="140" y2="225" />
          </svg>

          圖1.13 在SVG容器的坐標系中定位線元素


          如果您保存并重新加載項目,您的線條將不可見,您可能想知道發(fā)生了什么。為了使 SVG 線條在屏幕上可見,我們還需要設(shè)置其描邊屬性,該屬性控制線條的顏色。border 屬性的值與 CSS color 屬性類似。它可以是顏色名稱 ( black, blue, ...)、RGB 顏色 ( rgb(255,0,0)) 或十六進制值 ( #808080)。向您的線條添加筆劃屬性,并為其指定您選擇的顏色(我們使用黑色)。現(xiàn)在它應(yīng)該在屏幕上可見。

          <line x1="50" y1="45" x2="140" y2="225" stroke="black" />

          如果我們想設(shè)置線條的寬度,我們可以使用描邊寬度屬性。此屬性接受絕對數(shù)字(轉(zhuǎn)換為像素)或相對值 (%)。例如,以下行的 a 為stroke-width3px。如果stroke-width未聲明該屬性,瀏覽器將應(yīng)用默認值 1px。

          <line x1="50" y1="45" x2="140" y2="225" stroke="black" stroke-width="3" />

          打開瀏覽器的檢查器工具并找到 SVG 節(jié)點及其包含的行。雙擊其中一個屬性,更改其值并觀察新值如何修改線的起點或終點。花時間嘗試不同的值,以確認您了解屬性x1、y1、x2和如何y2影響線條的位置和長度。

          -20現(xiàn)在,為屬性賦予 值x1。你看到線的起點是如何消失的嗎?落在 SVG viewBox 之外的任何形狀或形狀部分在屏幕上都不可見。不過,該元素仍然存在于 DOM 中。我們可以訪問和操縱它。如果 SVG 中的某個元素不可見,并且您不知道為什么首先要檢查它是否在 SVG viewBox 之外!請記住,您始終可以通過使用開發(fā)人員工具檢查 DOM 來找到它。正如我們之前所做的那樣,如果將鼠標移到檢查器工具中的元素上,即使它位于 SVG viewBox 之外,它也會在視口中突出顯示。

          圖 1.14 SVG 線在 SVG 容器外部時部分隱藏



          筆記

          為了提高效率,大多數(shù) SVG 元素只需要一個自閉合標簽(我們使用 <line /> 而不是 <line></line>)。與其他一些 HTML 標簽一樣,SVG 元素的固有結(jié)構(gòu)在自閉合標簽中提供了所有必需的信息。這對于 SVG 文本元素有所不同,其中文本放置在開始標簽和結(jié)束標簽之間。

          長方形

          顧名思義,矩形元素<rect />在屏幕上繪制一個矩形形狀。該<rect />元素需要四個屬性才能可見。屬性x和y聲明矩形左上角的位置,而屬性width和height分別控制其寬度和高度。<rect />在 SVG 容器中添加以下元素及其屬性。

          <rect x="260" y="25" width="120" height="60" />

          在我們的示例中,矩形的左上角位于SVG 容器原點的260px右側(cè)和下方。25px它的寬度為120px,高度為60px。與其他位置屬性一樣,我們可以使用百分比而不是絕對數(shù)字來設(shè)置它們的值。例如,如果我們將該width屬性設(shè)置為50%,則矩形將擴展到 SVG 容器寬度的一半。

          圖 1.15 在 SVG 容器的坐標系中定位矩形并調(diào)整其大小


          您可能已經(jīng)注意到我們的矩形充滿了黑色。默認情況下,瀏覽器對大多數(shù) SVG 形狀應(yīng)用黑色填充。我們可以通過設(shè)置fill屬性并為其指定任何 CSS 顏色來更改該顏色。如果我們想給矩形添加邊框,我們添加一個描邊屬性。圖 1.16 顯示了一些示例。請注意,如果不聲明屬性,則矩形周圍不會繪制邊框stroke。另外,在最后一個矩形中,屬性fill-opacity和border-opacity用于使fill和stroke半透明。與 CSS 中一樣,不透明度可以設(shè)置為絕對值 ( 0.3) 或百分比 (30%)。與填充和描邊相關(guān)的所有屬性也可以從 CSS 文件設(shè)置或修改。

          圖 1.16 應(yīng)用于矩形 SVG 形狀的不同樣式屬性


          如果您希望矩形具有圓角,則只需添加rxry屬性,分別是水平和垂直角半徑。這些屬性接受絕對值(以像素為單位)和相對值(百分比)。例如,下面矩形的每個角的半徑都是 20px。將此矩形添加到您的形狀庫中。

          <rect x="260" y="100" width="120" height="60" rx="20" ry="20" />

          此時,您可能想知道 SVG 中是否有一個可以繪制正方形的元素。我們不需要一個!在 SVG 中,我們<rect />通過賦予元素相等width和height屬性來繪制帶有元素的正方形。例如,以下<rect />元素將繪制一個 60px x 60px 的正方形。也將它添加到您的形狀庫中。

          <rect x="260" y="175" width="60" height="60" />

          作為參考,我們的形狀庫中現(xiàn)在有三種類型的 SVG 矩形:經(jīng)典矩形、圓角矩形和正方形。為了好玩,我們給了它們顏色#6ba5d7并玩弄它們stroke和fill屬性。請注意,只有筆劃在正方形上可見,因為其fill屬性值為transparent或none。您的矩形應(yīng)該類似于圖 1.17 中的矩形,除非您更改了它們的屬性(我們鼓勵您這樣做)!

          <rect x="260" y="25" width="120" height="60" fill="#6ba5d7" />
          <rect x="260" y="100" width="120" height="60" rx="20" ry="20"
          ?  fill="#6ba5d7" />
          <rect x="260" y="175" width="60" height="60" fill="transparent"
          ?  stroke="#6ba5d7" />

          圖1.17 三種SVG矩形


          SVG筆畫的位置

          當您嘗試在可視化中對齊形狀時需要記住的一點是,筆劃是均勻地繪制在 SVG 形狀的內(nèi)部和外部邊界上的。如下圖所示,如果矩形的width屬性為 40px,則應(yīng)用 ofstroke-width會1在視覺上向矩形的左側(cè)添加 0.5px,向右側(cè)添加 0.5px(而不是像我們本能地認為的那樣,向每邊添加 1px) ),實際總寬度為 41px。如果stroke-width是2,它會在每邊添加 1px,依此類推。

          筆劃寬度對 SVG 形狀實際寬度的影響


          圓和橢圓

          圓形形狀經(jīng)常用于數(shù)據(jù)可視化。它們自然地吸引眼球,并使可視化感覺更加友好和有趣。我們使用<circle />元素繪制 SVG 圓圈。其所需屬性是圓心的位置 ( cx , cy ) 及其半徑 ( r )。圓的半徑是從圓心到其邊界上任意點所繪制的直線的長度。將以下圓圈添加到您的形狀庫中。將其中心定位于(530, 80)并為其指定 50px 的半徑。

          <circle cx="530" cy="80" r="50" />

          圖 1.18 在 SVG 容器的坐標系中定位圓和橢圓并調(diào)整其大小


          您還可以使用圓形的填充和描邊屬性。為了生成圖 1.18 中的效果,我們使用了透明填充和 3px 的描邊,顏色為#81c21c。

          類似地,<ellipse />元素需要形狀中心位置的屬性 ( cx, cy)。圓形具有恒定的半徑,而橢圓形的半徑則不同,從而使其具有扁平形狀。我們通過聲明水平半徑 ( rx ) 和垂直半徑 ( ry ) 來創(chuàng)建這種扁平化效果。將下一個片段添加到您的圖庫中。它將在圓下方繪制一個橢圓,水平半徑為 50px,垂直半徑為 30px。

          <ellipse cx="530" cy="205" rx="50" ry="30" />

          路徑

          SVG路徑是迄今為止所有 SVG 元素中最靈活的。它們在 D3 中廣泛用于繪制幾乎所有無法用迄今為止討論的形狀基元之一(直線、矩形、圓形和橢圓形)表示的復(fù)雜形狀和曲線。

          d我們通過聲明其屬性(代表“draw”)來指示瀏覽器如何繪制路徑。該d屬性包含一個命令列表,從開始繪制路徑的位置到要使用的曲線類型,直到指定我們是否希望路徑成為閉合形狀。例如,將以下路徑元素添加到您的庫中。在此示例中,d屬性以M680 150開頭,表示“移動到坐標(680, 150)”。然后我們從當前點 (680, 150) 到字母 C 后面的第三個坐標 (755 150) 指定的端點繪制一條三次貝塞爾曲線。三次貝塞爾曲線需要控制點,即字母 C 后面、起點和終點之間的坐標((710, 80) 和 (725, 80))。這些控制點定義了曲線的陡峭程度。然后我們有字母 S,它代表“停止”。它的工作原理與字母 C 類似,只不過它通向曲線的端點。這里最后一條曲線的起點是(755 150),終點是(840, 150),控制點是(810, 220)。曲線可以由一個或兩個控制點定義。

          <path d="M680 150 C 710 80, 725 80, 755 150 S 810 220, 840 150" fill="none" 
          ?  stroke="#773b9a" stroke-width="3" />

          圖 1.19 一個簡單的 SVG 路徑及其控制點


          要深入了解 SVG 路徑,請參閱 MDN 的教程:https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths。

          手動編寫d屬性對于簡單的形狀是可行的,但隨著形狀變得復(fù)雜而變得乏味。幸運的是,D3 具有強大的形狀生成器,我們將在第 4 章中討論。

          關(guān)于路徑要記住的另一件重要的事情是瀏覽器將以黑色填充它們,除非我們將它們的fill屬性設(shè)置為noneor transparent。即使路徑未閉合(如我們的示例中所示),情況也是如此。

          文本

          <div>內(nèi)聯(lián) SVG 圖形的最大優(yōu)點之一是它們可以包含可導(dǎo)航的文本,就像插入一個或一個元素中的任何其他 HTML 文本一樣<p>。這對于可訪問性來說是一個很大的優(yōu)勢。

          由于數(shù)據(jù)可視化通常包含多個標簽,因此有必要了解如何使用<text></text>元素操作 SVG 文本。讓我們向形狀庫添加標簽,以了解 SVG 文本的基本原理。

          到目前為止討論的 SVG 形狀使用自閉合標簽 ( <line />, <rect />, <path />, ...)。使用 SVGtext元素時,我們需要使用開始標簽和結(jié)束標簽。我們將要顯示的文本放置在這兩個標簽之間。例如,讓我們在 SVG 中添加一個表示“l(fā)ine”的文本元素。

          <text>line</text>

          保存文件并重新加載頁面。您可能希望文本出現(xiàn)在 SVG 容器的左上角,但實際上卻看不到......這是為什么?默認情況下,SVG 文本的位置是參考其基線計算的,由屬性控制dominant-baseline。如果文本基線的坐標是(0, 0),您可以在圖 1.20 中看到實際文本如何最終出現(xiàn)在 SVG 容器之外。由于位于 SVG 容器外部的任何元素都是不可見的,因此我們看不到文本。

          圖 1.20 位于 SVG 容器外部的文本



          使用 SVG 文本時要考慮的另一點是文本的流動方式。常規(guī) HTML 元素按照控制內(nèi)容流的特定規(guī)則放置在頁面上。如果您將一堆<div></div>元素插入頁面中,它們會自然地堆疊在一起,并且它們的內(nèi)容將重排,以便它永遠不會超出其容器。SVG 文本根本不流動,每個 SVG 元素必須單獨定位。一種方法是設(shè)置它們的x和y屬性。如果我們使用這些屬性將文本放置在 處(60, 260),標簽“l(fā)ine”將出現(xiàn)在形狀庫中 SVG 線的下方。

          <text x="60" y="260">line</text>

          為了練習(xí),創(chuàng)建一個新的文本元素,將標簽“矩形”放置在矩形和正方形下方。

          到目前為止,我們已經(jīng)使用x和y屬性來聲明文本元素的左下角。但是如果我們想設(shè)置文本中點的位置怎么辦?我們可以通過使用屬性text-anchor并為其指定值來做到這一點middle。例如,我們可以使用此屬性將圓形的文本標簽居中。

          <text x="530" y="155" text-anchor="middle">circle</text>

          圖1.21 text-anchor屬性影響SVG文本的對齊方式。它的默認值是“開始”。為了根據(jù)中間對齊文本元素,我們應(yīng)用“middle”的 text-andchor 屬性。類似地,為了根據(jù)文本的結(jié)尾對齊文本,我們應(yīng)用“end”的 text-andchor 屬性。


          最后為橢圓添加一個標簽,為路徑元素添加另一個標簽。默認情況下,SVG 文本為黑色。您可以使用屬性更改其顏色fill。

          分組元素

          我們將在本節(jié)中討論的最后一個 SVG 元素是組元素。group 或<g></g>元素與我們迄今為止討論的 SVG 元素不同,因為它沒有圖形表示,也不作為有界空間存在。相反,它是元素的邏輯分組。在創(chuàng)建由多個形狀和文本元素組成的可視化效果時,您需要廣泛使用組。

          如果我們希望正方形和“rect”標簽一起顯示并在 SVG 容器中作為一個整體移動,我們可以將它們放置在一個<g>元素內(nèi),如下例所示。請注意元素的左上角如何<rect>更改為(0, 0)。位于<text>處以(0, 85)保持其低于<rect>。

          <g>
            <rect x="0" y="0" width="60" height="60" />
            <text x="0" y="85">rect</text>
          </g>

          包含正方形及其標簽的組現(xiàn)在顯示在 SVG 容器的左上角。我們可以將這個組及其包含的所有元素移動到 SVG 容器中任何我們想要的位置,同時保持正方形與其標簽之間的對齊。

          在 SVG 容器中移動組是通過轉(zhuǎn)換屬性完成的。變換屬性比目前討論的屬性有點嚇人,但與 CSS 變換屬性相同。它采用一個變換(平移、旋轉(zhuǎn)、縮放等)或一堆變換作為值。為了移動一個組,我們使用translate(x, y)變換。如果我們想要將<rect>和<text>元素移回其原始位置,我們需要對元素應(yīng)用向右 260 像素和向下 175 像素的平移。<g>為此,我們將其 Transform 屬性設(shè)置為transform="translate(260,175)"。

          <g transform="translate(260,175)">
            <rect x="0" y="0" width="60" height="60" />
            <text x="0" y="85">rect</text>
          </g>

          <g> 元素的另一個有用的方面是它的子元素繼承它的屬性。為了說明這一點,讓我們將<g>元素中所有剩余的文本元素分組,除了標簽“矩形”,我們已經(jīng)將其與正方形分組。

          <g>
            <text x="60" y="260">line</text>
            <text x="530" y="155" style="text-anchor:middle">circle</text>
            <text x="530" y="260" style="text-anchor:middle">ellipse</text>
            <text x="730" y="260">path</text>
          </g>

          #636466如果我們對組應(yīng)用填充屬性,<text>則該組內(nèi)的每個元素將繼承相同的顏色。同樣,如果我們向組添加樣式屬性,例如使用font-family和font-size屬性,則組內(nèi)的文本將繼承這些屬性。

          <g fill="#636466" style="font-size:16px; font-family:monospace">
            <text x="60" y="260">line</text>
            <text x="530" y="155" style="text-anchor:middle">circle</text>
            <text x="530" y="260" style="text-anchor:middle">ellipse</text>
            <text x="730" y="260">path</text>
          </g>

          最后重新加載頁面并觀察組內(nèi)的標簽如何繼承組的顏色和字體,而保留在該組之外的標簽則保持其原始外觀。這種將共享屬性應(yīng)用于組元素的技術(shù)非常方便,可以幫助您將 DRY(不要重復(fù)自己)編碼原則應(yīng)用到您的工作中。當您需要更新這些屬性時,它也會讓您的生活更輕松。

          恭喜您完成了本書的第一個練習(xí)!您可以在清單 1.1.b 和編碼文件的末尾文件夾中找到形狀庫的完整代碼。當您構(gòu)建第一個 D3 項目時,請使用此練習(xí)作為參考。

          清單 1.1.b 用于 SVG 形狀圖庫練習(xí)的完整 HTML 文件

          <!DOCTYPE html>
          <html>
          <head> [...] </head>
          <body>
            <div style="width:100%; max-width:1200px; margin:0 auto;">
              <svg viewBox="0 0 900 300" style="border:1px solid black;">
           
                <line x1="50" y1="45" x2="140" y2="225" stroke="black" />
           
                <rect x="260" y="25" width="120" height="60" fill="#6ba5d7" />
                <rect x="260" y="100" width="120" height="60" rx="20" ry="20"  
                ?  fill="#6ba5d7" /> 
                <g transform="translate(260, 175)">
                  <rect x="0" y="0" width="60" height="60" fill="transparent"
                  ?  stroke="#6ba5d7" />
                  <text x="0" y="85">rect</text>
                </g>
           
                <circle cx="530" cy="80" r="50" fill="none" stroke="#81c21c" stroke-
                ?  width="3" />
                <ellipse cx="530" cy="205" rx="50" ry="30" fill="#81c21c" />
           
                <path d="M680 150 C 710 80, 725 80, 755 150 S 810 220, 840 150" 
                ?  fill="none" stroke="#773b9a" stroke-width="3" />
           
                <g fill="#636466" style="font-size:16px; font-family:monospace">
                  <text x="60" y="260">line</text>
                  <text x="530" y="155" style="text-anchor:middle">circle</text>
                  <text x="530" y="260" style="text-anchor:middle">ellipse</text>
                  <text x="730" y="260">path</text>
                </g>
           
              </svg>
            </div>
          </body>
          </html>

          練習(xí):創(chuàng)建 SVG 圖形

          現(xiàn)在輪到你了!創(chuàng)建如下圖所示的 SVG 圖形。您可以在本章代碼文件start內(nèi)的文件夾中工作。02_SVG_exercise以下是一些指導(dǎo)原則:

          · 創(chuàng)建一個寬度和高度均為 400 像素的響應(yīng)式 SVG 容器(當屏幕上有足夠的空間時)。

          · 繪制一個寬度和高度均為 200 像素的正方形。將其置于 SVG 容器的中心,并為其提供透明填充和 5px 黑色描邊。

          · 在 SVG 容器的中心添加一個半徑為 100px 的圓。將其填充屬性設(shè)置為 CSS 顏色名稱“plum”。

          · 繪制兩條對角黑線,筆劃為 5 像素。一個從正方形的左上角到右下角。另一個從正方形的右上角到左下角。

          · 添加文本“SVG 太棒了!” 位于正方形上方并將其置于 SVG 容器的中心。為文本指定以下樣式屬性:字體大小為 18px,字體系列為 sans-serif。

          我們鼓勵您構(gòu)建此 SVG 圖形來強化本節(jié)中討論的概念。


          02_SVG_exercise / end您可以在附錄 D 的 D.1.1 節(jié)和本章代碼文件的文件夾中找到解決方案。我們鼓勵您嘗試自己完成它。

          1.2.3 畫布和webGL

          我們已經(jīng)提到過,我們通常使用 SVG 元素構(gòu)建 D3 項目。有時,我們可能需要從大型數(shù)據(jù)集創(chuàng)建復(fù)雜的可視化效果,而傳統(tǒng)的 SVG 方法可能會產(chǎn)生性能問題。請務(wù)必記住,對于數(shù)據(jù)可視化中的每個圖形細節(jié),D3 都會將一個或多個 SVG 元素附加到 DOM。一個典型的例子是由數(shù)千個節(jié)點和鏈接組成的大型網(wǎng)絡(luò)可視化。這些可能會讓你的瀏覽器喘不過氣來……盡管瀏覽器可以輕松處理的對象數(shù)量隨著性能的提高而不斷增加,但普遍接受的經(jīng)驗法則是,如果滿足以下條件,我們應(yīng)該考慮使用畫布而不是 SVG:可視化包含 1000 多個元素。

          Canvas 是一種客戶端繪圖 API,它使用腳本(通常是 JavaScript)來創(chuàng)建視覺效果和動畫。它不會將 XML 元素添加到 DOM,這在從大型數(shù)據(jù)集構(gòu)建可視化時可以顯著提高性能。

          Canvas 還允許您使用 WebGL API 來創(chuàng)建 3D 對象。盡管學(xué)習(xí) WebGL 超出了本書的范圍,但為 Web 創(chuàng)建 3D 數(shù)據(jù)可視化是可能的。目前主要用于實驗項目。在第 15 章中,我們將介紹如何使用畫布構(gòu)建可視化并討論其優(yōu)點和缺點。

          1.2.4 CSS

          CSS 代表層疊樣式表,是一種描述 DOM 元素如何在屏幕上顯示及其外觀的語言。從頁面的整體網(wǎng)格布局到文本使用的字體系列,再到散點圖中圓圈的顏色,CSS 可以將普通的 HTML 文件變成令人驚嘆的網(wǎng)頁。在 D3 項目中,我們通常使用內(nèi)聯(lián)樣式或通過外部樣式表應(yīng)用 CSS 樣式。

          內(nèi)聯(lián)樣式應(yīng)用于具有該style屬性的元素,如以下示例所示。該style屬性可以在傳統(tǒng)的 HTML 或 SVG 元素上使用,D3 有一個方便的方法來設(shè)置或修改該屬性,我們將在第 2 章中討論。

          <div style="padding:10px; background:#00ced1;"> ... </div>
          <text style="font-size:16px; font-family:serif;"> ... </text>

          內(nèi)聯(lián)樣式僅影響應(yīng)用它們的元素。如果我們想要將相同的設(shè)計傳播到多個元素,我們需要將相同的style屬性應(yīng)用于每個元素(或?qū)⑺性匕b在一起的 SVG 組)。它當然有效,但不是最有效的方法。

          另一方面,外部 CSS 樣式表非常適合全局應(yīng)用樣式。一種策略是要求 D3 將相同的類名添加到多個元素。然后,我們使用此類名稱作為外部樣式表中的選擇器,并將相同的樣式屬性應(yīng)用于目標元素組,如以下示例所示。這種方法效率更高,尤其是在維護大型項目時。它還遵循關(guān)注點分離原則,即我們將由 JavaScript 控制的行為與由 CSS 監(jiān)管的樣式分開。請注意,CSS 預(yù)處理器(例如 SASS 和 LESS)是此處描述的外部樣式表方法的一部分。

          在 CSS 樣式表中:

          .my-class {
            font-size: 16px;
            font-family: serif;
          }
           
          In the DOM:
          <text class="my-class"> ... </text>

          請記住,內(nèi)聯(lián)樣式優(yōu)先于從外部樣式表應(yīng)用的樣式。在任何前端開發(fā)項目中,規(guī)劃 CSS 樣式的架構(gòu)并考慮級聯(lián)順序非常重要。

          1.2.5 JavaScript

          D3 是一個 JavaScript 庫。它在 JavaScript 現(xiàn)有核心功能的基礎(chǔ)上添加了新方法。這意味著在使用 D3 時,具有一點 JavaScript 經(jīng)驗會很有幫助。這也意味著,在構(gòu)建 D3 項目時,您可以訪問所有現(xiàn)有的 JavaScript 功能。

          在本節(jié)中,我們將解釋 D3 項目中廣泛使用的兩個 JavaScript 主題:方法鏈和對象操作。

          方法鏈接

          如果您在網(wǎng)絡(luò)上搜索 D3 項目的示例,您會發(fā)現(xiàn)在同一選擇上會依次調(diào)用方法。這種技術(shù)就是我們所說的方法鏈,有助于保持代碼簡潔和可讀。

          我們可以將方法鏈視為汽車裝配線。假設(shè)我們編寫了運行這樣一條裝配線的腳本。正如您在下面的示例中看到的,我們首先聲明一個car創(chuàng)建新Car()對象的變量。然后我們調(diào)用函數(shù)putOnHood(),將引擎蓋放在汽車頂部,然后我們繼續(xù)調(diào)用將放置車輪、輪胎和燈的函數(shù)。每個連續(xù)的調(diào)用都會添加一個元素到Car()對象,并且,一旦執(zhí)行了所有方法,汽車就有了引擎蓋、車輪、輪胎和車燈。每個方法都會將更新后的汽車對象傳遞給下一個方法,從而“鏈接”。請注意,每個調(diào)用都用點分隔,并且調(diào)用方法的順序很重要。在我們的汽車裝配線示例中,我們需要先安裝車輪,然后才能將輪胎安裝到車輪上。

          let car = new Car().putOnHood().putOnWheels().putOnTires().putOnLights();

          現(xiàn)在讓我們看看如何在 D3 中使用方法鏈接。想象一下,我們想要從 DOM 中獲取所有 div 并在每個 div 中添加一個段落元素。段落元素應(yīng)具有類屬性my-class并包含文本“Wow”。然后,我們要在每個段落中插入一個 span 元素,并將文本“Even More Wow”以粗體顯示。如果沒有方法鏈接,我們需要將每個操作存儲到一個常量中,然后在執(zhí)行下一個操作時調(diào)用該常量,如下所示。光是看著就已經(jīng)很累了……

          const mySelection = d3.selectAll("div");
          const myParagraphs = mySelection.append("p");
          const myParagraphsWithAClass = myParagraphs.attr("class", "my-class");
          const myParagraphsWithText = myParagraphsWithAClass.text("Wow");
          const mySpans = myParagraphsWithText.append("span");
          const mySpansWithText = mySpans.text("Even More Wow")
          const myBoldSpans = mySpansWithText.style("font-weight", "900");

          由于方法鏈接,相同的示例變得更加簡潔。

          d3.selectAll("div").append("p").attr("class", "my-class").text("Wow")
             ? .append("span").text("Even More Wow").style("font-weight", "900");

          在 D3 中,斷行(JavaScript 會忽略這一點)以及縮進鏈接方法是很常見的。這使得代碼更容易閱讀,并且縮進可以幫助我們看到我們正在處理哪個元素。

          d3.selectAll("div")
            .append("p")
              .attr("class", "my-class")
              .text("Wow")
            .append("span")
              .text("Even More Wow")
              .style("font-weight", "900");

          不要擔心理解前面的代碼示例的作用,盡管您完全可以從不同方法的名稱中猜出它!目前,我們只希望您熟悉如何在 JavaScript 中鏈接方法。我們將在第 2 章中介紹 D3 特定的術(shù)語。

          數(shù)組和對象操作

          D3 都是關(guān)于數(shù)據(jù)的,而數(shù)據(jù)通常被構(gòu)造為 JavaScript 對象。了解這些對象的構(gòu)造以及如何訪問和操作它們包含的數(shù)據(jù)將為您構(gòu)建可視化提供巨大幫助。

          我們首先討論簡單數(shù)組,它是元素列表。在與數(shù)據(jù)相關(guān)的項目中,數(shù)組通常是數(shù)字或字符串的有序列表。

          const arrayOfNumbers = [17, 82, 9, 500, 40];
          const arrayOfStrings = ["blue", "red", "yellow", "orange"];

          數(shù)組中的每個元素都有一個數(shù)字位置,稱為索引,數(shù)組中第一個元素的索引為 0。

          arrayOfNumbers[0]   // => 17
          arrayOfStrings[2]   // => "yellow"

          數(shù)組具有長度屬性,對于非稀疏數(shù)組,該屬性指定它們包含的元素數(shù)量。由于數(shù)組是零索引的,因此數(shù)組中最后一個元素的索引對應(yīng)于數(shù)組長度減一。

          arrayOfNumbers.length;                      // => 5
          arrayOfStrings[arrayOfStrings.length - 1]   // => "orange"

          我們還可以使用方法來確定數(shù)組是否包含特定值includes()。true如果數(shù)組中的元素之一與作為參數(shù)傳遞的值完全對應(yīng),則此方法返回。否則,它返回false。

          arrayOfNumbers.includes(9)         // => true
          arrayOfStrings.includes("pink")    // => false
          arrayOfStrings.includes("ellow")   // => false

          然而,大多數(shù)數(shù)據(jù)集并不是簡單的數(shù)字或字符串列表,它們的每個數(shù)據(jù)點通常由多個屬性組成。讓我們想象一個虛構(gòu)機構(gòu)的員工數(shù)據(jù)庫,如表 1.1 所示。該表包含四列:每個員工的 ID、姓名和職位,以及該員工是否在 D3 工作。

          表 1.1 包含員工及其職位的小型數(shù)據(jù)集

          ID

          姓名

          位置

          與_d3一起工作

          1

          佐伊

          數(shù)據(jù)分析師

          錯誤的

          2

          詹姆士

          前端開發(fā)人員

          真的

          3

          愛麗絲

          全棧開發(fā)人員

          真的

          4

          休伯特

          設(shè)計師

          錯誤的

          數(shù)據(jù)集中的每一行或數(shù)據(jù)點都可以由 JavaScript 對象表示,如下所示row1。

          const row1 = {
                         id:"1",
                         name:"Zoe",
                         position:"Data analyst",
                         works_with_d3:false
                       };

          我們可以使用點符號輕松訪問對象中每個屬性的值。

          row1.name            // => "Zoe"
          row1.works_with_d3   // => false

          我們還可以使用括號表示法訪問這些值。如果屬性名稱包含空格等特殊字符,或者如果我們之前將屬性名稱保存在常量或變量中,那么括號表示法會很方便。

          row1["position"]                      // => "Data analyst"
           
          const myProperty = "works_with_d3";
          row1[myProperty]                      // => false

          在現(xiàn)實生活中,數(shù)據(jù)集通常被格式化為對象數(shù)組。例如,如果我們使用 D3 加載表 1.2 中包含的數(shù)據(jù)集(正如我們將在第 3 章中學(xué)習(xí)的那樣),我們將獲得以下對象數(shù)組,可以將其保存在名為 的常量中data。

          const data = [
           {id:"1", name:"Zoe", position:"Data analyst", works_with_d3:false},
           {id:"2", name:"James", position:"Frontend developer", works_with_d3:true},
           {id:"3", name:"Alice", position:"Fullstack developer", works_with_d3:true},
           {id:"4", name:"Hubert", position:"Designer", works_with_d3:false}
          ];

          data我們可以使用循環(huán)遍歷數(shù)組中的每個元素或數(shù)據(jù)點。更具體地說,JavaScript forEach循環(huán)非常方便且易于編寫和閱讀。迭代數(shù)據(jù)集的一個常見用例是數(shù)據(jù)整理。當我們加載外部 CSV 文件時,數(shù)字通常被格式化為字符串。讓我們以data數(shù)組為例,將屬性的值id從字符串轉(zhuǎn)換為數(shù)字。

          在下面的示例中,數(shù)組迭代器使d我們能夠訪問每個對象。使用點符號,我們id使用運算符將?每個值轉(zhuǎn)換為數(shù)字+。

          data.forEach(d => {
            d.id = +d.id;
          });

          JavaScript 提供了許多數(shù)組迭代器方法,可以幫助我們與數(shù)據(jù)交互,甚至在需要時重塑數(shù)據(jù)。假設(shè)我們想要將數(shù)據(jù)集中的每個員工定位到可視化上。創(chuàng)建一個僅包含員工姓名的簡單數(shù)組可能會派上用場,為此我們將使用map()方法。

          data.map(d => d.name);   // => ["Zoe", "James", "Alice", "Hubert"]

          同樣,如果我們只想隔離使用 D3 的員工,我們可以使用這些filter()方法。

          data.filter(d => d.works_with_d3);
           
          // => [
             {id:2, name:"James", position:"Frontend developer", works_with_d3:true},
             {id:4, name:"Hubert", position:"Designer", works_with_d3:true}
            ];

          最后,我們可以通過該方法找到id為3的員工find()。請注意,該find()方法在找到它要查找的值后停止迭代。我們只能在搜索單個數(shù)據(jù)點時使用此方法。

          data.find(d => d.id === 3);
           
          // => {id:"3", name:"Alice", position:"Fullstack developer", works_with_d3:true}

          本節(jié)討論的方法遠未涵蓋 JavaScript 提供的所有數(shù)組和對象操作技術(shù)。但在處理數(shù)據(jù)時,您可能會不斷回想起它們。每當您需要找到另一種方法來訪問或操作數(shù)據(jù)時,MDN Web 文檔 ( https://developer.mozilla.org/ ) 始終是包含大量示例的可靠參考。

          1.2.6 Node 和 JavaScript 框架

          JavaScript 在過去十年中發(fā)生了重大變化。現(xiàn)代 JavaScript 的兩個最重要的趨勢是 Node.js 的興起和 JavaScript 框架作為大多數(shù)項目標準的建立。

          對于 D3 項目,我們想了解的主要 Node 技術(shù)是 NPM,即 Node Package Manager。NPM 允許您安裝“模塊”或小型 JavaScript 代碼庫以在應(yīng)用程序中使用。您不必包含<script>對單個文件的一堆標記引用,并且如果模塊已構(gòu)建為不是一個整體結(jié)構(gòu),則可以減少應(yīng)用程序中包含的代碼量。

          D3.js 版本 7 于 2021 年中期發(fā)布,利用了模塊導(dǎo)入的優(yōu)勢。在本書中,您將看到以兩種方式之一使用 D3 的示例。我們要么加載整個 D3 庫,就像我們在第 2 章中所做的那樣,要么只包含我們需要的 D3 的各個部分,正如您將在后面的示例中看到的那樣。我們可以使用腳本標簽來做到這一點,但從第 2 部分開始,我們將使用 NPM 導(dǎo)入 D3 模塊,因為這被認為是當今的標準做法。如果您交付專業(yè)的 D3 項目,您可能需要熟悉它。

          如果您已經(jīng)參與了專業(yè)的 Web 項目,那么您也很有可能正在使用 JavaScript 框架,例如 React、Angular、Vue 或 Svelte。框架為開發(fā)人員提供了使用模塊化、可重用且可測試的代碼構(gòu)建 Web 項目的基礎(chǔ)。這些框架負責(zé)構(gòu)建和更新 DOM,這也是 D3 庫所做的事情。在第 8 章中,我們將討論在 JavaScript 框架內(nèi)構(gòu)建 D3 可視化時避免沖突的策略。

          最后,在專業(yè)的工作環(huán)境中,您可能會將 D3 與 TypeScript 結(jié)合使用。TypeScript 是 JavaScript 的語法超集,為代碼添加了類型安全性。盡管我們不會在本書中詳細討論它,但 D3 方法的類型可以使用 NPM 包 @type/d3 ( https://www.npmjs.com/package/@types/d3 ) 進行安裝。在第 8 章中,我們將在 Angular 項目中使用此類類型。

          1.2.7 可觀察的筆記本

          如果您在網(wǎng)絡(luò)上搜索 D3 項目的示例,您無疑會遇到 Observable 筆記本 ( observablehq.com )。Observable 是數(shù)據(jù)科學(xué)和可視化的協(xié)作平臺,類似于 Python 項目的 Jupyter 環(huán)境。Observable 平臺由 Mike Bostock 創(chuàng)建,取代了之前的在線 D3 沙箱bl.ocks.org 。所有官方的 D3 示例現(xiàn)在都位于 Observable 上,并且 D3 社區(qū)在那里非常活躍。

          重要的是要知道 Observable 要求您學(xué)習(xí)一種處理特定于該平臺的 D3 項目的方法。此外,您不能直接將 Observable Notebook 復(fù)制粘貼到前端開發(fā)環(huán)境中(但有多種方法可以導(dǎo)出和重用它們)。由于本書的重點是在類似于我們?nèi)绾谓桓?D3 項目進行生產(chǎn)的環(huán)境中構(gòu)建 D3 可視化,因此我們不會討論 Observable 筆記本。如果您有興趣學(xué)習(xí) Observable,您可以在observablehq.com/tutorials找到一系列優(yōu)秀的教程。您將在本書中學(xué)到的大部分技術(shù)和概念都可以轉(zhuǎn)化為 Observable 筆記本。

          1.3 D3.js 表達的數(shù)據(jù)可視化標準

          數(shù)據(jù)可視化從未像今天這樣流行。豐富的地圖、圖表以及系統(tǒng)和數(shù)據(jù)集的復(fù)雜表示不僅存在于工作場所,而且還存在于我們的娛樂和日常生活中。隨著這種流行,使用視覺手段以及美學(xué)規(guī)則來表示數(shù)據(jù)和信息的類和子類庫不斷增長,以促進易讀性和理解性。您的受眾,無論是公眾、學(xué)者還是決策者,已經(jīng)習(xí)慣了我們曾經(jīng)認為極其抽象和復(fù)雜的數(shù)據(jù)趨勢表示。這使得 D3 這樣的庫不僅受到數(shù)據(jù)科學(xué)家的歡迎,而且還受到記者、藝術(shù)家、學(xué)者、IT 專業(yè)人士,甚至數(shù)據(jù)可視化愛好者的歡迎。

          如此豐富的選項似乎讓人不知所措,而且修改數(shù)據(jù)集以顯示在流圖、樹狀圖或直方圖中相對容易,這往往會促進這樣一種觀念:信息可視化更多地是關(guān)于風(fēng)格而不是實質(zhì)內(nèi)容。幸運的是,完善的規(guī)則規(guī)定了針對不同系統(tǒng)的不同數(shù)據(jù)類型使用哪些圖表和方法。本書并不旨在涵蓋數(shù)據(jù)可視化中的所有最佳實踐,但我們將介紹其中的一些。盡管開發(fā)人員使用 D3 徹底改變了顏色和布局的使用,但大多數(shù)人希望創(chuàng)建支持實際問題的數(shù)據(jù)的可視化表示。

          當您構(gòu)建第一個可視化項目時,如果有疑問,請簡化 - 通常,呈現(xiàn)直方圖比小提琴圖更好,或者分層網(wǎng)絡(luò)布局(如樹狀圖)比力導(dǎo)向的網(wǎng)絡(luò)布局更好。視覺上更復(fù)雜的數(shù)據(jù)顯示方法往往會激發(fā)更多的興奮,但也會導(dǎo)致觀眾關(guān)注圖形的美觀而不是數(shù)據(jù)。創(chuàng)建酷炫且令人瞠目結(jié)舌的可視化并沒有什么錯,但我們永遠不應(yīng)該忘記任何數(shù)據(jù)可視化的主要目標都是講述一個故事。詢問周圍的人是否理解你的可視化以及他們?nèi)绾谓忉屗侵陵P(guān)重要的一步。他們需要解釋嗎?他們可以從與您的項目的互動中得出哪些結(jié)論?故事被講述了嗎?

          盡管如此,為了正確部署信息可視化,您應(yīng)該知道該做什么和不該做什么。您需要對您的數(shù)據(jù)和受眾有深入的了解。D3 賦予我們巨大的靈活性,但正如俗話所說,“能力越大,責(zé)任越大”。雖然知道某些圖表更適合表示特定類型的數(shù)據(jù)固然很好,但更重要的是要記住,如果不謹慎地從知情的角度構(gòu)建數(shù)據(jù)可視化,則可能會攜帶錯誤信息。如果您打算設(shè)計自己的可視化,那么了解數(shù)據(jù)可視化最佳實踐是至關(guān)重要的。了解這一點的最佳方法是回顧知名設(shè)計師和信息可視化從業(yè)者的工作。盡管整個圖書館的作品都在處理這些問題,以下是我們發(fā)現(xiàn)的一些有用的內(nèi)容,可以幫助您了解基礎(chǔ)知識。這些絕不是學(xué)習(xí)數(shù)據(jù)可視化的唯一文本,但它們是一個很好的起點。

          • 更好的數(shù)據(jù)可視化,喬納森施瓦比什
          • 功能藝術(shù)真實藝術(shù)圖表如何謊言,阿爾貝托·開羅
          • 數(shù)據(jù)可視化數(shù)據(jù)驅(qū)動設(shè)計手冊,安迪·柯克
          • 定量信息的視覺顯示設(shè)想信息,愛德華·塔夫特
          • 信息設(shè)計,伊莎貝爾·梅雷萊斯
          • 模式識別,克里斯蒂安·斯溫哈特
          • 可視化分析與設(shè)計,Tamara Munzner

          在閱讀有關(guān)數(shù)據(jù)可視化的內(nèi)容時要記住的一件事是,文獻通常關(guān)注靜態(tài)圖表。使用 D3,您將進行交互式動態(tài)可視化。一些交互可以使可視化不僅更具可讀性,而且更有吸引力。感覺自己是在探索而不是閱讀的用戶,即使只是將鼠標懸停在事件上幾次或簡單地單擊進行縮放,也可能會發(fā)現(xiàn)可視化的內(nèi)容比閱讀靜態(tài)等效內(nèi)容更引人注目和更令人難忘。但這種增加的復(fù)雜性需要了解用戶體驗。我們將在第 7 章中更詳細地討論這一點。

          我們的第一章到此結(jié)束!盡管我們還沒有使用過 D3,但您現(xiàn)在已經(jīng)掌握了入門所需的所有知識。當您不確定應(yīng)該在可視化中使用哪個 SVG 元素或者需要提醒如何使用 JavaScript 操作數(shù)據(jù)時,請繼續(xù)返回本章。從下一章開始,我們將卷起袖子,創(chuàng)建 D3 可視化。

          1.4 總結(jié)

          • 當您希望在數(shù)據(jù)可視化方面擁有完全的創(chuàng)意和技術(shù)自由時,D3 是您的首選工具。
          • D3 應(yīng)用程序的樣式和服務(wù)與傳統(tǒng) Web 內(nèi)容類似。
          • D3 從來不會單獨使用,而是技術(shù)和工具生態(tài)系統(tǒng)的一部分,我們將這些技術(shù)和工具結(jié)合起來創(chuàng)建豐富的 Web 界面:HTML、CSS、JavaScript、SVG、Canvas 和 React 或 Svelte 等框架。
          • 我們在構(gòu)建數(shù)據(jù)可視化時最常使用的 SVG 形狀是直線、矩形、圓形、橢圓形、路徑和文本。
          • 您需要對這些形狀及其主要屬性有基本的了解才能使用 D3。使用 D3 編寫 JavaScript 時,您應(yīng)該熟悉兩個主題:方法鏈和對象操作。方法鏈接是一種模式,其中在同一對象上依次調(diào)用多個方法。在 D3 中,數(shù)據(jù)集通常被構(gòu)造為對象數(shù)組。JavaScript 提供了多種方法來訪問和操作這些結(jié)構(gòu)中的數(shù)據(jù)。
          • 作為 D3 開發(fā)人員,深入了解數(shù)據(jù)可視化最佳實踐非常重要。多種資源可以幫助您開始學(xué)習(xí)之旅。

          眾號:

          CSS

          1. 請解釋CSS的盒模型是什么,并描述其組成部分。

          答案:CSS的盒模型是用于布局和定位元素的概念。它由內(nèi)容區(qū)域、內(nèi)邊距、邊框和外邊距組成,這些部分依次包裹在元素周圍。

          2. 解釋CSS中的選擇器及其優(yōu)先級。

          答案:CSS選擇器用于選擇要應(yīng)用樣式的HTML元素。選擇器的優(yōu)先級規(guī)則是:內(nèi)聯(lián)樣式 > ID選擇器 > 類選擇器、屬性選擇器、偽類選擇器 > 元素選擇器 > 通用選擇器。同時,使用!important可以提升樣式的優(yōu)先級。

          3. 解釋CSS中的浮動(float)是如何工作的,并提供一個示例。

          答案:浮動(float)是CSS中用于實現(xiàn)元素的左浮動或右浮動,使其脫離文檔流并環(huán)繞在其周圍的元素。例如:

          .float-example {
          float: left;
          width: 200px;
          height: 200px;
          }

          4. 解釋CSS中的定位(position)屬性及其不同的取值。

          答案:定位(position)屬性用于控制元素的定位方式。常見的取值有:static(默認,按照文檔流定位)、relative(相對定位)、absolute(絕對定位)、fixed(固定定位)和sticky(粘性定位)。

          5. 解釋CSS中的層疊順序(z-index)是如何工作的。

          答案:層疊順序(z-index)用于控制元素在垂直方向上的堆疊順序。具有較高層疊順序值的元素將顯示在較低層疊順序值的元素之上。默認情況下,層疊順序值為auto。

          6. 解釋CSS中的偽類和偽元素的區(qū)別,并給出一個示例。

          答案:偽類用于向選擇器添加特殊的狀態(tài),如:hover、:active等。偽元素用于向選擇器添加特殊的元素,如::before、::after等。例如:

          /* 偽類示例 */
          a:hover {
          color: red;
          }
          /* 偽元素示例 */
          p::before {
          content: "前綴";
          }

          7. 解釋CSS中的盒子模型的兩種模式:標準模式和怪異模式。

          答案:標準模式是按照W3C標準解析渲染頁面的模式。怪異模式是兼容舊版本瀏覽器的解析渲染頁面的模式。可以通過聲明來指定使用哪種模式。

          8. 解釋CSS中的BFC是什么,它的作用是什么?

          答案:BFC(塊級格式化上下文)是CSS中的一種渲染模式,它創(chuàng)建了一個獨立的渲染環(huán)境,其中的元素按照一定的規(guī)則進行布局和定位。BFC的作用包括:清除浮動、防止外邊距重疊等。

          9. 解釋CSS中的flexbox布局是什么,它的優(yōu)勢是什么?

          答案:flexbox布局是一種用于創(chuàng)建靈活的、響應(yīng)式的布局的CSS模塊。它通過flex容器和flex項目的組合來實現(xiàn)強大的布局能力。其優(yōu)勢包括簡單易用、自適應(yīng)性強、對齊和分布控制靈活等。

          10.解釋CSS中的媒體查詢是什么,它的作用是什么?

          答案:媒體查詢是CSS中的一種技術(shù),用于根據(jù)設(shè)備的特性和屬性來應(yīng)用不同的樣式。通過媒體查詢,可以根據(jù)屏幕尺寸、設(shè)備類型、分辨率等條件來優(yōu)化頁面的布局和樣式。

          JavaScript

          1. 解釋JavaScript的數(shù)據(jù)類型,并舉例說明每種類型。

          答案:JavaScript有七種數(shù)據(jù)類型:字符串(String)、數(shù)字(Number)、布爾值(Boolean)、對象(Object。Array/數(shù)組 和 function/函數(shù) 也屬于對象的一種)、空值(Null)、未定義(Undefined)、Symbol(獨一無二的值,ES6 新增)、BigInt (大整數(shù),能夠表示超過 Number 類型大小限制的整數(shù),ES 2020新增)

          例如:

          let str = "Hello";
          let num = 10;
          let bool = true;
          let obj = { name: "John" };
          let arr = [1, 2, 3];
          let n = null;
          let undef;

          2. 解釋JavaScript中的變量提升(Hoisting)是什么。

          答案:變量提升是指在JavaScript中,變量和函數(shù)聲明會在代碼執(zhí)行之前被提升到作用域的頂部。這意味著可以在聲明之前使用變量和函數(shù)。例如:

          console.log(x); // 輸出 undefined
          var x = 5;

          3. 解釋JavaScript中的閉包(Closure)是什么,并舉例說明。

          答案:閉包是指函數(shù)可以訪問并操作其詞法作用域之外的變量。它通過在函數(shù)內(nèi)部創(chuàng)建一個內(nèi)部函數(shù),并返回該內(nèi)部函數(shù)來實現(xiàn)。例如:

          function outer() {
          let x = 10;
          function inner() {
          console.log(x);
          }
          return inner;
          }
          let closure = outer();
          closure(); // 輸出 10

          4. 解釋JavaScript中的事件冒泡(Event Bubbling)和事件捕獲(Event Capturing)。

          答案:事件冒泡是指事件從最具體的元素開始向父元素逐級觸發(fā),直到觸發(fā)到根元素。事件捕獲是指事件從根元素開始,逐級向最具體的元素觸發(fā)。可以使用addEventListener方法的第三個參數(shù)來控制是使用事件冒泡還是事件捕獲。

          5. 解釋JavaScript中的原型繼承(Prototype Inheritance)是什么。

          答案:原型繼承是JavaScript中實現(xiàn)對象之間繼承關(guān)系的一種機制。每個對象都有一個原型對象,它包含了共享的屬性和方法。當訪問對象的屬性或方法時,如果對象本身沒有,則會沿著原型鏈向上查找。可以使用Object.create()方法或設(shè)置對象的__proto__屬性來實現(xiàn)原型繼承。

          6. 解釋JavaScript中的異步編程,并提供一個異步操作的示例。

          答案:異步編程是指在代碼執(zhí)行過程中,不會阻塞后續(xù)代碼執(zhí)行的一種編程方式。常見的異步操作包括網(wǎng)絡(luò)請求、定時器等。例如:

          console.log("開始");
          setTimeout(function() {
          console.log("異步操作");
          }, 1000);
          console.log("結(jié)束");

          7. 解釋JavaScript中的this關(guān)鍵字的作用和使用場景。

          答案:this關(guān)鍵字在JavaScript中表示當前執(zhí)行上下文的對象。它的具體取值根據(jù)函數(shù)的調(diào)用方式而定。在全局作用域中,this指向全局對象(瀏覽器環(huán)境中為window對象)。在函數(shù)中,this的指向取決于函數(shù)的調(diào)用方式,可以通過call、apply、bind等方法來顯式地指定this的值。

          8. 解釋JavaScript中的事件委托(Event Delegation)是什么,并提供一個使用事件委托的示例。

          答案:事件委托是指將事件處理程序綁定到父元素上,而不是直接綁定到每個子元素上。當事件觸發(fā)時,事件會冒泡到父元素,然后通過判斷事件的目標來執(zhí)行相應(yīng)的處理邏輯。這樣可以減少事件處理程序的數(shù)量,提高性能。例如:

          <ul id="list">
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
          </ul>
          <script>
          document.getElementById("list").addEventListener("click", function(event) {
          if (event.target.tagName === "LI") {
          console.log(event.target.textContent);
          }
          });
          </script>

          9. 解釋JavaScript中的模塊化編程,并提供一個使用模塊的示例。

          答案:模塊化編程是指將代碼劃分為獨立的模塊,每個模塊負責(zé)特定的功能,并通過導(dǎo)入和導(dǎo)出來實現(xiàn)模塊之間的依賴關(guān)系。ES6引入了模塊化的語法,可以使用import和export關(guān)鍵字來導(dǎo)入和導(dǎo)出模塊。例如:

          // module.js
          export function sayHello() {
          console.log("Hello!");
          }
          // main.js
          import { sayHello } from "./module.js";
          sayHello(); // 輸出 "Hello!"

          10. 解釋JavaScript中的嚴格模式(Strict Mode)。

          答案:嚴格模式是一種JavaScript的執(zhí)行模式,它提供了更嚴格的語法和錯誤檢查。在嚴格模式下,一些不安全或不推薦的語法會被禁用,同時會引入一些新的特性,如變量必須先聲明才能使用、禁止使用this指向全局對象等。

          11. 解釋JavaScript中的事件冒泡(Event Bubbling)和事件捕獲(Event Capturing)。

          答案:事件冒泡是指當一個事件在DOM樹中觸發(fā)時,它會從最內(nèi)層的元素開始向外傳播至最外層的元素。事件捕獲是指當一個事件在DOM樹中觸發(fā)時,它會從最外層的元素開始向內(nèi)傳播至最內(nèi)層的元素。

          12. 什么是原型鏈(Prototype Chain)?如何利用原型鏈實現(xiàn)繼承?

          答案:原型鏈是JavaScript中對象之間的連接關(guān)系,每個對象都有一個指向其原型(prototype)的引用。通過原型鏈,對象可以繼承其原型對象的屬性和方法。可以使用原型鏈實現(xiàn)繼承,通過將一個對象的原型指向另一個對象,從而使得該對象可以訪問另一個對象的屬性和方法。

          13. 解釋JavaScript中的防抖(Debounce)和節(jié)流(Throttle)。

          答案:防抖和節(jié)流都是用于控制函數(shù)執(zhí)行頻率的技術(shù)。防抖指的是在某個時間段內(nèi),只執(zhí)行最后一次觸發(fā)的函數(shù)調(diào)用。節(jié)流指的是在某個時間段內(nèi),按照固定的時間間隔執(zhí)行函數(shù)調(diào)用。

          14. 什么是事件循環(huán)(Event Loop)?請解釋JavaScript中的事件循環(huán)機制。

          答案:事件循環(huán)是JavaScript中處理異步操作的機制。事件循環(huán)不斷地從任務(wù)隊列中取出任務(wù)并執(zhí)行,直到任務(wù)隊列為空。事件循環(huán)由主線程和任務(wù)隊列組成,主線程負責(zé)執(zhí)行同步任務(wù),異步任務(wù)會被放入任務(wù)隊列中,等待主線程空閑時被執(zhí)行。

          15. 解釋JavaScript中的深拷貝和淺拷貝。

          答案:深拷貝是指創(chuàng)建一個新對象,將原始對象的所有屬性和嵌套對象的屬性都復(fù)制到新對象中。淺拷貝是指創(chuàng)建一個新對象,將原始對象的屬性復(fù)制到新對象中,但嵌套對象的引用仍然是共享的。

          16. 什么是異步編程?請列舉幾種處理異步操作的方法。

          答案:異步編程是一種處理可能耗時的操作而不阻塞主線程的編程方式。常見的處理異步操作的方法有回調(diào)函數(shù)、Promise、async/await和事件監(jiān)聽等。

          17. 解釋JavaScript中的Hoisting(變量提升)。

          答案:變量提升是指在JavaScript中,變量和函數(shù)的聲明會被提升到當前作用域的頂部。這意味著可以在聲明之前使用變量和函數(shù),但它們的賦值或定義仍然在原來的位置。

          18. 什么是柯里化(Currying)?請給出一個柯里化的示例。

          答案:柯里化是一種將接受多個參數(shù)的函數(shù)轉(zhuǎn)換為接受一個參數(shù)并返回一個新函數(shù)的過程。示例:

          function add(a) {
          return function(b) {
          return a + b;
          }
          }
          var add5 = add(5);
          console.log(add5(3)); // 輸出:8

          TypeScript

          1. 解釋TypeScript和JavaScript之間的關(guān)系。

          答案:TypeScript是JavaScript的超集,它添加了靜態(tài)類型和其他一些特性。TypeScript代碼可以編譯成JavaScript代碼,因此可以在任何支持JavaScript的環(huán)境中運行。

          2. TypeScript中的類型注解是什么?如何使用類型注解?

          答案:類型注解是指在變量、函數(shù)參數(shù)、函數(shù)返回值等地方顯式地聲明類型信息。可以使用冒號(:)后跟類型來添加類型注解。例如:

          let num: number = 10;
          function add(a: number, b: number): number {
          return a + b;
          }

          3. TypeScript中的接口是什么?如何定義和使用接口?

          答案:接口是一種用于定義對象的結(jié)構(gòu)和類型的語法。可以使用interface關(guān)鍵字來定義接口。例如:

          interface Person {
          name: string;
          age: number;
          }
          function greet(person: Person) {
          console.log(`Hello, ${person.name}!`);
          }
          let john: Person = { name: "John", age: 25 };
          greet(john); // 輸出 "Hello, John!"

          4. TypeScript中的類是什么?如何定義和使用類?

          答案:類是一種用于創(chuàng)建對象的藍圖,它包含屬性和方法。可以使用class關(guān)鍵字來定義類。例如:

          class Person {
          name: string;
          age: number;
          constructor(name: string, age: number) {
          this.name = name;
          this.age = age;
          }
          greet() {
          console.log(`Hello, ${this.name}!`);
          }
          }
          let john = new Person("John", 25);
          john.greet(); // 輸出 "Hello, John!"

          5. TypeScript中的泛型是什么?如何使用泛型?

          答案:泛型是一種用于創(chuàng)建可重用代碼的工具,它允許在定義函數(shù)、類或接口時使用占位符類型。可以使用尖括號(<>)來指定泛型類型。例如:

          function identity<T>(value: T): T {
          return value;
          }
          let result = identity<string>("Hello");
          console.log(result); // 輸出 "Hello"

          6. TypeScript中的枚舉是什么?如何定義和使用枚舉?

          答案:枚舉是一種用于定義命名常量集合的語法。可以使用enum關(guān)鍵字來定義枚舉。例如:

          enum Color {
          Red,
          Green,
          Blue,
          }
          let color: Color = Color.Green;
          console.log(color); // 輸出 1

          7. TypeScript中的模塊是什么?如何導(dǎo)出和導(dǎo)入模塊?

          答案:模塊是用于組織和封裝代碼的單元。可以使用export關(guān)鍵字將模塊中的變量、函數(shù)、類等導(dǎo)出,以便其他模塊可以使用。可以使用import關(guān)鍵字來導(dǎo)入其他模塊的導(dǎo)出。例如:

          // module.ts
          export function greet(name: string) {
          console.log(`Hello, ${name}!`);
          }
          // main.ts
          import { greet } from "./module";
          greet("John"); // 輸出 "Hello, John!"

          8. TypeScript中的類型推斷是什么?如何使用類型推斷?

          答案:類型推斷是指TypeScript根據(jù)上下文自動推斷變量的類型,而無需顯式地添加類型注解。例如:

          let num = 10; // 推斷為 number 類型
          let str = "Hello"; // 推斷為 string 類型

          9. TypeScript中的命名空間是什么?如何定義和使用命名空間?

          答案:命名空間是一種用于組織和封裝代碼的機制,它避免了全局命名沖突。可以使用namespace關(guān)鍵字來定義命名空間。例如:

          namespace MyNamespace {
          export function greet(name: string) {
          console.log(`Hello, ${name}!`);
          }
          }
          MyNamespace.greet("John"); // 輸出 "Hello, John!"

          10. TypeScript中的類型別名是什么?如何定義和使用類型別名?

          答案:類型別名是給類型起一個別名,以便在代碼中更方便地引用。可以使用type關(guān)鍵字來定義類型別名。例如:

          type Point = { x: number; y: number };
          function printPoint(point: Point) {
          console.log(`(${point.x}, ${point.y})`);
          }
          let p: Point = { x: 1, y: 2 };
          printPoint(p); // 輸出 "(1, 2)"

          VUE2

          1. Vue.js是什么?它有哪些特點?

          答案:Vue.js是一個用于構(gòu)建用戶界面的JavaScript框架。它具有以下特點:

          響應(yīng)式數(shù)據(jù)綁定:通過使用Vue的數(shù)據(jù)綁定語法,可以實現(xiàn)數(shù)據(jù)的自動更新。 組件化開發(fā):Vue允許將頁面劃分為獨立的組件,提高了代碼的可維護性和復(fù)用性。 虛擬DOM:Vue使用虛擬DOM來跟蹤頁面上的變化,并高效地更新實際的DOM。 指令系統(tǒng):Vue提供了豐富的內(nèi)置指令,用于處理常見的DOM操作和邏輯控制。 生態(tài)系統(tǒng):Vue擁有龐大的生態(tài)系統(tǒng),包括插件、工具和第三方庫,可以滿足各種開發(fā)需求。

          2. Vue中的雙向數(shù)據(jù)綁定是如何實現(xiàn)的?

          答案:Vue中的雙向數(shù)據(jù)綁定是通過v-model指令實現(xiàn)的。v-model可以在表單元素(如、、)上創(chuàng)建雙向數(shù)據(jù)綁定。當用戶輸入改變表單元素的值時,數(shù)據(jù)模型會自動更新;反之,當數(shù)據(jù)模型的值改變時,表單元素也會自動更新。

          3. Vue中的生命周期鉤子有哪些?它們的執(zhí)行順序是怎樣的?

          答案:Vue中的生命周期鉤子包括beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy和destroyed。它們的執(zhí)行順序如下:

          beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy destroyed

          4. Vue中的計算屬性和監(jiān)聽器有什么區(qū)別?

          答案:計算屬性是基于依賴的屬性,它根據(jù)其依賴的數(shù)據(jù)動態(tài)計算得出值。計算屬性具有緩存機制,只有在依賴的數(shù)據(jù)發(fā)生變化時才會重新計算。監(jiān)聽器是用于監(jiān)聽數(shù)據(jù)的變化并執(zhí)行相應(yīng)的操作。當數(shù)據(jù)發(fā)生變化時,監(jiān)聽器會立即執(zhí)行指定的回調(diào)函數(shù)。

          5. Vue中的組件通信有哪些方式?

          答案:Vue中的組件通信方式包括:

          父子組件通信:通過props向子組件傳遞數(shù)據(jù),子組件通過事件向父組件發(fā)送消息。 子父組件通信:子組件通過$emit觸發(fā)事件,父組件通過監(jiān)聽事件并響應(yīng)。 兄弟組件通信:通過共享的父組件來傳遞數(shù)據(jù)或通過事件總線(Event Bus)進行通信。 跨級組件通信:通過provide和inject來在祖先組件中提供數(shù)據(jù),然后在后代組件中使用。

          6. Vue中的路由是如何實現(xiàn)的?

          答案:Vue中的路由是通過Vue Router實現(xiàn)的。Vue Router是Vue.js官方提供的路由管理器,它允許開發(fā)者在Vue應(yīng)用中實現(xiàn)單頁面應(yīng)用(SPA)。Vue Router通過配置路由映射關(guān)系,將URL路徑與組件進行關(guān)聯(lián),并提供導(dǎo)航功能,使用戶可以在不刷新頁面的情況下切換視圖。

          7. Vue中的指令有哪些?舉例說明它們的用法。

          答案:Vue中常用的指令包括:

          v-if:根據(jù)表達式的值條件性地渲染元素。 v-for:根據(jù)數(shù)組或?qū)ο蟮臄?shù)據(jù)進行循環(huán)渲染。 v-bind:用于動態(tài)綁定屬性或響應(yīng)式地更新屬性。 v-on:用于監(jiān)聽DOM事件并執(zhí)行相應(yīng)的方法。 v-model:用于在表單元素上實現(xiàn)雙向數(shù)據(jù)綁定。 例如:

          <div v-if="show">顯示內(nèi)容</div>
          <ul>
          <li v-for="item in items" :key="item.id">{{ item.name }}</li>
          </ul>
          <img v-bind:src="imageUrl">
          <button v-on:click="handleClick">點擊按鈕</button>
          <input v-model="message">

          8. Vue中的watch和computed有什么區(qū)別?

          答案:watch和computed都可以用于監(jiān)聽數(shù)據(jù)的變化,但它們的用法和實現(xiàn)方式略有不同。watch用于監(jiān)聽指定的數(shù)據(jù)變化,并在數(shù)據(jù)變化時執(zhí)行相應(yīng)的操作。computed用于根據(jù)依賴的數(shù)據(jù)動態(tài)計算得出一個新的值,并將該值緩存起來,只有在依賴的數(shù)據(jù)發(fā)生變化時才會重新計算。

          9. Vue中的mixin是什么?它有什么作用?

          答案:Mixin是一種用于在多個組件之間共享代碼的方式。Mixin可以包含組件選項(如數(shù)據(jù)、方法、生命周期鉤子等),并將其合并到使用Mixin的組件中。這樣可以實現(xiàn)代碼的復(fù)用和組件的擴展,減少重復(fù)編寫相似代碼的工作。

          10. Vue中的keep-alive是什么?它有什么作用?

          答案:是Vue中的一個內(nèi)置組件,用于緩存動態(tài)組件。當組件包裹在中時,組件的狀態(tài)將被保留,包括它的實例、狀態(tài)和DOM結(jié)構(gòu)。這樣可以避免在組件切換時重復(fù)創(chuàng)建和銷毀組件,提高性能和用戶體驗。

          11. 請解釋Vue.js中的依賴注入(Dependency Injection)是什么?它在Vue中的應(yīng)用場景是什么?

          答案:依賴注入是一種設(shè)計模式,用于將依賴關(guān)系從一個組件傳遞到另一個組件。在Vue中,依賴注入通過provide和inject選項實現(xiàn)。父組件通過provide提供數(shù)據(jù),然后子組件通過inject注入這些數(shù)據(jù)。它在跨多個層級的組件通信中非常有用。

          12. Vue.js中的渲染函數(shù)(Render Function)是什么?它與模板(Template)有什么區(qū)別?

          答案:渲染函數(shù)是一種用JavaScript代碼編寫組件的方式,它可以動態(tài)地生成虛擬DOM。與模板相比,渲染函數(shù)提供了更大的靈活性和控制力,可以處理更復(fù)雜的邏輯和動態(tài)渲染需求。

          13. Vue.js中的插槽(Slot)是什么?請?zhí)峁┮粋€具有命名插槽和作用域插槽的示例。

          答案:插槽是一種用于在組件中擴展內(nèi)容的機制。命名插槽允許父組件向子組件插入具有特定名稱的內(nèi)容,而作用域插槽允許子組件將數(shù)據(jù)傳遞給父組件。示例:

          <!-- 父組件 -->
          <template>
          <div>
          <slot name="header"></slot>
          <slot :data="data"></slot>
          </div>
          </template>
          <!-- 子組件 -->
          <template>
          <div>
          <slot name="header">默認標題</slot>
          <slot :data="computedData">{{ computedData }}</slot>
          </div>
          </template>

          14. Vue.js中的動畫系統(tǒng)是如何工作的?請?zhí)峁┮粋€簡單的動畫示例。

          答案:Vue.js的動畫系統(tǒng)通過CSS過渡和動畫類實現(xiàn)。通過在元素上添加過渡類或動畫類,可以觸發(fā)相應(yīng)的過渡效果或動畫效果。示例:

          <transition name="fade">
          <div v-if="show">顯示內(nèi)容</div>
          </transition>
          <!-- CSS樣式 -->
          <style>
          .fade-enter-active, .fade-leave-active {
          transition: opacity 0.5s;
          }
          .fade-enter, .fade-leave-to {
          opacity: 0;
          }
          </style>

          15. Vue.js中的錯誤處理機制是什么?如何捕獲和處理Vue組件中的錯誤?

          答案:Vue.js提供了全局的錯誤處理機制和組件級別的錯誤處理機制。全局錯誤處理可以通過errorCaptured鉤子函數(shù)捕獲和處理錯誤。組件級別的錯誤處理可以通過errorCaptured鉤子函數(shù)或errorHandler選項捕獲和處理錯誤。

          16. Vue.js中的服務(wù)端渲染(SSR)是什么?它有哪些優(yōu)勢和限制?

          答案:服務(wù)端渲染是指在服務(wù)器上生成HTML內(nèi)容并將其發(fā)送到瀏覽器進行渲染的過程。Vue.js可以進行服務(wù)端渲染,提供更好的首次加載性能和SEO優(yōu)化。然而,服務(wù)端渲染也帶來了一些限制,如增加了服務(wù)器負載和開發(fā)復(fù)雜性。

          17. Vue.js中的響應(yīng)式數(shù)組有哪些限制?如何解決這些限制?

          答案:Vue.js的響應(yīng)式系統(tǒng)對于數(shù)組的變異方法(如push、pop、splice等)是無法追蹤的。為了解決這個限制,Vue提供了一些特殊的方法,如Vue.set、vm.$set和Array.prototype.splice。這些方法可以用于更新數(shù)組并保持響應(yīng)式。

          18. Vue.js中的性能優(yōu)化有哪些常見的技巧?

          答案:常見的Vue.js性能優(yōu)化技巧包括:

          使用v-if和v-for時注意避免不必要的渲染。 合理使用computed屬性和watch監(jiān)聽器。 使用keep-alive組件緩存組件狀態(tài)。 使用異步組件進行按需加載。 避免在模板中使用復(fù)雜的表達式。 使用key屬性管理組件和元素的復(fù)用。 合理使用懶加載和分割代碼。

          19. Vue.js中的路由導(dǎo)航守衛(wèi)有哪些?它們的執(zhí)行順序是怎樣的?

          答案:Vue.js中的路由導(dǎo)航守衛(wèi)包括全局前置守衛(wèi)、全局解析守衛(wèi)、全局后置守衛(wèi)、路由獨享守衛(wèi)和組件內(nèi)守衛(wèi)。它們的執(zhí)行順序如下:

          全局前置守衛(wèi)(beforeEach) 路由獨享守衛(wèi)(beforeEnter) 解析守衛(wèi)(beforeResolve) 組件內(nèi)守衛(wèi)(beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave) 全局后置守衛(wèi)(afterEach)

          20. Vue.js中的單元測試是如何進行的?請?zhí)峁┮粋€簡單的單元測試示例。

          答案:Vue.js的單元測試可以使用工具如Jest或Mocha進行。示例:

          // 組件代碼
          // MyComponent.vue
          <template>
          <div class="my-component">
          <span>{{ message }}</span>
          <button @click="increment">增加</button>
          </div>
          </template>
          <script>
          export default {
          data() {
          return {
          message: 'Hello',
          count: 0
          }
          },
          methods: {
          increment() {
          this.count++
          }
          }
          }
          </script>
          // 單元測試代碼
          // MyComponent.spec.js
          import { shallowMount } from '@vue/test-utils'
          import MyComponent from './MyComponent.vue'
          describe('MyComponent', () => {
          it('renders message correctly', () => {
          const wrapper = shallowMount(MyComponent)
          expect(wrapper.find('span').text()).toBe('Hello')
          })
          it('increments count when button is clicked', () => {
          const wrapper = shallowMount(MyComponent)
          wrapper.find('button').trigger('click')
          expect(wrapper.vm.count).toBe(1)
          })
          })

          VUE3

          1. Vue.js 3中的Composition API是什么?它與Options API有什么區(qū)別?

          答案:Composition API是Vue.js 3中引入的一種新的組織組件邏輯的方式。它允許開發(fā)者通過函數(shù)的方式組織和重用邏輯,而不是通過選項對象。相比之下,Options API是Vue.js 2中常用的組織組件邏輯的方式,通過選項對象中的屬性來定義組件的數(shù)據(jù)、方法等。

          2. Vue.js 3中的Teleport是什么?請給出一個Teleport的示例。

          答案:Teleport是Vue.js 3中引入的一種機制,用于將組件的內(nèi)容渲染到DOM樹中的任意位置。示例:

          <template>
          <div>
          <button @click="showModal = true">打開模態(tài)框</button>
          <teleport to="body">
          <modal v-if="showModal" @close="showModal = false">模態(tài)框內(nèi)容</modal>
          </teleport>
          </div>
          </template>

          3. Vue.js 3中的響應(yīng)式系統(tǒng)是如何工作的?它與Vue.js 2中的響應(yīng)式系統(tǒng)有什么區(qū)別?

          答案:Vue.js 3中的響應(yīng)式系統(tǒng)使用了Proxy對象來實現(xiàn)。與Vue.js 2中的響應(yīng)式系統(tǒng)相比,Vue.js 3的響應(yīng)式系統(tǒng)具有更好的性能和更細粒度的追蹤,能夠更準確地檢測到數(shù)據(jù)的變化,并且支持嵌套的響應(yīng)式數(shù)據(jù)。

          4. Vue.js 3中的Suspense是什么?它的作用是什么?

          答案:Suspense是Vue.js 3中引入的一種機制,用于處理異步組件的加載狀態(tài)。它可以在異步組件加載完成之前顯示一個占位符,并在加載完成后渲染異步組件的內(nèi)容。這樣可以更好地處理異步組件的加載過程,提供更好的用戶體驗。

          5. Vue.js 3中的provide和inject有什么作用?請給出一個provide和inject的示例。

          答案:provide和inject用于實現(xiàn)組件之間的依賴注入。通過在父組件中使用provide提供數(shù)據(jù),然后在子組件中使用inject注入這些數(shù)據(jù)。示例:

          // 父組件
          const Parent = {
          provide: {
          message: 'Hello'
          },
          // ...
          }
          // 子組件
          const Child = {
          inject: ['message'],
          created() {
          console.log(this.message); // 輸出:Hello
          },
          // ...
          }

          6. Vue.js 3中的動畫系統(tǒng)有哪些改進?請列舉幾個改進之處。

          答案:Vue.js 3中的動畫系統(tǒng)相比Vue.js 2有以下改進之處:

          更好的性能:Vue.js 3的動畫系統(tǒng)使用了更高效的動畫引擎,提供了更好的性能。 更簡潔的語法:Vue.js 3的動畫系統(tǒng)使用了更簡潔的語法,使得動畫的定義和使用更加直觀和方便。 支持更多的動畫特性:Vue.js 3的動畫系統(tǒng)支持更多的動畫特性,如交互式動畫和更復(fù)雜的動畫效果。 Vue.js 3中的靜態(tài)提升(Static Tree Hoisting)是什么?它有什么優(yōu)勢? 答案:靜態(tài)提升是Vue.js 3中的一項優(yōu)化技術(shù),通過在編譯階段將靜態(tài)節(jié)點提升為常量,從而減少了運行時的開銷。這項優(yōu)化技術(shù)可以提高組件的渲染性能,并減少生成的代碼體積。

          7. Vue.js 3中的Fragment是什么?它的作用是什么?

          答案:Fragment是Vue.js 3中引入的一種機制,用于在組件中返回多個根節(jié)點。在Vue.js 2中,組件的模板只能有一個 Vue.js 3中的Composition API中的ref和reactive有什么區(qū)別?什么時候使用哪個? 答案:ref用于創(chuàng)建一個響應(yīng)式的基本數(shù)據(jù)類型,而reactive用于創(chuàng)建一個響應(yīng)式的對象。當需要創(chuàng)建一個簡單的響應(yīng)式數(shù)據(jù)時,可以使用ref,當需要創(chuàng)建一個包含多個屬性的響應(yīng)式對象時,可以使用reactive。

          8. Vue.js 3中的watchEffect和watch有什么區(qū)別?什么時候使用哪個?

          答案:watchEffect用于監(jiān)聽響應(yīng)式數(shù)據(jù)的變化,并在回調(diào)函數(shù)中執(zhí)行相應(yīng)的操作。它會自動追蹤依賴,并在依賴變化時重新運行回調(diào)函數(shù)。watch用于監(jiān)聽指定的響應(yīng)式數(shù)據(jù),并在其變化時執(zhí)行相應(yīng)的操作。它可以精確地指定要監(jiān)聽的數(shù)據(jù),并提供更多的配置選項。一般來說,如果只需要監(jiān)聽一個響應(yīng)式數(shù)據(jù)的變化并執(zhí)行相應(yīng)操作,可以使用watchEffect;如果需要更細粒度的控制,可以使用watch。

          9. Vue.js 3中的v-model指令在使用時有哪些注意事項?

          答案:在使用v-model指令時,有以下注意事項:

          v-model指令必須與一個表單元素一起使用,如、、等。 當使用自定義組件時,組件內(nèi)部必須實現(xiàn)modelValue屬性和update:modelValue事件,以支持v-model的雙向綁定。 可以使用.lazy修飾符實現(xiàn)在輸入框失去焦點時更新數(shù)據(jù)。 可以使用.trim修飾符自動去除輸入框內(nèi)容的首尾空格。 可以使用.number修飾符將輸入框的值轉(zhuǎn)換為數(shù)字類型。

          10. Vue.js 3中的provide和inject是否支持響應(yīng)式數(shù)據(jù)?

          答案:默認情況下,provide和inject不支持響應(yīng)式數(shù)據(jù)。如果需要在provide中提供一個響應(yīng)式數(shù)據(jù),可以使用ref或reactive將數(shù)據(jù)包裝起來。然后在inject中使用toRefs或toRef將數(shù)據(jù)解構(gòu)出來,以獲取響應(yīng)式的引用。

          11. Vue.js 3中的nextTick方法有什么作用?在什么情況下使用它?

          答案:nextTick方法用于在下次DOM更新循環(huán)結(jié)束之后執(zhí)行回調(diào)函數(shù)。它可以用來確保在更新DOM后執(zhí)行某些操作,如操作更新后的DOM元素或獲取更新后的計算屬性的值。通常在需要等待DOM更新完成后進行操作的情況下使用nextTick。

          12. Vue.js 3中的和組件有什么區(qū)別?

          答案:組件用于將組件的內(nèi)容渲染到DOM樹中的任意位置,而組件用于在組件進入或離開DOM樹時應(yīng)用過渡效果。主要用于組件的位置移動,而主要用于組件的顯示和隱藏過渡。

          13. Vue.js 3中的v-for指令中的key屬性有什么作用?為什么要使用它?

          答案:v-for指令中的key屬性用于給每個迭代項設(shè)置一個唯一的標識符。它的作用是幫助Vue.js跟蹤每個節(jié)點的身份,以便在數(shù)據(jù)發(fā)生變化時高效地更新DOM。使用key屬性可以避免出現(xiàn)錯誤的節(jié)點更新或重新排序的問題。

          React

          1. 什么是React?它的核心概念是什么?

          答案:React是一個用于構(gòu)建用戶界面的JavaScript庫。它的核心概念是組件化和聲明式編程。React將用戶界面拆分為獨立的可重用組件,并使用聲明式語法描述組件的狀態(tài)和UI的關(guān)系,使得構(gòu)建復(fù)雜的UI變得簡單和可維護。

          2. 什么是JSX?它與HTML有什么區(qū)別?

          答案:JSX是一種JavaScript的語法擴展,用于在React中描述UI的結(jié)構(gòu)。它類似于HTML,但有一些區(qū)別:

          3. 什么是React組件?它們有哪兩種類型?

          答案:React組件是構(gòu)建用戶界面的獨立單元。React組件有兩種類型:

          函數(shù)組件:使用函數(shù)來定義組件,接收props作為參數(shù),并返回一個React元素。 類組件:使用ES6類來定義組件,繼承自React.Component類,通過render方法返回一個React元素。

          4. 什么是狀態(tài)(state)和屬性(props)?它們之間有什么區(qū)別?

          答案:狀態(tài)(state)是組件自身管理的數(shù)據(jù),可以通過setState方法來更新。屬性(props)是從父組件傳遞給子組件的數(shù)據(jù),子組件無法直接修改props,只能通過父組件的更新來改變props。

          區(qū)別:

          狀態(tài)(state)是組件內(nèi)部的數(shù)據(jù),可以在組件中自由修改和管理。 屬性(props)是從父組件傳遞給子組件的數(shù)據(jù),子組件無法直接修改,只能接收和使用。

          5. 什么是React生命周期方法?列舉一些常用的生命周期方法。

          答案:React生命周期方法是在組件不同階段執(zhí)行的特定方法。以下是一些常用的React生命周期方法:

          componentDidMount:組件掛載后立即調(diào)用。 componentDidUpdate:組件更新后調(diào)用。 componentWillUnmount:組件卸載前調(diào)用。 shouldComponentUpdate:決定組件是否需要重新渲染。 getDerivedStateFromProps:根據(jù)props的變化來更新狀態(tài)。

          6. 什么是React Hooks?它們的作用是什么?

          答案:React Hooks是React 16.8版本引入的一種特性,用于在函數(shù)組件中使用狀態(tài)和其他React特性。Hooks提供了一種無需編寫類組件的方式來管理狀態(tài)和處理副作用,使得函數(shù)組件具有類組件的能力。

          7. 什么是React Router?它的作用是什么?

          答案:React Router是React中用于處理路由的庫。它提供了一種在單頁面應(yīng)用中實現(xiàn)導(dǎo)航和路由功能的方式。React Router可以幫助開發(fā)者實現(xiàn)頁面之間的切換、URL參數(shù)的傳遞、嵌套路由等功能。

          8. 什么是React Context?它的作用是什么?

          答案:React Context是一種用于在組件樹中共享數(shù)據(jù)的機制。它可以避免通過props一層層傳遞數(shù)據(jù),使得跨組件的數(shù)據(jù)共享變得更加簡單和高效。React Context提供了一個Provider和Consumer組件,用于提供和消費共享的數(shù)據(jù)。

          9. 什么是React的協(xié)調(diào)(Reconciliation)過程?它是如何工作的?

          答案:React的協(xié)調(diào)過程是指React在進行組件更新時,通過比較新舊虛擬DOM樹的差異,僅對需要更新的部分進行實際的DOM操作。協(xié)調(diào)過程的工作方式如下:

          React會逐層比較新舊虛擬DOM樹的節(jié)點,并找出差異。 對于每個差異,React會生成相應(yīng)的DOM操作指令,如插入、更新或刪除節(jié)點。 React會將所有的DOM操作指令批量執(zhí)行,以減少對真實DOM的操作次數(shù)。

          10. 什么是React的事件合成(SyntheticEvent)?它的作用是什么?

          答案:React的事件合成是一種在React中處理事件的機制。它是React為了提高性能和跨瀏覽器兼容性而實現(xiàn)的一種事件系統(tǒng)。事件合成的作用包括:

          提供了一種統(tǒng)一的方式來處理事件,無需考慮瀏覽器兼容性。 可以通過事件委托的方式將事件處理程序綁定到父組件,提高性能。 可以訪問原生事件對象的屬性和方法。

          11. 什么是React的Fiber架構(gòu)?它解決了什么問題?

          答案:React的Fiber架構(gòu)是React 16版本引入的一種新的協(xié)調(diào)算法和架構(gòu)。它旨在解決長時間渲染阻塞主線程的問題,提高應(yīng)用的性能和用戶體驗。Fiber架構(gòu)通過將渲染過程分解為多個小任務(wù),并使用優(yōu)先級調(diào)度算法來動態(tài)分配時間片,使得React可以在每個幀中執(zhí)行一部分任務(wù),從而實現(xiàn)平滑的用戶界面和更好的響應(yīng)性能。

          12. 什么是React的錯誤邊界(Error Boundary)?它的作用是什么?

          答案:React的錯誤邊界是一種用于處理組件錯誤的機制。它允許組件捕獲并處理其子組件中發(fā)生的JavaScript錯誤,以避免整個應(yīng)用崩潰。錯誤邊界的作用包括:

          捕獲并處理組件樹中的錯誤,防止錯誤導(dǎo)致整個應(yīng)用崩潰。 提供一種優(yōu)雅的方式來顯示錯誤信息或備用UI。 可以用于記錄錯誤和發(fā)送錯誤報告。

          網(wǎng)絡(luò)

          1. 什么是HTTP?它是如何工作的?

          答案:HTTP(Hypertext Transfer Protocol)是一種用于在Web上傳輸數(shù)據(jù)的協(xié)議。它使用客戶端-服務(wù)器模型,客戶端發(fā)送HTTP請求到服務(wù)器,服務(wù)器返回HTTP響應(yīng)。HTTP的工作流程如下:

          客戶端發(fā)送HTTP請求到指定的URL。 服務(wù)器接收請求并處理,然后返回HTTP響應(yīng)。 客戶端接收響應(yīng)并解析,從中獲取所需的數(shù)據(jù)。

          2. 什么是HTTPS?與HTTP有什么區(qū)別?

          答案:HTTPS(Hypertext Transfer Protocol Secure)是HTTP的安全版本,通過使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)協(xié)議對通信進行加密和身份驗證。與HTTP相比,HTTPS具有以下區(qū)別:

          數(shù)據(jù)在傳輸過程中通過加密進行保護,提供更高的安全性。 使用數(shù)字證書對服務(wù)器進行身份驗證,防止中間人攻擊。 使用默認端口443。

          3. 什么是跨域請求?它是如何解決的?

          答案:跨域請求是指在瀏覽器中向不同域名、端口或協(xié)議發(fā)送的請求。由于瀏覽器的同源策略(Same-Origin Policy)限制,跨域請求會受到限制。為了解決跨域問題,可以使用以下方法:

          JSONP(JSON with Padding):通過動態(tài)創(chuàng)建

          4. 什么是緩存?在前端中如何使用緩存來提高性能?

          答案:緩存是將數(shù)據(jù)或資源存儲在臨時存儲中,以便在后續(xù)請求中重復(fù)使用,從而提高性能和減少網(wǎng)絡(luò)流量。在前端中,可以使用以下方式來利用緩存:

          HTTP緩存:通過設(shè)置適當?shù)木彺骖^(如Cache-Control和Expires)來指示瀏覽器緩存響應(yīng)。 資源緩存:使用文件指紋或版本號來重命名靜態(tài)資源文件,以便在文件內(nèi)容變化時使瀏覽器重新下載。 數(shù)據(jù)緩存:使用內(nèi)存緩存、瀏覽器本地存儲(如localStorage)或服務(wù)端緩存(如Redis)來存儲數(shù)據(jù),避免重復(fù)請求。

          5. 什么是CDN?它的作用是什么?

          答案:CDN(Content Delivery Network)是一種分布式網(wǎng)絡(luò)架構(gòu),用于在全球各地提供高性能、低延遲的內(nèi)容傳輸服務(wù)。CDN的作用包括:

          將靜態(tài)資源(如圖片、樣式表、腳本等)緩存到離用戶更近的服務(wù)器上,提供更快的加載速度。 分發(fā)網(wǎng)絡(luò)流量,減輕源服務(wù)器的負載壓力。 提供內(nèi)容壓縮、數(shù)據(jù)壓縮和緩存等優(yōu)化技術(shù),提高用戶體驗。

          6. 什么是網(wǎng)頁加載性能優(yōu)化?可以采取哪些措施來改善網(wǎng)頁加載性能?

          答案:網(wǎng)頁加載性能優(yōu)化是指通過各種技術(shù)手段來減少網(wǎng)頁加載時間并提高用戶體驗。可以采取以下措施來改善網(wǎng)頁加載性能:

          壓縮和合并資源文件(如CSS和JavaScript),減少文件大小和請求數(shù)量。 使用圖像壓縮和適當?shù)母袷竭x擇來減小圖像文件大小。 使用瀏覽器緩存和HTTP緩存頭來緩存靜態(tài)資源。 使用懶加載延遲加載非關(guān)鍵資源,提高初始加載速度。 使用CDN(內(nèi)容分發(fā)網(wǎng)絡(luò))來分發(fā)靜態(tài)資源,減少網(wǎng)絡(luò)延遲。 優(yōu)化關(guān)鍵渲染路徑,盡早呈現(xiàn)頁面內(nèi)容。

          7. 什么是網(wǎng)頁性能監(jiān)測和分析?可以使用哪些工具來監(jiān)測和分析網(wǎng)頁性能?

          答案:網(wǎng)頁性能監(jiān)測和分析是指通過測量和收集有關(guān)網(wǎng)頁加載和交互性能的數(shù)據(jù),以便識別性能瓶頸并進行優(yōu)化。可以使用以下工具來監(jiān)測和分析網(wǎng)頁性能:

          Web性能API:瀏覽器提供的JavaScript API,可通過performance對象來收集性能數(shù)據(jù)。 Lighthouse:一種開源工具,可提供關(guān)于網(wǎng)頁性能、可訪問性和最佳實踐的綜合報告。 WebPagetest:在線工具,可測量網(wǎng)頁加載時間并提供詳細的性能分析報告。 Chrome開發(fā)者工具:瀏覽器內(nèi)置的開發(fā)者工具,提供了性能分析、網(wǎng)絡(luò)監(jiān)控和頁面審查等功能。

          8. 什么是漸進式圖像加載(Progressive Image Loading)?它如何改善網(wǎng)頁加載性能?

          答案:漸進式圖像加載是一種技術(shù),通過逐步加載圖像的模糊或低分辨率版本,然后逐漸提高圖像的清晰度,以改善網(wǎng)頁加載性能和用戶體驗。漸進式圖像加載的好處包括:

          用戶可以更快地看到頁面內(nèi)容,提高感知速度。 逐步加載圖像可以減少網(wǎng)頁整體的加載時間。 漸進式圖像加載可以提供平滑的過渡效果,避免頁面內(nèi)容突然閃爍或變化。

          9. 什么是前端資源優(yōu)先級(Resource Prioritization)?如何設(shè)置資源的優(yōu)先級?

          答案:前端資源優(yōu)先級是指為不同類型的資源分配加載優(yōu)先級,以優(yōu)化網(wǎng)頁加載性能。可以使用以下方法設(shè)置資源的優(yōu)先級:

          使用標簽來指定資源的預(yù)加載,以確保關(guān)鍵資源盡早加載。 使用標簽來指定可能在未來頁面中使用的資源,以提前加載。 使用標簽來指定要預(yù)解析的域名,以減少DNS查找時間。 使用標簽來指定要預(yù)連接的域名,以減少建立連接的時間。

          瀏覽器

          1.解釋一下瀏覽器的工作原理。

          答案:瀏覽器的工作原理包括以下幾個關(guān)鍵步驟:

          解析:瀏覽器將接收到的HTML、CSS和JavaScript代碼解析成DOM樹、CSSOM樹和JavaScript引擎可執(zhí)行的代碼。 渲染:瀏覽器使用DOM樹和CSSOM樹構(gòu)建渲染樹,然后根據(jù)渲染樹進行布局(計算元素的位置和大小)和繪制(將元素繪制到屏幕上)。 布局和繪制:瀏覽器根據(jù)渲染樹的變化進行布局和繪制,然后將最終的頁面呈現(xiàn)給用戶。 JavaScript引擎執(zhí)行:瀏覽器的JavaScript引擎解釋和執(zhí)行JavaScript代碼,并根據(jù)需要更新渲染樹和重新渲染頁面。

          2. 什么是重繪(Repaint)和重排(Reflow)?它們之間有什么區(qū)別?

          答案:重繪是指當元素的外觀(如顏色、背景等)發(fā)生改變,但布局不受影響時的更新過程。重繪不會導(dǎo)致元素的位置或大小發(fā)生變化。

          重排是指當元素的布局屬性(如寬度、高度、位置等)發(fā)生改變時的更新過程。重排會導(dǎo)致瀏覽器重新計算渲染樹和重新繪制頁面的一部分或全部。

          區(qū)別在于重繪只涉及外觀的更改,而重排涉及布局的更改。重排比重繪更消耗性能,因為它需要重新計算布局和繪制整個頁面。

          3. 什么是事件冒泡和事件捕獲?它們之間有什么區(qū)別?

          答案:事件冒泡和事件捕獲是指瀏覽器處理事件時的兩種不同的傳播方式。

          事件冒泡是指事件從最內(nèi)層的元素開始觸發(fā),然后逐級向上傳播到父元素,直到傳播到最外層的元素。

          事件捕獲是指事件從最外層的元素開始觸發(fā),然后逐級向下傳播到最內(nèi)層的元素。

          區(qū)別在于傳播方向的不同。事件冒泡是從內(nèi)向外傳播,而事件捕獲是從外向內(nèi)傳播。

          4. 解釋一下同步和異步的JavaScript代碼執(zhí)行方式。

          答案:同步代碼是按照順序執(zhí)行的代碼,每個任務(wù)必須等待前一個任務(wù)完成后才能執(zhí)行。同步代碼會阻塞后續(xù)代碼的執(zhí)行,直到當前任務(wù)完成。

          異步代碼是不按照順序執(zhí)行的代碼,它會在后臺執(zhí)行,不會阻塞后續(xù)代碼的執(zhí)行。異步代碼通常使用回調(diào)函數(shù)、Promise、async/await等方式來處理異步操作的結(jié)果。

          通過異步執(zhí)行,可以避免阻塞主線程,提高頁面的響應(yīng)性能。

          5. 什么是事件循環(huán)(Event Loop)?它在JavaScript中的作用是什么?

          答案:事件循環(huán)是JavaScript中處理異步代碼執(zhí)行的機制。它負責(zé)管理調(diào)度和執(zhí)行異步任務(wù),并將它們添加到執(zhí)行隊列中。

          在JavaScript中,事件循環(huán)的作用是確保異步任務(wù)按照正確的順序執(zhí)行,并且不會阻塞主線程。它通過不斷地從執(zhí)行隊列中取出任務(wù)并執(zhí)行,以實現(xiàn)非阻塞的異步操作。

          6. 解釋一下瀏覽器的垃圾回收機制是如何工作的。

          答案:瀏覽器的垃圾回收機制是一種自動管理內(nèi)存的機制,用于檢測和回收不再使用的對象,以釋放內(nèi)存資源。

          垃圾回收機制通過標記-清除算法實現(xiàn)。它的工作原理如下:

          標記階段:垃圾回收器會從根對象(如全局對象)開始,遞歸遍歷所有對象,并標記仍然可訪問的對象。 清除階段:垃圾回收器會掃描堆內(nèi)存,清除未被標記的對象,并回收它們所占用的內(nèi)存空間。 垃圾回收機制的目標是識別和回收不再使用的對象,以避免內(nèi)存泄漏和提高內(nèi)存利用率。

          7. 解釋一下瀏覽器的同源策略(Same-Origin Policy)及其限制。

          答案:同源策略是瀏覽器的一項安全機制,用于限制來自不同源的網(wǎng)頁之間的交互。同源是指協(xié)議、域名和端口號完全相同。

          同源策略的限制包括:

          腳本訪問限制:不同源的腳本無法直接訪問彼此的數(shù)據(jù)和操作。 DOM訪問限制:不同源的網(wǎng)頁無法通過JavaScript訪問彼此的DOM元素。 Cookie限制:不同源的網(wǎng)頁無法讀取或修改彼此的Cookie。 AJAX請求限制:不同源的網(wǎng)頁無法通過AJAX請求訪問彼此的數(shù)據(jù)。 同源策略的存在可以防止惡意網(wǎng)站獲取用戶的敏感信息或進行惡意操作。

          8. 什么是Web Workers?它們在瀏覽器中的作用是什么?

          答案:Web Workers是一種瀏覽器提供的JavaScript API,用于在后臺線程中執(zhí)行耗時的計算任務(wù),以避免阻塞主線程。

          Web Workers的作用是提高瀏覽器的響應(yīng)性能,使得在執(zhí)行復(fù)雜計算或處理大量數(shù)據(jù)時,不會影響用戶界面的流暢性。

          Web Workers通過將任務(wù)委托給后臺線程來實現(xiàn)并行處理,從而充分利用多核處理器的能力。它們可以與主線程進行通信,但不能直接訪問DOM或執(zhí)行UI相關(guān)的操作。

          9. 解釋一下瀏覽器緩存(Browser Cache)是什么,以及它的作用是什么?

          答案:瀏覽器緩存是瀏覽器在本地存儲Web頁面和資源的副本,以便在后續(xù)訪問時可以快速加載。它的作用是減少對服務(wù)器的請求次數(shù)和網(wǎng)絡(luò)傳輸量,提高頁面加載速度和用戶體驗。

          瀏覽器緩存通過在首次請求時將資源保存到本地,并在后續(xù)請求時檢查資源是否已經(jīng)存在并且沒有過期來工作。如果資源已經(jīng)存在且未過期,瀏覽器會直接從緩存中加載資源,而不是從服務(wù)器重新下載。

          10. 什么是重定向(Redirect)?它在瀏覽器中的作用是什么?

          答案:重定向是指當瀏覽器請求一個URL時,服務(wù)器返回一個不同的URL,從而將瀏覽器的請求重定向到新的URL上。

          重定向在瀏覽器中的作用是實現(xiàn)頁面的跳轉(zhuǎn)、URL的修改或資源的重定向。它可以用于多種情況,例如處理舊鏈接的跳轉(zhuǎn)、實現(xiàn)URL的規(guī)范化、處理用戶認證等。

          重定向通過在HTTP響應(yīng)中設(shè)置特定的狀態(tài)碼(如301永久重定向、302臨時重定向)和Location頭部字段來實現(xiàn)。

          11. 什么是瀏覽器存儲(Browser Storage)?它有哪些不同的存儲機制?

          答案:瀏覽器存儲是瀏覽器提供的一種在客戶端存儲數(shù)據(jù)的機制,用于在不同的網(wǎng)頁間共享數(shù)據(jù)或持久保存數(shù)據(jù)。

          瀏覽器存儲有以下不同的存儲機制:

          Cookie:小型文本文件,可以存儲少量數(shù)據(jù),并在每次HTTP請求中自動發(fā)送到服務(wù)器。 Web Storage(localStorage和sessionStorage):可以存儲較大量的數(shù)據(jù),以鍵值對的形式存儲在瀏覽器中。 IndexedDB:一種高級的客戶端數(shù)據(jù)庫,可以存儲大量結(jié)構(gòu)化數(shù)據(jù),并支持索引和事務(wù)操作。 Cache API:用于緩存網(wǎng)絡(luò)請求的響應(yīng),以便離線訪問或提高頁面加載速度。 不同的存儲機制適用于不同的需求,開發(fā)者可以根據(jù)具體情況選擇合適的存儲方式。


          原文鏈接:https://juejin.cn/post/7276407803618656295

          2023金九銀十必看前端面試題! 金九銀十黃金期來了 想要跳槽的小伙伴快來看啊

          CSS

          1. 請解釋CSS的盒模型是什么,并描述其組成部分。

          答案:CSS的盒模型是用于布局和定位元素的概念。它由內(nèi)容區(qū)域、內(nèi)邊距、邊框和外邊距組成,這些部分依次包裹在元素周圍。

          2. 解釋CSS中的選擇器及其優(yōu)先級。

          答案:CSS選擇器用于選擇要應(yīng)用樣式的HTML元素。選擇器的優(yōu)先級規(guī)則是:內(nèi)聯(lián)樣式 > ID選擇器 > 類選擇器、屬性選擇器、偽類選擇器 > 元素選擇器 > 通用選擇器。同時,使用!important可以提升樣式的優(yōu)先級。

          3. 解釋CSS中的浮動(float)是如何工作的,并提供一個示例。

          答案:浮動(float)是CSS中用于實現(xiàn)元素的左浮動或右浮動,使其脫離文檔流并環(huán)繞在其周圍的元素。例如:

          .float-example {
            float: left;
            width: 200px;
            height: 200px;
          }

          4. 解釋CSS中的定位(position)屬性及其不同的取值。

          答案:定位(position)屬性用于控制元素的定位方式。常見的取值有:static(默認,按照文檔流定位)、relative(相對定位)、absolute(絕對定位)、fixed(固定定位)和sticky(粘性定位)。

          5. 解釋CSS中的層疊順序(z-index)是如何工作的。

          答案:層疊順序(z-index)用于控制元素在垂直方向上的堆疊順序。具有較高層疊順序值的元素將顯示在較低層疊順序值的元素之上。默認情況下,層疊順序值為auto。

          6. 解釋CSS中的偽類和偽元素的區(qū)別,并給出一個示例。

          答案:偽類用于向選擇器添加特殊的狀態(tài),如:hover、:active等。偽元素用于向選擇器添加特殊的元素,如::before、::after等。例如:

          /* 偽類示例 */
          a:hover {
            color: red;
          }
          
          /* 偽元素示例 */
          p::before {
            content: "前綴";
          }

          7. 解釋CSS中的盒子模型的兩種模式:標準模式和怪異模式。

          答案:標準模式是按照W3C標準解析渲染頁面的模式。怪異模式是兼容舊版本瀏覽器的解析渲染頁面的模式。可以通過聲明來指定使用哪種模式。

          8. 解釋CSS中的BFC是什么,它的作用是什么?

          答案:BFC(塊級格式化上下文)是CSS中的一種渲染模式,它創(chuàng)建了一個獨立的渲染環(huán)境,其中的元素按照一定的規(guī)則進行布局和定位。BFC的作用包括:清除浮動、防止外邊距重疊等。

          9. 解釋CSS中的flexbox布局是什么,它的優(yōu)勢是什么?

          答案:flexbox布局是一種用于創(chuàng)建靈活的、響應(yīng)式的布局的CSS模塊。它通過flex容器和flex項目的組合來實現(xiàn)強大的布局能力。其優(yōu)勢包括簡單易用、自適應(yīng)性強、對齊和分布控制靈活等。

          10.解釋CSS中的媒體查詢是什么,它的作用是什么?

          答案:媒體查詢是CSS中的一種技術(shù),用于根據(jù)設(shè)備的特性和屬性來應(yīng)用不同的樣式。通過媒體查詢,可以根據(jù)屏幕尺寸、設(shè)備類型、分辨率等條件來優(yōu)化頁面的布局和樣式。

          JavaScript

          1. 解釋JavaScript的數(shù)據(jù)類型,并舉例說明每種類型。

          答案:JavaScript有七種數(shù)據(jù)類型:字符串(String)、數(shù)字(Number)、布爾值(Boolean)、對象(Object)、數(shù)組(Array)、空值(Null)和未定義(Undefined)。例如:

          let str = "Hello";
          let num = 10;
          let bool = true;
          let obj = { name: "John" };
          let arr = [1, 2, 3];
          let n = null;
          let undef;

          2. 解釋JavaScript中的變量提升(Hoisting)是什么。

          答案:變量提升是指在JavaScript中,變量和函數(shù)聲明會在代碼執(zhí)行之前被提升到作用域的頂部。這意味著可以在聲明之前使用變量和函數(shù)。例如:

          console.log(x); // 輸出 undefined
          var x = 5;

          3. 解釋JavaScript中的閉包(Closure)是什么,并舉例說明。

          答案:閉包是指函數(shù)可以訪問并操作其詞法作用域之外的變量。它通過在函數(shù)內(nèi)部創(chuàng)建一個內(nèi)部函數(shù),并返回該內(nèi)部函數(shù)來實現(xiàn)。例如:

          function outer() {
            let x = 10;
            function inner() {
              console.log(x);
            }
            return inner;
          }
          
          let closure = outer();
          closure(); // 輸出 10
          

          4. 解釋JavaScript中的事件冒泡(Event Bubbling)和事件捕獲(Event Capturing)。

          答案:事件冒泡是指事件從最具體的元素開始向父元素逐級觸發(fā),直到觸發(fā)到根元素。事件捕獲是指事件從根元素開始,逐級向最具體的元素觸發(fā)。可以使用addEventListener方法的第三個參數(shù)來控制是使用事件冒泡還是事件捕獲。

          5. 解釋JavaScript中的原型繼承(Prototype Inheritance)是什么。

          答案:原型繼承是JavaScript中實現(xiàn)對象之間繼承關(guān)系的一種機制。每個對象都有一個原型對象,它包含了共享的屬性和方法。當訪問對象的屬性或方法時,如果對象本身沒有,則會沿著原型鏈向上查找。可以使用Object.create()方法或設(shè)置對象的__proto__屬性來實現(xiàn)原型繼承。

          6. 解釋JavaScript中的異步編程,并提供一個異步操作的示例。

          答案:異步編程是指在代碼執(zhí)行過程中,不會阻塞后續(xù)代碼執(zhí)行的一種編程方式。常見的異步操作包括網(wǎng)絡(luò)請求、定時器等。例如:

          console.log("開始");
          setTimeout(function() {
            console.log("異步操作");
          }, 1000);
          console.log("結(jié)束");

          7. 解釋JavaScript中的閉包(Closure)是什么,并舉例說明。

          答案:閉包是指函數(shù)可以訪問并操作其詞法作用域之外的變量。它通過在函數(shù)內(nèi)部創(chuàng)建一個內(nèi)部函數(shù),并返回該內(nèi)部函數(shù)來實現(xiàn)。例如:

          function outer() {
            let x = 10;
            function inner() {
              console.log(x);
            }
            return inner;
          }
          
          let closure = outer();
          closure(); // 輸出 10

          8. 解釋JavaScript中的this關(guān)鍵字的作用和使用場景。

          答案:this關(guān)鍵字在JavaScript中表示當前執(zhí)行上下文的對象。它的具體取值根據(jù)函數(shù)的調(diào)用方式而定。在全局作用域中,this指向全局對象(瀏覽器環(huán)境中為window對象)。在函數(shù)中,this的指向取決于函數(shù)的調(diào)用方式,可以通過call、apply、bind等方法來顯式地指定this的值。

          9. 解釋JavaScript中的事件委托(Event Delegation)是什么,并提供一個使用事件委托的示例。

          答案:事件委托是指將事件處理程序綁定到父元素上,而不是直接綁定到每個子元素上。當事件觸發(fā)時,事件會冒泡到父元素,然后通過判斷事件的目標來執(zhí)行相應(yīng)的處理邏輯。這樣可以減少事件處理程序的數(shù)量,提高性能。例如:

          <ul id="list">
            <li>Item 1</li>
            <li>Item 2</li>
            <li>Item 3</li>
          </ul>
          
          <script>
          document.getElementById("list").addEventListener("click", function(event) {
            if (event.target.tagName === "LI") {
              console.log(event.target.textContent);
            }
          });
          </script>

          10. 解釋JavaScript中的模塊化編程,并提供一個使用模塊的示例。

          答案:模塊化編程是指將代碼劃分為獨立的模塊,每個模塊負責(zé)特定的功能,并通過導(dǎo)入和導(dǎo)出來實現(xiàn)模塊之間的依賴關(guān)系。ES6引入了模塊化的語法,可以使用import和export關(guān)鍵字來導(dǎo)入和導(dǎo)出模塊。例如:

          // module.js
          export function sayHello() {
            console.log("Hello!");
          }
          
          // main.js
          import { sayHello } from "./module.js";
          sayHello(); // 輸出 "Hello!"

          11. 解釋JavaScript中的事件冒泡(Event Bubbling)和事件捕獲(Event Capturing)。

          答案:事件冒泡是指當一個事件在DOM樹中觸發(fā)時,它會從最內(nèi)層的元素開始向外傳播至最外層的元素。事件捕獲是指當一個事件在DOM樹中觸發(fā)時,它會從最外層的元素開始向內(nèi)傳播至最內(nèi)層的元素。

          12. 什么是原型鏈(Prototype Chain)?如何利用原型鏈實現(xiàn)繼承?

          答案:原型鏈是JavaScript中對象之間的連接關(guān)系,每個對象都有一個指向其原型(prototype)的引用。通過原型鏈,對象可以繼承其原型對象的屬性和方法。可以使用原型鏈實現(xiàn)繼承,通過將一個對象的原型指向另一個對象,從而使得該對象可以訪問另一個對象的屬性和方法。

          13. 解釋JavaScript中的防抖(Debounce)和節(jié)流(Throttle)。

          答案:防抖和節(jié)流都是用于控制函數(shù)執(zhí)行頻率的技術(shù)。防抖指的是在某個時間段內(nèi),只執(zhí)行最后一次觸發(fā)的函數(shù)調(diào)用。節(jié)流指的是在某個時間段內(nèi),按照固定的時間間隔執(zhí)行函數(shù)調(diào)用。

          14. 什么是事件循環(huán)(Event Loop)?請解釋JavaScript中的事件循環(huán)機制。

          答案:事件循環(huán)是JavaScript中處理異步操作的機制。事件循環(huán)不斷地從任務(wù)隊列中取出任務(wù)并執(zhí)行,直到任務(wù)隊列為空。事件循環(huán)由主線程和任務(wù)隊列組成,主線程負責(zé)執(zhí)行同步任務(wù),異步任務(wù)會被放入任務(wù)隊列中,等待主線程空閑時被執(zhí)行。

          15. 解釋JavaScript中的深拷貝和淺拷貝。

          答案:深拷貝是指創(chuàng)建一個新對象,將原始對象的所有屬性和嵌套對象的屬性都復(fù)制到新對象中。淺拷貝是指創(chuàng)建一個新對象,將原始對象的屬性復(fù)制到新對象中,但嵌套對象的引用仍然是共享的。

          16. 什么是異步編程?請列舉幾種處理異步操作的方法。

          答案:異步編程是一種處理可能耗時的操作而不阻塞主線程的編程方式。常見的處理異步操作的方法有回調(diào)函數(shù)、Promise、async/await和事件監(jiān)聽等。

          17. 解釋JavaScript中的Hoisting(變量提升)。

          答案:變量提升是指在JavaScript中,變量和函數(shù)的聲明會被提升到當前作用域的頂部。這意味著可以在聲明之前使用變量和函數(shù),但它們的賦值或定義仍然在原來的位置。

          18. 什么是柯里化(Currying)?請給出一個柯里化的示例。

          答案:柯里化是一種將接受多個參數(shù)的函數(shù)轉(zhuǎn)換為接受一個參數(shù)并返回一個新函數(shù)的過程。示例:

          function add(a) {
            return function(b) {
              return a + b;
            }
          }
          
          var add5 = add(5);
          console.log(add5(3)); // 輸出:8

          19. 解釋JavaScript中的嚴格模式(Strict Mode)。

          答案:嚴格模式是一種JavaScript的執(zhí)行模式,它提供了更嚴格的語法和錯誤檢查。在嚴格模式下,一些不安全或不推薦的語法會被禁用,同時會引入一些新的特性,如變量必須先聲明才能使用、禁止使用this指向全局對象等。

          TypeScript

          1. 解釋TypeScript和JavaScript之間的關(guān)系。

          答案:TypeScript是JavaScript的超集,它添加了靜態(tài)類型和其他一些特性。TypeScript代碼可以編譯成JavaScript代碼,因此可以在任何支持JavaScript的環(huán)境中運行。

          2. TypeScript中的類型注解是什么?如何使用類型注解?

          答案:類型注解是指在變量、函數(shù)參數(shù)、函數(shù)返回值等地方顯式地聲明類型信息。可以使用冒號(:)后跟類型來添加類型注解。例如:

          let num: number = 10;
          
          function add(a: number, b: number): number {
            return a + b;
          }

          3. TypeScript中的接口是什么?如何定義和使用接口?

          答案:接口是一種用于定義對象的結(jié)構(gòu)和類型的語法。可以使用interface關(guān)鍵字來定義接口。例如:

          interface Person {
            name: string;
            age: number;
          }
          
          function greet(person: Person) {
            console.log(`Hello, ${person.name}!`);
          }
          
          let john: Person = { name: "John", age: 25 };
          greet(john); // 輸出 "Hello, John!"

          4. TypeScript中的類是什么?如何定義和使用類?

          答案:類是一種用于創(chuàng)建對象的藍圖,它包含屬性和方法。可以使用class關(guān)鍵字來定義類。例如:

          class Person {
            name: string;
            age: number;
          
            constructor(name: string, age: number) {
              this.name = name;
              this.age = age;
            }
          
            greet() {
              console.log(`Hello, ${this.name}!`);
            }
          }
          
          let john = new Person("John", 25);
          john.greet(); // 輸出 "Hello, John!"

          5. TypeScript中的泛型是什么?如何使用泛型?

          答案:泛型是一種用于創(chuàng)建可重用代碼的工具,它允許在定義函數(shù)、類或接口時使用占位符類型。可以使用尖括號(<>)來指定泛型類型。例如:

          function identity<T>(value: T): T {
            return value;
          }
          
          let result = identity<string>("Hello");
          console.log(result); // 輸出 "Hello"

          6. TypeScript中的枚舉是什么?如何定義和使用枚舉?

          答案:枚舉是一種用于定義命名常量集合的語法。可以使用enum關(guān)鍵字來定義枚舉。例如:

          enum Color {
            Red,
            Green,
            Blue,
          }
          
          let color: Color = Color.Green;
          console.log(color); // 輸出 1

          7. TypeScript中的模塊是什么?如何導(dǎo)出和導(dǎo)入模塊?

          答案:模塊是用于組織和封裝代碼的單元。可以使用export關(guān)鍵字將模塊中的變量、函數(shù)、類等導(dǎo)出,以便其他模塊可以使用。可以使用import關(guān)鍵字來導(dǎo)入其他模塊的導(dǎo)出。例如:

          // module.ts
          export function greet(name: string) {
            console.log(`Hello, ${name}!`);
          }
          
          // main.ts
          import { greet } from "./module";
          greet("John"); // 輸出 "Hello, John!"

          8. TypeScript中的類型推斷是什么?如何使用類型推斷?

          答案:類型推斷是指TypeScript根據(jù)上下文自動推斷變量的類型,而無需顯式地添加類型注解。例如:

          let num = 10; // 推斷為 number 類型
          let str = "Hello"; // 推斷為 string 類型

          9. TypeScript中的命名空間是什么?如何定義和使用命名空間?

          答案:命名空間是一種用于組織和封裝代碼的機制,它避免了全局命名沖突。可以使用namespace關(guān)鍵字來定義命名空間。例如:

          namespace MyNamespace {
            export function greet(name: string) {
              console.log(`Hello, ${name}!`);
            }
          }
          
          MyNamespace.greet("John"); // 輸出 "Hello, John!"

          10. TypeScript中的類型別名是什么?如何定義和使用類型別名?

          答案:類型別名是給類型起一個別名,以便在代碼中更方便地引用。可以使用type關(guān)鍵字來定義類型別名。例如:

          type Point = { x: number; y: number };
          
          function printPoint(point: Point) {
            console.log(`(${point.x}, ${point.y})`);
          }
          
          let p: Point = { x: 1, y: 2 };
          printPoint(p); // 輸出 "(1, 2)"

          VUE2

          1. Vue.js是什么?它有哪些特點?

          答案:Vue.js是一個用于構(gòu)建用戶界面的JavaScript框架。它具有以下特點:

          響應(yīng)式數(shù)據(jù)綁定:通過使用Vue的數(shù)據(jù)綁定語法,可以實現(xiàn)數(shù)據(jù)的自動更新。 組件化開發(fā):Vue允許將頁面劃分為獨立的組件,提高了代碼的可維護性和復(fù)用性。 虛擬DOM:Vue使用虛擬DOM來跟蹤頁面上的變化,并高效地更新實際的DOM。 指令系統(tǒng):Vue提供了豐富的內(nèi)置指令,用于處理常見的DOM操作和邏輯控制。 生態(tài)系統(tǒng):Vue擁有龐大的生態(tài)系統(tǒng),包括插件、工具和第三方庫,可以滿足各種開發(fā)需求。

          2. Vue中的雙向數(shù)據(jù)綁定是如何實現(xiàn)的?

          答案:Vue中的雙向數(shù)據(jù)綁定是通過v-model指令實現(xiàn)的。v-model可以在表單元素(如、、)上創(chuàng)建雙向數(shù)據(jù)綁定。當用戶輸入改變表單元素的值時,數(shù)據(jù)模型會自動更新;反之,當數(shù)據(jù)模型的值改變時,表單元素也會自動更新。

          3. Vue中的生命周期鉤子有哪些?它們的執(zhí)行順序是怎樣的?

          答案:Vue中的生命周期鉤子包括beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy和destroyed。它們的執(zhí)行順序如下:

          beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy destroyed

          4. Vue中的計算屬性和監(jiān)聽器有什么區(qū)別?

          答案:計算屬性是基于依賴的屬性,它根據(jù)其依賴的數(shù)據(jù)動態(tài)計算得出值。計算屬性具有緩存機制,只有在依賴的數(shù)據(jù)發(fā)生變化時才會重新計算。監(jiān)聽器是用于監(jiān)聽數(shù)據(jù)的變化并執(zhí)行相應(yīng)的操作。當數(shù)據(jù)發(fā)生變化時,監(jiān)聽器會立即執(zhí)行指定的回調(diào)函數(shù)。

          5. Vue中的組件通信有哪些方式?

          答案:Vue中的組件通信方式包括:

          父子組件通信:通過props向子組件傳遞數(shù)據(jù),子組件通過事件向父組件發(fā)送消息。 子父組件通信:子組件通過$emit觸發(fā)事件,父組件通過監(jiān)聽事件并響應(yīng)。 兄弟組件通信:通過共享的父組件來傳遞數(shù)據(jù)或通過事件總線(Event Bus)進行通信。 跨級組件通信:通過provide和inject來在祖先組件中提供數(shù)據(jù),然后在后代組件中使用。

          6. Vue中的路由是如何實現(xiàn)的?

          答案:Vue中的路由是通過Vue Router實現(xiàn)的。Vue Router是Vue.js官方提供的路由管理器,它允許開發(fā)者在Vue應(yīng)用中實現(xiàn)單頁面應(yīng)用(SPA)。Vue Router通過配置路由映射關(guān)系,將URL路徑與組件進行關(guān)聯(lián),并提供導(dǎo)航功能,使用戶可以在不刷新頁面的情況下切換視圖。

          7. Vue中的指令有哪些?舉例說明它們的用法。

          答案:Vue中常用的指令包括:

          v-if:根據(jù)表達式的值條件性地渲染元素。 v-for:根據(jù)數(shù)組或?qū)ο蟮臄?shù)據(jù)進行循環(huán)渲染。 v-bind:用于動態(tài)綁定屬性或響應(yīng)式地更新屬性。 v-on:用于監(jiān)聽DOM事件并執(zhí)行相應(yīng)的方法。 v-model:用于在表單元素上實現(xiàn)雙向數(shù)據(jù)綁定。 例如:

          <div v-if="show">顯示內(nèi)容</div>
          
          <ul>
            <li v-for="item in items" :key="item.id">{{ item.name }}</li>
          </ul>
          
          <img v-bind:src="imageUrl">
          
          <button v-on:click="handleClick">點擊按鈕</button>
          
          <input v-model="message">

          8. Vue中的watch和computed有什么區(qū)別?

          答案:watch和computed都可以用于監(jiān)聽數(shù)據(jù)的變化,但它們的用法和實現(xiàn)方式略有不同。watch用于監(jiān)聽指定的數(shù)據(jù)變化,并在數(shù)據(jù)變化時執(zhí)行相應(yīng)的操作。computed用于根據(jù)依賴的數(shù)據(jù)動態(tài)計算得出一個新的值,并將該值緩存起來,只有在依賴的數(shù)據(jù)發(fā)生變化時才會重新計算。

          9. Vue中的mixin是什么?它有什么作用?

          答案:Mixin是一種用于在多個組件之間共享代碼的方式。Mixin可以包含組件選項(如數(shù)據(jù)、方法、生命周期鉤子等),并將其合并到使用Mixin的組件中。這樣可以實現(xiàn)代碼的復(fù)用和組件的擴展,減少重復(fù)編寫相似代碼的工作。

          10. Vue中的keep-alive是什么?它有什么作用?

          答案:是Vue中的一個內(nèi)置組件,用于緩存動態(tài)組件。當組件包裹在中時,組件的狀態(tài)將被保留,包括它的實例、狀態(tài)和DOM結(jié)構(gòu)。這樣可以避免在組件切換時重復(fù)創(chuàng)建和銷毀組件,提高性能和用戶體驗。

          11. 請解釋Vue.js中的依賴注入(Dependency Injection)是什么?它在Vue中的應(yīng)用場景是什么?

          答案:依賴注入是一種設(shè)計模式,用于將依賴關(guān)系從一個組件傳遞到另一個組件。在Vue中,依賴注入通過provide和inject選項實現(xiàn)。父組件通過provide提供數(shù)據(jù),然后子組件通過inject注入這些數(shù)據(jù)。它在跨多個層級的組件通信中非常有用。

          12. Vue.js中的渲染函數(shù)(Render Function)是什么?它與模板(Template)有什么區(qū)別?

          答案:渲染函數(shù)是一種用JavaScript代碼編寫組件的方式,它可以動態(tài)地生成虛擬DOM。與模板相比,渲染函數(shù)提供了更大的靈活性和控制力,可以處理更復(fù)雜的邏輯和動態(tài)渲染需求。

          13. Vue.js中的插槽(Slot)是什么?請?zhí)峁┮粋€具有命名插槽和作用域插槽的示例。

          答案:插槽是一種用于在組件中擴展內(nèi)容的機制。命名插槽允許父組件向子組件插入具有特定名稱的內(nèi)容,而作用域插槽允許子組件將數(shù)據(jù)傳遞給父組件。示例:

          <!-- 父組件 -->
          <template>
            <div>
              <slot name="header"></slot>
              <slot :data="data"></slot>
            </div>
          </template>
          
          <!-- 子組件 -->
          <template>
            <div>
              <slot name="header">默認標題</slot>
              <slot :data="computedData">{{ computedData }}</slot>
            </div>
          </template>

          14. Vue.js中的動畫系統(tǒng)是如何工作的?請?zhí)峁┮粋€簡單的動畫示例。

          答案:Vue.js的動畫系統(tǒng)通過CSS過渡和動畫類實現(xiàn)。通過在元素上添加過渡類或動畫類,可以觸發(fā)相應(yīng)的過渡效果或動畫效果。示例:

          <transition name="fade">
            <div v-if="show">顯示內(nèi)容</div>
          </transition>
          
          <!-- CSS樣式 -->
          <style>
          .fade-enter-active, .fade-leave-active {
            transition: opacity 0.5s;
          }
          .fade-enter, .fade-leave-to {
            opacity: 0;
          }
          </style>

          15. Vue.js中的錯誤處理機制是什么?如何捕獲和處理Vue組件中的錯誤?

          答案:Vue.js提供了全局的錯誤處理機制和組件級別的錯誤處理機制。全局錯誤處理可以通過errorCaptured鉤子函數(shù)捕獲和處理錯誤。組件級別的錯誤處理可以通過errorCaptured鉤子函數(shù)或errorHandler選項捕獲和處理錯誤。

          16. Vue.js中的服務(wù)端渲染(SSR)是什么?它有哪些優(yōu)勢和限制?

          答案:服務(wù)端渲染是指在服務(wù)器上生成HTML內(nèi)容并將其發(fā)送到瀏覽器進行渲染的過程。Vue.js可以進行服務(wù)端渲染,提供更好的首次加載性能和SEO優(yōu)化。然而,服務(wù)端渲染也帶來了一些限制,如增加了服務(wù)器負載和開發(fā)復(fù)雜性。

          17. Vue.js中的響應(yīng)式數(shù)組有哪些限制?如何解決這些限制?

          答案:Vue.js的響應(yīng)式系統(tǒng)對于數(shù)組的變異方法(如push、pop、splice等)是無法追蹤的。為了解決這個限制,Vue提供了一些特殊的方法,如Vue.set、vm.$set和Array.prototype.splice。這些方法可以用于更新數(shù)組并保持響應(yīng)式。

          18. Vue.js中的性能優(yōu)化有哪些常見的技巧?

          答案:常見的Vue.js性能優(yōu)化技巧包括:

          使用v-if和v-for時注意避免不必要的渲染。 合理使用computed屬性和watch監(jiān)聽器。 使用keep-alive組件緩存組件狀態(tài)。 使用異步組件進行按需加載。 避免在模板中使用復(fù)雜的表達式。 使用key屬性管理組件和元素的復(fù)用。 合理使用懶加載和分割代碼。

          19. Vue.js中的路由導(dǎo)航守衛(wèi)有哪些?它們的執(zhí)行順序是怎樣的?

          答案:Vue.js中的路由導(dǎo)航守衛(wèi)包括全局前置守衛(wèi)、全局解析守衛(wèi)、全局后置守衛(wèi)、路由獨享守衛(wèi)和組件內(nèi)守衛(wèi)。它們的執(zhí)行順序如下:

          全局前置守衛(wèi)(beforeEach) 路由獨享守衛(wèi)(beforeEnter) 解析守衛(wèi)(beforeResolve) 組件內(nèi)守衛(wèi)(beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave) 全局后置守衛(wèi)(afterEach)

          20. Vue.js中的單元測試是如何進行的?請?zhí)峁┮粋€簡單的單元測試示例。

          答案:Vue.js的單元測試可以使用工具如Jest或Mocha進行。示例:

          // 組件代碼
          // MyComponent.vue
          <template>
            <div class="my-component">
              <span>{{ message }}</span>
              <button @click="increment">增加</button>
            </div>
          </template>
          
          <script>
          export default {
            data() {
              return {
                message: 'Hello',
                count: 0
              }
            },
            methods: {
              increment() {
                this.count++
              }
            }
          }
          </script>
          
          // 單元測試代碼
          // MyComponent.spec.js
          import { shallowMount } from '@vue/test-utils'
          import MyComponent from './MyComponent.vue'
          
          describe('MyComponent', () => {
            it('renders message correctly', () => {
              const wrapper = shallowMount(MyComponent)
              expect(wrapper.find('span').text()).toBe('Hello')
            })
          
            it('increments count when button is clicked', () => {
              const wrapper = shallowMount(MyComponent)
              wrapper.find('button').trigger('click')
              expect(wrapper.vm.count).toBe(1)
            })
          })

          VUE3

          1. Vue.js 3中的Composition API是什么?它與Options API有什么區(qū)別?

          答案:Composition API是Vue.js 3中引入的一種新的組織組件邏輯的方式。它允許開發(fā)者通過函數(shù)的方式組織和重用邏輯,而不是通過選項對象。相比之下,Options API是Vue.js 2中常用的組織組件邏輯的方式,通過選項對象中的屬性來定義組件的數(shù)據(jù)、方法等。

          2. Vue.js 3中的Teleport是什么?請給出一個Teleport的示例。

          答案:Teleport是Vue.js 3中引入的一種機制,用于將組件的內(nèi)容渲染到DOM樹中的任意位置。示例:

          <template>
            <div>
              <button @click="showModal = true">打開模態(tài)框</button>
              <teleport to="body">
                <modal v-if="showModal" @close="showModal = false">模態(tài)框內(nèi)容</modal>
              </teleport>
            </div>
          </template>

          3. Vue.js 3中的響應(yīng)式系統(tǒng)是如何工作的?它與Vue.js 2中的響應(yīng)式系統(tǒng)有什么區(qū)別?

          答案:Vue.js 3中的響應(yīng)式系統(tǒng)使用了Proxy對象來實現(xiàn)。與Vue.js 2中的響應(yīng)式系統(tǒng)相比,Vue.js 3的響應(yīng)式系統(tǒng)具有更好的性能和更細粒度的追蹤,能夠更準確地檢測到數(shù)據(jù)的變化,并且支持嵌套的響應(yīng)式數(shù)據(jù)。

          4. Vue.js 3中的Suspense是什么?它的作用是什么?

          答案:Suspense是Vue.js 3中引入的一種機制,用于處理異步組件的加載狀態(tài)。它可以在異步組件加載完成之前顯示一個占位符,并在加載完成后渲染異步組件的內(nèi)容。這樣可以更好地處理異步組件的加載過程,提供更好的用戶體驗。

          5. Vue.js 3中的provide和inject有什么作用?請給出一個provide和inject的示例。

          答案:provide和inject用于實現(xiàn)組件之間的依賴注入。通過在父組件中使用provide提供數(shù)據(jù),然后在子組件中使用inject注入這些數(shù)據(jù)。示例:

          // 父組件
          const Parent = {
            provide: {
              message: 'Hello'
            },
            // ...
          }
          
          // 子組件
          const Child = {
            inject: ['message'],
            created() {
              console.log(this.message); // 輸出:Hello
            },
            // ...
          }

          6. Vue.js 3中的動畫系統(tǒng)有哪些改進?請列舉幾個改進之處。

          答案:Vue.js 3中的動畫系統(tǒng)相比Vue.js 2有以下改進之處:

          更好的性能:Vue.js 3的動畫系統(tǒng)使用了更高效的動畫引擎,提供了更好的性能。 更簡潔的語法:Vue.js 3的動畫系統(tǒng)使用了更簡潔的語法,使得動畫的定義和使用更加直觀和方便。 支持更多的動畫特性:Vue.js 3的動畫系統(tǒng)支持更多的動畫特性,如交互式動畫和更復(fù)雜的動畫效果。 Vue.js 3中的靜態(tài)提升(Static Tree Hoisting)是什么?它有什么優(yōu)勢? 答案:靜態(tài)提升是Vue.js 3中的一項優(yōu)化技術(shù),通過在編譯階段將靜態(tài)節(jié)點提升為常量,從而減少了運行時的開銷。這項優(yōu)化技術(shù)可以提高組件的渲染性能,并減少生成的代碼體積。

          7. Vue.js 3中的Fragment是什么?它的作用是什么?

          答案:Fragment是Vue.js 3中引入的一種機制,用于在組件中返回多個根節(jié)點。在Vue.js 2中,組件的模板只能有一個 Vue.js 3中的Composition API中的ref和reactive有什么區(qū)別?什么時候使用哪個? 答案:ref用于創(chuàng)建一個響應(yīng)式的基本數(shù)據(jù)類型,而reactive用于創(chuàng)建一個響應(yīng)式的對象。當需要創(chuàng)建一個簡單的響應(yīng)式數(shù)據(jù)時,可以使用ref,當需要創(chuàng)建一個包含多個屬性的響應(yīng)式對象時,可以使用reactive。

          8. Vue.js 3中的watchEffect和watch有什么區(qū)別?什么時候使用哪個?

          答案:watchEffect用于監(jiān)聽響應(yīng)式數(shù)據(jù)的變化,并在回調(diào)函數(shù)中執(zhí)行相應(yīng)的操作。它會自動追蹤依賴,并在依賴變化時重新運行回調(diào)函數(shù)。watch用于監(jiān)聽指定的響應(yīng)式數(shù)據(jù),并在其變化時執(zhí)行相應(yīng)的操作。它可以精確地指定要監(jiān)聽的數(shù)據(jù),并提供更多的配置選項。一般來說,如果只需要監(jiān)聽一個響應(yīng)式數(shù)據(jù)的變化并執(zhí)行相應(yīng)操作,可以使用watchEffect;如果需要更細粒度的控制,可以使用watch。

          9. Vue.js 3中的v-model指令在使用時有哪些注意事項?

          答案:在使用v-model指令時,有以下注意事項:

          v-model指令必須與一個表單元素一起使用,如、、等。 當使用自定義組件時,組件內(nèi)部必須實現(xiàn)modelValue屬性和update:modelValue事件,以支持v-model的雙向綁定。 可以使用.lazy修飾符實現(xiàn)在輸入框失去焦點時更新數(shù)據(jù)。 可以使用.trim修飾符自動去除輸入框內(nèi)容的首尾空格。 可以使用.number修飾符將輸入框的值轉(zhuǎn)換為數(shù)字類型。

          10. Vue.js 3中的provide和inject是否支持響應(yīng)式數(shù)據(jù)?

          答案:默認情況下,provide和inject不支持響應(yīng)式數(shù)據(jù)。如果需要在provide中提供一個響應(yīng)式數(shù)據(jù),可以使用ref或reactive將數(shù)據(jù)包裝起來。然后在inject中使用toRefs或toRef將數(shù)據(jù)解構(gòu)出來,以獲取響應(yīng)式的引用。

          11. Vue.js 3中的nextTick方法有什么作用?在什么情況下使用它?

          答案:nextTick方法用于在下次DOM更新循環(huán)結(jié)束之后執(zhí)行回調(diào)函數(shù)。它可以用來確保在更新DOM后執(zhí)行某些操作,如操作更新后的DOM元素或獲取更新后的計算屬性的值。通常在需要等待DOM更新完成后進行操作的情況下使用nextTick。

          12. Vue.js 3中的和組件有什么區(qū)別?

          答案:組件用于將組件的內(nèi)容渲染到DOM樹中的任意位置,而組件用于在組件進入或離開DOM樹時應(yīng)用過渡效果。主要用于組件的位置移動,而主要用于組件的顯示和隱藏過渡。

          13. Vue.js 3中的v-for指令中的key屬性有什么作用?為什么要使用它?

          答案:v-for指令中的key屬性用于給每個迭代項設(shè)置一個唯一的標識符。它的作用是幫助Vue.js跟蹤每個節(jié)點的身份,以便在數(shù)據(jù)發(fā)生變化時高效地更新DOM。使用key屬性可以避免出現(xiàn)錯誤的節(jié)點更新或重新排序的問題。

          React

          1. 什么是React?它的核心概念是什么?

          答案:React是一個用于構(gòu)建用戶界面的JavaScript庫。它的核心概念是組件化和聲明式編程。React將用戶界面拆分為獨立的可重用組件,并使用聲明式語法描述組件的狀態(tài)和UI的關(guān)系,使得構(gòu)建復(fù)雜的UI變得簡單和可維護。

          2. 什么是JSX?它與HTML有什么區(qū)別?

          答案:JSX是一種JavaScript的語法擴展,用于在React中描述UI的結(jié)構(gòu)。它類似于HTML,但有一些區(qū)別:

          3. 什么是React組件?它們有哪兩種類型?

          答案:React組件是構(gòu)建用戶界面的獨立單元。React組件有兩種類型:

          函數(shù)組件:使用函數(shù)來定義組件,接收props作為參數(shù),并返回一個React元素。 類組件:使用ES6類來定義組件,繼承自React.Component類,通過render方法返回一個React元素。

          4. 什么是狀態(tài)(state)和屬性(props)?它們之間有什么區(qū)別?

          答案:狀態(tài)(state)是組件自身管理的數(shù)據(jù),可以通過setState方法來更新。屬性(props)是從父組件傳遞給子組件的數(shù)據(jù),子組件無法直接修改props,只能通過父組件的更新來改變props。

          區(qū)別:

          狀態(tài)(state)是組件內(nèi)部的數(shù)據(jù),可以在組件中自由修改和管理。 屬性(props)是從父組件傳遞給子組件的數(shù)據(jù),子組件無法直接修改,只能接收和使用。

          5. 什么是React生命周期方法?列舉一些常用的生命周期方法。

          答案:React生命周期方法是在組件不同階段執(zhí)行的特定方法。以下是一些常用的React生命周期方法:

          componentDidMount:組件掛載后立即調(diào)用。 componentDidUpdate:組件更新后調(diào)用。 componentWillUnmount:組件卸載前調(diào)用。 shouldComponentUpdate:決定組件是否需要重新渲染。 getDerivedStateFromProps:根據(jù)props的變化來更新狀態(tài)。

          6. 什么是React Hooks?它們的作用是什么?

          答案:React Hooks是React 16.8版本引入的一種特性,用于在函數(shù)組件中使用狀態(tài)和其他React特性。Hooks提供了一種無需編寫類組件的方式來管理狀態(tài)和處理副作用,使得函數(shù)組件具有類組件的能力。

          7. 什么是React Router?它的作用是什么?

          答案:React Router是React中用于處理路由的庫。它提供了一種在單頁面應(yīng)用中實現(xiàn)導(dǎo)航和路由功能的方式。React Router可以幫助開發(fā)者實現(xiàn)頁面之間的切換、URL參數(shù)的傳遞、嵌套路由等功能。

          8. 什么是React Context?它的作用是什么?

          答案:React Context是一種用于在組件樹中共享數(shù)據(jù)的機制。它可以避免通過props一層層傳遞數(shù)據(jù),使得跨組件的數(shù)據(jù)共享變得更加簡單和高效。React Context提供了一個Provider和Consumer組件,用于提供和消費共享的數(shù)據(jù)。

          9. 什么是React的協(xié)調(diào)(Reconciliation)過程?它是如何工作的?

          答案:React的協(xié)調(diào)過程是指React在進行組件更新時,通過比較新舊虛擬DOM樹的差異,僅對需要更新的部分進行實際的DOM操作。協(xié)調(diào)過程的工作方式如下:

          React會逐層比較新舊虛擬DOM樹的節(jié)點,并找出差異。 對于每個差異,React會生成相應(yīng)的DOM操作指令,如插入、更新或刪除節(jié)點。 React會將所有的DOM操作指令批量執(zhí)行,以減少對真實DOM的操作次數(shù)。

          10. 什么是React的事件合成(SyntheticEvent)?它的作用是什么?

          答案:React的事件合成是一種在React中處理事件的機制。它是React為了提高性能和跨瀏覽器兼容性而實現(xiàn)的一種事件系統(tǒng)。事件合成的作用包括:

          提供了一種統(tǒng)一的方式來處理事件,無需考慮瀏覽器兼容性。 可以通過事件委托的方式將事件處理程序綁定到父組件,提高性能。 可以訪問原生事件對象的屬性和方法。

          11. 什么是React的Fiber架構(gòu)?它解決了什么問題?

          答案:React的Fiber架構(gòu)是React 16版本引入的一種新的協(xié)調(diào)算法和架構(gòu)。它旨在解決長時間渲染阻塞主線程的問題,提高應(yīng)用的性能和用戶體驗。Fiber架構(gòu)通過將渲染過程分解為多個小任務(wù),并使用優(yōu)先級調(diào)度算法來動態(tài)分配時間片,使得React可以在每個幀中執(zhí)行一部分任務(wù),從而實現(xiàn)平滑的用戶界面和更好的響應(yīng)性能。

          12. 什么是React的錯誤邊界(Error Boundary)?它的作用是什么?

          答案:React的錯誤邊界是一種用于處理組件錯誤的機制。它允許組件捕獲并處理其子組件中發(fā)生的JavaScript錯誤,以避免整個應(yīng)用崩潰。錯誤邊界的作用包括:

          捕獲并處理組件樹中的錯誤,防止錯誤導(dǎo)致整個應(yīng)用崩潰。 提供一種優(yōu)雅的方式來顯示錯誤信息或備用UI。 可以用于記錄錯誤和發(fā)送錯誤報告。

          網(wǎng)絡(luò)

          1. 什么是HTTP?它是如何工作的?

          答案:HTTP(Hypertext Transfer Protocol)是一種用于在Web上傳輸數(shù)據(jù)的協(xié)議。它使用客戶端-服務(wù)器模型,客戶端發(fā)送HTTP請求到服務(wù)器,服務(wù)器返回HTTP響應(yīng)。HTTP的工作流程如下:

          客戶端發(fā)送HTTP請求到指定的URL。 服務(wù)器接收請求并處理,然后返回HTTP響應(yīng)。 客戶端接收響應(yīng)并解析,從中獲取所需的數(shù)據(jù)。

          2. 什么是HTTPS?與HTTP有什么區(qū)別?

          答案:HTTPS(Hypertext Transfer Protocol Secure)是HTTP的安全版本,通過使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)協(xié)議對通信進行加密和身份驗證。與HTTP相比,HTTPS具有以下區(qū)別:

          數(shù)據(jù)在傳輸過程中通過加密進行保護,提供更高的安全性。 使用數(shù)字證書對服務(wù)器進行身份驗證,防止中間人攻擊。 使用默認端口443。

          3. 什么是跨域請求?它是如何解決的?

          答案:跨域請求是指在瀏覽器中向不同域名、端口或協(xié)議發(fā)送的請求。由于瀏覽器的同源策略(Same-Origin Policy)限制,跨域請求會受到限制。為了解決跨域問題,可以使用以下方法:

          JSONP(JSON with Padding):通過動態(tài)創(chuàng)建

          4. 什么是緩存?在前端中如何使用緩存來提高性能?

          答案:緩存是將數(shù)據(jù)或資源存儲在臨時存儲中,以便在后續(xù)請求中重復(fù)使用,從而提高性能和減少網(wǎng)絡(luò)流量。在前端中,可以使用以下方式來利用緩存:

          HTTP緩存:通過設(shè)置適當?shù)木彺骖^(如Cache-Control和Expires)來指示瀏覽器緩存響應(yīng)。 資源緩存:使用文件指紋或版本號來重命名靜態(tài)資源文件,以便在文件內(nèi)容變化時使瀏覽器重新下載。 數(shù)據(jù)緩存:使用內(nèi)存緩存、瀏覽器本地存儲(如localStorage)或服務(wù)端緩存(如Redis)來存儲數(shù)據(jù),避免重復(fù)請求。

          5. 什么是CDN?它的作用是什么?

          答案:CDN(Content Delivery Network)是一種分布式網(wǎng)絡(luò)架構(gòu),用于在全球各地提供高性能、低延遲的內(nèi)容傳輸服務(wù)。CDN的作用包括:

          將靜態(tài)資源(如圖片、樣式表、腳本等)緩存到離用戶更近的服務(wù)器上,提供更快的加載速度。 分發(fā)網(wǎng)絡(luò)流量,減輕源服務(wù)器的負載壓力。 提供內(nèi)容壓縮、數(shù)據(jù)壓縮和緩存等優(yōu)化技術(shù),提高用戶體驗。

          6. 什么是網(wǎng)頁加載性能優(yōu)化?可以采取哪些措施來改善網(wǎng)頁加載性能?

          答案:網(wǎng)頁加載性能優(yōu)化是指通過各種技術(shù)手段來減少網(wǎng)頁加載時間并提高用戶體驗。可以采取以下措施來改善網(wǎng)頁加載性能:

          壓縮和合并資源文件(如CSS和JavaScript),減少文件大小和請求數(shù)量。 使用圖像壓縮和適當?shù)母袷竭x擇來減小圖像文件大小。 使用瀏覽器緩存和HTTP緩存頭來緩存靜態(tài)資源。 使用懶加載延遲加載非關(guān)鍵資源,提高初始加載速度。 使用CDN(內(nèi)容分發(fā)網(wǎng)絡(luò))來分發(fā)靜態(tài)資源,減少網(wǎng)絡(luò)延遲。 優(yōu)化關(guān)鍵渲染路徑,盡早呈現(xiàn)頁面內(nèi)容。

          7. 什么是網(wǎng)頁性能監(jiān)測和分析?可以使用哪些工具來監(jiān)測和分析網(wǎng)頁性能?

          答案:網(wǎng)頁性能監(jiān)測和分析是指通過測量和收集有關(guān)網(wǎng)頁加載和交互性能的數(shù)據(jù),以便識別性能瓶頸并進行優(yōu)化。可以使用以下工具來監(jiān)測和分析網(wǎng)頁性能:

          Web性能API:瀏覽器提供的JavaScript API,可通過performance對象來收集性能數(shù)據(jù)。 Lighthouse:一種開源工具,可提供關(guān)于網(wǎng)頁性能、可訪問性和最佳實踐的綜合報告。 WebPagetest:在線工具,可測量網(wǎng)頁加載時間并提供詳細的性能分析報告。 Chrome開發(fā)者工具:瀏覽器內(nèi)置的開發(fā)者工具,提供了性能分析、網(wǎng)絡(luò)監(jiān)控和頁面審查等功能。

          8. 什么是漸進式圖像加載(Progressive Image Loading)?它如何改善網(wǎng)頁加載性能?

          答案:漸進式圖像加載是一種技術(shù),通過逐步加載圖像的模糊或低分辨率版本,然后逐漸提高圖像的清晰度,以改善網(wǎng)頁加載性能和用戶體驗。漸進式圖像加載的好處包括:

          用戶可以更快地看到頁面內(nèi)容,提高感知速度。 逐步加載圖像可以減少網(wǎng)頁整體的加載時間。 漸進式圖像加載可以提供平滑的過渡效果,避免頁面內(nèi)容突然閃爍或變化。

          9. 什么是前端資源優(yōu)先級(Resource Prioritization)?如何設(shè)置資源的優(yōu)先級?

          答案:前端資源優(yōu)先級是指為不同類型的資源分配加載優(yōu)先級,以優(yōu)化網(wǎng)頁加載性能。可以使用以下方法設(shè)置資源的優(yōu)先級:

          使用標簽來指定資源的預(yù)加載,以確保關(guān)鍵資源盡早加載。 使用標簽來指定可能在未來頁面中使用的資源,以提前加載。 使用標簽來指定要預(yù)解析的域名,以減少DNS查找時間。 使用標簽來指定要預(yù)連接的域名,以減少建立連接的時間。

          瀏覽器

          1.解釋一下瀏覽器的工作原理。

          答案:瀏覽器的工作原理包括以下幾個關(guān)鍵步驟:

          解析:瀏覽器將接收到的HTML、CSS和JavaScript代碼解析成DOM樹、CSSOM樹和JavaScript引擎可執(zhí)行的代碼。 渲染:瀏覽器使用DOM樹和CSSOM樹構(gòu)建渲染樹,然后根據(jù)渲染樹進行布局(計算元素的位置和大小)和繪制(將元素繪制到屏幕上)。 布局和繪制:瀏覽器根據(jù)渲染樹的變化進行布局和繪制,然后將最終的頁面呈現(xiàn)給用戶。 JavaScript引擎執(zhí)行:瀏覽器的JavaScript引擎解釋和執(zhí)行JavaScript代碼,并根據(jù)需要更新渲染樹和重新渲染頁面。

          2. 什么是重繪(Repaint)和重排(Reflow)?它們之間有什么區(qū)別?

          答案:重繪是指當元素的外觀(如顏色、背景等)發(fā)生改變,但布局不受影響時的更新過程。重繪不會導(dǎo)致元素的位置或大小發(fā)生變化。

          重排是指當元素的布局屬性(如寬度、高度、位置等)發(fā)生改變時的更新過程。重排會導(dǎo)致瀏覽器重新計算渲染樹和重新繪制頁面的一部分或全部。

          區(qū)別在于重繪只涉及外觀的更改,而重排涉及布局的更改。重排比重繪更消耗性能,因為它需要重新計算布局和繪制整個頁面。

          3. 什么是事件冒泡和事件捕獲?它們之間有什么區(qū)別?

          答案:事件冒泡和事件捕獲是指瀏覽器處理事件時的兩種不同的傳播方式。

          事件冒泡是指事件從最內(nèi)層的元素開始觸發(fā),然后逐級向上傳播到父元素,直到傳播到最外層的元素。

          事件捕獲是指事件從最外層的元素開始觸發(fā),然后逐級向下傳播到最內(nèi)層的元素。

          區(qū)別在于傳播方向的不同。事件冒泡是從內(nèi)向外傳播,而事件捕獲是從外向內(nèi)傳播。

          4. 解釋一下同步和異步的JavaScript代碼執(zhí)行方式。

          答案:同步代碼是按照順序執(zhí)行的代碼,每個任務(wù)必須等待前一個任務(wù)完成后才能執(zhí)行。同步代碼會阻塞后續(xù)代碼的執(zhí)行,直到當前任務(wù)完成。

          異步代碼是不按照順序執(zhí)行的代碼,它會在后臺執(zhí)行,不會阻塞后續(xù)代碼的執(zhí)行。異步代碼通常使用回調(diào)函數(shù)、Promise、async/await等方式來處理異步操作的結(jié)果。

          通過異步執(zhí)行,可以避免阻塞主線程,提高頁面的響應(yīng)性能。

          5. 什么是事件循環(huán)(Event Loop)?它在JavaScript中的作用是什么?

          答案:事件循環(huán)是JavaScript中處理異步代碼執(zhí)行的機制。它負責(zé)管理調(diào)度和執(zhí)行異步任務(wù),并將它們添加到執(zhí)行隊列中。

          在JavaScript中,事件循環(huán)的作用是確保異步任務(wù)按照正確的順序執(zhí)行,并且不會阻塞主線程。它通過不斷地從執(zhí)行隊列中取出任務(wù)并執(zhí)行,以實現(xiàn)非阻塞的異步操作。

          6. 解釋一下瀏覽器的垃圾回收機制是如何工作的。

          答案:瀏覽器的垃圾回收機制是一種自動管理內(nèi)存的機制,用于檢測和回收不再使用的對象,以釋放內(nèi)存資源。

          垃圾回收機制通過標記-清除算法實現(xiàn)。它的工作原理如下:

          標記階段:垃圾回收器會從根對象(如全局對象)開始,遞歸遍歷所有對象,并標記仍然可訪問的對象。 清除階段:垃圾回收器會掃描堆內(nèi)存,清除未被標記的對象,并回收它們所占用的內(nèi)存空間。 垃圾回收機制的目標是識別和回收不再使用的對象,以避免內(nèi)存泄漏和提高內(nèi)存利用率。

          7. 解釋一下瀏覽器的同源策略(Same-Origin Policy)及其限制。

          答案:同源策略是瀏覽器的一項安全機制,用于限制來自不同源的網(wǎng)頁之間的交互。同源是指協(xié)議、域名和端口號完全相同。

          同源策略的限制包括:

          腳本訪問限制:不同源的腳本無法直接訪問彼此的數(shù)據(jù)和操作。 DOM訪問限制:不同源的網(wǎng)頁無法通過JavaScript訪問彼此的DOM元素。 Cookie限制:不同源的網(wǎng)頁無法讀取或修改彼此的Cookie。 AJAX請求限制:不同源的網(wǎng)頁無法通過AJAX請求訪問彼此的數(shù)據(jù)。 同源策略的存在可以防止惡意網(wǎng)站獲取用戶的敏感信息或進行惡意操作。

          8. 什么是Web Workers?它們在瀏覽器中的作用是什么?

          答案:Web Workers是一種瀏覽器提供的JavaScript API,用于在后臺線程中執(zhí)行耗時的計算任務(wù),以避免阻塞主線程。

          Web Workers的作用是提高瀏覽器的響應(yīng)性能,使得在執(zhí)行復(fù)雜計算或處理大量數(shù)據(jù)時,不會影響用戶界面的流暢性。

          Web Workers通過將任務(wù)委托給后臺線程來實現(xiàn)并行處理,從而充分利用多核處理器的能力。它們可以與主線程進行通信,但不能直接訪問DOM或執(zhí)行UI相關(guān)的操作。

          9. 解釋一下瀏覽器緩存(Browser Cache)是什么,以及它的作用是什么?

          答案:瀏覽器緩存是瀏覽器在本地存儲Web頁面和資源的副本,以便在后續(xù)訪問時可以快速加載。它的作用是減少對服務(wù)器的請求次數(shù)和網(wǎng)絡(luò)傳輸量,提高頁面加載速度和用戶體驗。

          瀏覽器緩存通過在首次請求時將資源保存到本地,并在后續(xù)請求時檢查資源是否已經(jīng)存在并且沒有過期來工作。如果資源已經(jīng)存在且未過期,瀏覽器會直接從緩存中加載資源,而不是從服務(wù)器重新下載。

          10. 什么是重定向(Redirect)?它在瀏覽器中的作用是什么?

          答案:重定向是指當瀏覽器請求一個URL時,服務(wù)器返回一個不同的URL,從而將瀏覽器的請求重定向到新的URL上。

          重定向在瀏覽器中的作用是實現(xiàn)頁面的跳轉(zhuǎn)、URL的修改或資源的重定向。它可以用于多種情況,例如處理舊鏈接的跳轉(zhuǎn)、實現(xiàn)URL的規(guī)范化、處理用戶認證等。

          重定向通過在HTTP響應(yīng)中設(shè)置特定的狀態(tài)碼(如301永久重定向、302臨時重定向)和Location頭部字段來實現(xiàn)。

          11. 什么是瀏覽器存儲(Browser Storage)?它有哪些不同的存儲機制?

          答案:瀏覽器存儲是瀏覽器提供的一種在客戶端存儲數(shù)據(jù)的機制,用于在不同的網(wǎng)頁間共享數(shù)據(jù)或持久保存數(shù)據(jù)。

          瀏覽器存儲有以下不同的存儲機制:

          Cookie:小型文本文件,可以存儲少量數(shù)據(jù),并在每次HTTP請求中自動發(fā)送到服務(wù)器。 Web Storage(localStorage和sessionStorage):可以存儲較大量的數(shù)據(jù),以鍵值對的形式存儲在瀏覽器中。 IndexedDB:一種高級的客戶端數(shù)據(jù)庫,可以存儲大量結(jié)構(gòu)化數(shù)據(jù),并支持索引和事務(wù)操作。 Cache API:用于緩存網(wǎng)絡(luò)請求的響應(yīng),以便離線訪問或提高頁面加載速度。 不同的存儲機制適用于不同的需求,開發(fā)者可以根據(jù)具體情況選擇合適的存儲方式。

          祝想跳槽的小伙伴們都能成功!需要更多完整面試題可以私信我!


          主站蜘蛛池模板: 国产美女口爆吞精一区二区| 国产精品视频一区麻豆| 亚洲中文字幕久久久一区| 无码日韩精品一区二区三区免费| AA区一区二区三无码精片| 国产成人精品第一区二区| 无码国产伦一区二区三区视频| 午夜视频一区二区| 中文字幕一区日韩精品| 久久久久人妻一区二区三区vr | 国产精品久久一区二区三区| 少妇人妻偷人精品一区二区| 视频在线一区二区三区| 国产伦一区二区三区免费| 精品欧美一区二区在线观看| 无码一区18禁3D| 天天视频一区二区三区| 精品久久综合一区二区| 日本一区二区三区在线看| 国产精品视频一区二区三区经 | 台湾无码AV一区二区三区| 成人无号精品一区二区三区| 99精品一区二区三区无码吞精| 中文字幕精品一区影音先锋| 国产大秀视频在线一区二区 | 免费国产在线精品一区| 亚洲av无码一区二区三区四区| 久久久国产精品无码一区二区三区| 成人中文字幕一区二区三区| 夜夜精品视频一区二区| 精品人妻一区二区三区四区在线| 日韩电影在线观看第一区| 日本道免费精品一区二区| 国产在线视频一区二区三区98| 中文字幕一精品亚洲无线一区| 国产亚洲情侣一区二区无码AV| 色妞AV永久一区二区国产AV | 国产成人av一区二区三区在线| 麻豆精品一区二区综合av| 亚洲一区二区三区自拍公司| 免费一区二区无码视频在线播放|