Lighthouse的使用與Google的移動(dòng)端最佳實(shí)踐

Lighthouse是一個(gè)Google開源的自動(dòng)化工具,主要用于改進(jìn)網(wǎng)絡(luò)應(yīng)用(移動(dòng)端)的質(zhì)量。目前測(cè)試項(xiàng)包括頁面性能、PWA可訪問性(無障礙)、最佳實(shí)踐SEO。Lighthouse會(huì)對(duì)各個(gè)測(cè)試項(xiàng)的結(jié)果打分,并給出優(yōu)化建議,這些打分標(biāo)準(zhǔn)和優(yōu)化建議可以視為Google的網(wǎng)頁最佳實(shí)踐。

options.png

使用入門


運(yùn)行Lighthouse的方式有三種:在開發(fā)者工具(Devtools)的Audits,作為Chrome拓展程序使用,或者作為命令行工具使用。Chrome開發(fā)者工具不需要額外安裝,和擴(kuò)展程序一樣提供了一個(gè)用戶友好的界面,方便讀取報(bào)告;擴(kuò)展程序相對(duì)于開發(fā)者工具的優(yōu)勢(shì)是更及時(shí),不用等待Chrome發(fā)版就能體驗(yàn)到最新的功能;命令行工具可以將Lighthouse集成到持續(xù)集成系統(tǒng)。

開發(fā)者工具

僅能在Chrome60及以上使用,因?yàn)橹鞍姹镜腃hrome的開發(fā)者工具的audits面板還不是Lighthouse。
extension.png
audits.png

通過右上角的菜單或者快捷鍵(command+option+i)打開開發(fā)者工具,然后選擇audits面板,點(diǎn)擊Perform an audits會(huì)彈出一個(gè)options面板勾選測(cè)試項(xiàng)然后點(diǎn)擊Run audits即可。

Chrome拓展程序

安裝地址(需要梯子)

extension.png

generate.png

在右上角或者菜單里點(diǎn)擊圖中圖標(biāo),Options可以配置測(cè)試項(xiàng)目,點(diǎn)擊Generate report即可測(cè)試。

命令行工具

安裝:

npm install -g lighthouse
# or use yarn:
# yarn global add lighthouse

使用:

lighthouse https://example.com

配置項(xiàng):

$ lighthouse --help

lighthouse <url>

Logging:
  --verbose  Displays verbose logging                                                                                                      [boolean]
  --quiet    Displays no progress, debug logs or errors                                                                                    [boolean]

Configuration:
  --save-assets                  Save the trace contents & screenshots to disk                                                             [boolean]
  --list-all-audits              Prints a list of all available audits and exits                                                           [boolean]
  --list-trace-categories        Prints a list of all required trace categories and exits                                                  [boolean]
  --additional-trace-categories  Additional categories to capture with the trace (comma-delimited).
  --config-path                  The path to the config JSON.
  --chrome-flags                 Custom flags to pass to Chrome (space-delimited). For a full list of flags, see
                                 http://peter.sh/experiments/chromium-command-line-switches/.

                                 Environment variables:
                                 CHROME_PATH: Explicit path of intended Chrome binary. If set must point to an executable of a build of
                                 Chromium version 54.0 or later. By default, any detected Chrome Canary or Chrome (stable) will be launched.
                                                                                                                                       [default: ""]
  --perf                         Use a performance-test-only configuration                                                                 [boolean]
  --port                         The port to use for the debugging protocol. Use 0 for a random port                                    [default: 0]
  --hostname                     The hostname to use for the debugging protocol.                                              [default: "localhost"]
  --max-wait-for-load            The timeout (in milliseconds) to wait before the page is considered done loading and the run should continue.
                                 WARNING: Very high values can lead to large traces and instability                                 [default: 45000]
  --enable-error-reporting       Enables error reporting, overriding any saved preference. --no-enable-error-reporting will do the opposite. More:
                                 https://git.io/vFFTO
  --gather-mode, -G              Collect artifacts from a connected browser and save to disk. If audit-mode is not also enabled, the run will quit
                                 early.                                                                                                    [boolean]
  --audit-mode, -A               Process saved artifacts from disk                                                                         [boolean]

Output:
  --output       Reporter for the results, supports multiple values                        [choices: "json", "html", "domhtml"] [default: "domhtml"]
  --output-path  The file path to output the results. Use 'stdout' to write to stdout.
                 If using JSON output, default is stdout.
                 If using HTML output, default is a file in the working directory with a name based on the test URL and date.
                 If using multiple outputs, --output-path is ignored.
                 Example: --output-path=./lighthouse-results.html
  --view         Open HTML report in your browser                                                                                          [boolean]

Options:
  --help                        Show help                                                                                                  [boolean]
  --version                     Show version number                                                                                        [boolean]
  --blocked-url-patterns        Block any network requests to the specified URL patterns                                                     [array]
  --disable-storage-reset       Disable clearing the browser cache and other storage APIs before a run                                     [boolean]
  --disable-device-emulation    Disable Nexus 5X emulation                                                                                 [boolean]
  --disable-cpu-throttling      Disable CPU throttling                                                                    [boolean] [default: false]
  --disable-network-throttling  Disable network throttling                                                                                 [boolean]
  --extra-headers               Set extra HTTP Headers to pass with request                                                                 [string]

Examples:
  lighthouse <url> --view                                                   Opens the HTML report in a browser after the run completes
  lighthouse <url> --config-path=./myconfig.js                              Runs Lighthouse with your own configuration: custom audits, report
                                                                            generation, etc.
  lighthouse <url> --output=json --output-path=./report.json --save-assets  Save trace, screenshots, and named JSON report.
  lighthouse <url> --disable-device-emulation --disable-network-throttling  Disable device emulation
  lighthouse <url> --chrome-flags="--window-size=412,732"                   Launch Chrome with a specific window size
  lighthouse <url> --quiet --chrome-flags="--headless"                      Launch Headless Chrome, turn off logging
  lighthouse <url> --extra-headers "{\"Cookie\":\"monster=blue\"}"          Stringify\'d JSON HTTP Header key/value pairs to send in requests
  lighthouse <url> --extra-headers=./path/to/file.json                      Path to JSON file of HTTP Header key/value pairs to send in requests

For more information on Lighthouse, see https://developers.google.com/web/tools/lighthouse/.

測(cè)試結(jié)果示例


result.png

最佳實(shí)踐


這些最佳實(shí)踐主要針對(duì)移動(dòng)端或者Web應(yīng)用。某些技術(shù)對(duì)瀏覽器版本要求較高,用之前最好在Can I use、MDN上查一下瀏覽器支持情況

打開外部鏈接使用rel="noopener"

當(dāng)頁面使用 target="_blank" 跳轉(zhuǎn)至另一個(gè)頁面時(shí),新頁面將與您的頁面在同一個(gè)進(jìn)程上運(yùn)行。 如果新頁面正在執(zhí)行開銷極大的 JavaScript,您的頁面性能可能會(huì)受影響。最重要的是target="_blank”也是一個(gè)安全漏洞。新頁面可以通過window.opener訪問舊頁面的window對(duì)象,并且它可以使用window.opener.location=newURL將舊頁面導(dǎo)航至不同的網(wǎng)址。所以當(dāng)在新窗口或標(biāo)簽中打開一個(gè)外部鏈接時(shí),應(yīng)該始終加上rel="noopener",例如:

<a  target="_blank" rel="noopener">...</a>
地址欄顏色應(yīng)該和品牌顏色、網(wǎng)頁主題匹配
address.png

就是地址欄的背景顏色應(yīng)該和品牌顏色一致
通過meta標(biāo)簽實(shí)現(xiàn)的:

<meta name="theme-color" content="#ff6633">

不過僅在認(rèn)可這個(gè)meta的瀏覽器上有效,比如Chrome for Android,實(shí)測(cè)pc、ios的Chrome、Safari無效。


bilibili.png

如果場(chǎng)景能用上還是能提高一些用戶體驗(yàn)的,避免了地址欄突兀。

避免使用AppCache

AppCache已被廢棄
考慮使用service worker的Cache API,另外現(xiàn)在ios 11.3也支持了service worker,未來一兩年應(yīng)該有很大發(fā)展。

避免使用console.time()

如果使用console.time()測(cè)試頁面性能,請(qǐng)考慮使用User Timing API。其優(yōu)勢(shì)包括:

  • 高分辨率時(shí)間戳
  • 可導(dǎo)出的計(jì)時(shí)數(shù)據(jù)
  • 與Chrome Devtools TImeline相集成。在 Timeline 錄制期間調(diào)用 User Timing 函數(shù) performance.measure() 時(shí),DevTools 自動(dòng)將此測(cè)量結(jié)果添加到 Timeline 的結(jié)果中。
    將console.time()替換為performance.mark()。如果需要測(cè)量兩個(gè)label之間經(jīng)過的時(shí)間,則使用performance.measure()。User Timing API
// 獲得命名時(shí)間戳
window.performance.mark('mark_fully_loaded');
// 獲得命名時(shí)間戳之間的時(shí)間間隔或者與PerformanceTiming的時(shí)間間隔
window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');
避免使用Date.now()

考慮改用performance.now()代替Date.now()。performance.now()可提供較高的時(shí)間戳分辨率,并始終以恒定的速率增加,它不受系統(tǒng)時(shí)鐘(可以調(diào)整)的影響。performance.now()

// 獲取相對(duì)于navigationStart屬性中的時(shí)間戳為起點(diǎn)開始計(jì)時(shí)的精確到千分之一毫秒的時(shí)間戳
 window.performance.now()
避免棄用的API

已棄用的API計(jì)劃從Chrome中移除,使用這些API后,被刪除后將導(dǎo)致網(wǎng)頁出錯(cuò)。查看Chrome平臺(tái)狀態(tài)

避免使用document.write()

對(duì)于網(wǎng)速較慢(2G、3G或較慢的WLAN)的用戶,外部腳本通過document.write()動(dòng)態(tài)注入會(huì)使頁面內(nèi)容的顯示延遲數(shù)十秒。

避免巨大的網(wǎng)絡(luò)負(fù)載

延遲請(qǐng)求直到需要它們
啟用文本壓縮
壓縮HTML、JS和CSS
使用Webp而不是JPEG或PNG
將JPEG圖像的壓縮級(jí)別設(shè)置為85
緩存請(qǐng)求

避免使用mutation events

以下mutation events會(huì)損害性能,在DOM事件規(guī)范中已經(jīng)棄用:

  • DOMAttrModified
  • DOMAttributeNameChanged
  • DOMCharacterDataModified
  • DOMElementNameChanged
  • DOMNodeInserted
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemoved
  • DOMNodeRemovedFromDocument
  • DOMSubtreeModified
    建議將每個(gè)mutation events替換成MutationObserver
避免使用舊版CSS Flexbox

2009年的舊Flexbox規(guī)范已棄用,其速度比最新的規(guī)范慢2.3倍。將頁面中的display:box及以box開頭的每個(gè)屬性替換成標(biāo)準(zhǔn)的Flexbox屬性。

避免在頁面加載時(shí)自動(dòng)請(qǐng)求地理位置

頁面在加載時(shí)自動(dòng)請(qǐng)求用戶位置會(huì)使用戶不信任頁面或感到困惑。應(yīng)將此請(qǐng)求與用戶的手勢(shì)進(jìn)行關(guān)聯(lián),而不是在頁面加載時(shí)自動(dòng)請(qǐng)求用戶的位置。

避免在頁面加載時(shí)自動(dòng)請(qǐng)求通知權(quán)限

好的通知需要做到及時(shí)、相關(guān)且準(zhǔn)確。如果頁面在加載時(shí)要求權(quán)限以發(fā)送通知,則這些通知可能與您的用戶無關(guān)或者不是他們的精準(zhǔn)需求。為提高用戶體驗(yàn),最好是向用戶發(fā)送特定類型的通知,并在他們選擇加入后顯示權(quán)限請(qǐng)求。

避免使用Web SQL

Web SQL已棄用,建議替換為IndexedDB

背景和前景應(yīng)該有足夠的對(duì)比度

低對(duì)比度文本對(duì)于許多用戶來說很難或不可能讀取
使用Chrome擴(kuò)展程序aXe可以分析出所有的可訪問性問題

按鈕有一個(gè)可訪問的名稱

沒有名字的按鈕對(duì)依賴屏幕閱讀器的用戶不可用。當(dāng)一個(gè)按鈕沒有名字時(shí),屏幕閱讀器會(huì)宣布“按鈕”。
對(duì)<button>元素和role="button"的元素:

  • 設(shè)置元素的內(nèi)部文本
  • 設(shè)置aria-label屬性
  • 將該aria-labelledby屬性設(shè)置為屏幕閱讀器可見的文本元素。

對(duì)于<input type = "button">的元素:

  • 設(shè)置value屬性
  • 設(shè)置aria-label屬性
  • 設(shè)置aria-labelledby屬性

對(duì)于<input type="submit">和<input type="rest">:

  • 設(shè)置value屬性,或省略它。瀏覽器在value省略時(shí)賦予"submit"或"reset"的默認(rèn)值
  • 設(shè)置aria-label屬性
  • 設(shè)置aria-labelledby屬性
頁面在其腳本不可用時(shí)包含一些內(nèi)容

基本內(nèi)容和頁面功能不應(yīng)該依賴于CSS或JS。對(duì)于必需依賴JavaScript的頁面,一種方法是使用一個(gè)<noscript>元素,以提醒用戶此頁面需要JavaScript。

優(yōu)化關(guān)鍵渲染路徑

將關(guān)鍵資源數(shù)降至最低:消除關(guān)鍵資源、延遲關(guān)鍵資源的下載并將它們標(biāo)記為不同步等。
優(yōu)化關(guān)鍵字節(jié)數(shù)以縮短下載時(shí)間。
優(yōu)化其余關(guān)鍵資源的加載順序:盡早下載所有關(guān)鍵資產(chǎn),以縮短關(guān)鍵路徑長度。

避免長寬比不正確的圖像

如果渲染的圖像與其源文件中的長寬比不同,則呈現(xiàn)的圖像可能看起來失真,產(chǎn)生不愉悅的用戶體驗(yàn)。

  • 避免將元素的寬度或高度設(shè)置為可變大小的容器的百分比。
  • 避免設(shè)置不同于源圖像尺寸的顯式寬度或高度值。
  • 考慮使用css-aspect-ratioAspect Ratio Boxes來幫助保留寬高比。
  • 如果可能的話,在HTML中指定圖片的寬度和高度是一個(gè)很好的做法,這樣瀏覽器就可以為圖片分配空間,這樣可以防止頁面在加載時(shí)跳過。在HTML中而不是CSS中指定寬度和高度是更理想的,因?yàn)闉g覽器在解析CSS之前分配空間。實(shí)際上,如果您使用響應(yīng)式圖像,則此方法可能很困難,因?yàn)樵谥酪暱诔叽缰盁o法指定寬度和高度。
啟用文本壓縮

如果瀏覽器支持,則配置服務(wù)器以使用Brotli壓縮響應(yīng)。Brotli比GZIP可以節(jié)省更多的流量。如果不支持Brotli則使用GZIP。在Chrome DevTools檢查響應(yīng)是否被壓縮:

  • 打開DevTools的Network面板
  • 點(diǎn)擊指定的回復(fù)的請(qǐng)求。
  • 點(diǎn)擊Headers選項(xiàng)卡
  • 檢查Response Headers中content-heading字段


    content.png
預(yù)計(jì)輸入延遲時(shí)間

輸入響應(yīng)能力對(duì)用戶如何看待應(yīng)用的性能起著關(guān)鍵作用。應(yīng)用有100毫秒的時(shí)間響應(yīng)用戶輸入。如果超過此時(shí)間,用戶就會(huì)認(rèn)為應(yīng)用反應(yīng)遲緩。

優(yōu)化代碼在瀏覽器中的運(yùn)行方式:
  1. 對(duì)于動(dòng)畫效果的實(shí)現(xiàn),避免使用setTimeout或setInterval,請(qǐng)使用requestAnimationFrame
  2. 將長時(shí)間運(yùn)行的JavaScript從主線程移動(dòng)到Web Worker
  3. 使用micro-tasks來執(zhí)行對(duì)多個(gè)幀的DOM更改
  4. 使用Chrome DevTools的Timeline和Javascript分析器來評(píng)估JavaScript的影響。
    降低選擇器的復(fù)雜性(例如:nth-of-type、:nth-child);使用以類為中心的方法,例如BEM,這有一篇BEM的教程
  5. 盡可能避免布局操作,對(duì)“幾何屬性”(如寬度、高度左側(cè)或頂部)的更改都需要布局計(jì)算。布局幾乎總是作用到整個(gè)文檔,如果有大量元素,會(huì)消耗很長時(shí)間來計(jì)算出所有元素的位置和尺寸。
  6. 避免強(qiáng)制同步布局


    render.png

    首先JavaScript運(yùn)行,然后計(jì)算樣式,然后布局。但是,可以使用JavaScript強(qiáng)制瀏覽器提前執(zhí)行布局。這被稱為強(qiáng)制同步布局。在JavaScript運(yùn)行時(shí),來自上一幀的所有舊布局值是已知的,并且可供查詢。因此,如果在幀的開頭寫出一個(gè)元素的高度是沒有問題的,但是在查詢高度之前,已經(jīng)更改其樣式,如下列代碼。,就會(huì)強(qiáng)制頁面計(jì)算返回正確的高度。這是不必要的,并且開銷很大。始終應(yīng)先批量讀取樣式并執(zhí)行,然后執(zhí)行任何寫操作。

function logBoxHeight() {

  box.classList.add('super-big');

  // Gets the height of the box in pixels
  // and logs it out.
  console.log(box.offsetHeight);
}
  1. 除 transform 或 opacity 屬性之外,更改任何屬性始終都會(huì)觸發(fā)繪制。可以使用Chrome DevTools來快速確定正在繪制的區(qū)域。打開DevTools,按下鍵盤上的 Esc 鍵。在出現(xiàn)的面板中,轉(zhuǎn)到“rendering”標(biāo)簽,然后選中“Show paint rectangles”。
    rendering.png
  1. 每一個(gè)表單元素都應(yīng)該有一個(gè)label
    label闡明了表單元素的用途。雖然每個(gè)元素的目的對(duì)于有視覺的用戶來說可能是顯而易見的,但對(duì)于依靠屏幕閱讀器的用戶來說并非如此。有四種方式可以實(shí)現(xiàn):
  • 隱含標(biāo)簽
<label>First Name <input type="text"/></label>
  • 顯式標(biāo)簽
<label for="first">First Name <input type="text" id="first"/></label>
  • aria-label
<button class="hamburger-menu" aria-label="menu">...</button>
  • aria-labelledby
<span id="foo">Select seat:</span>
<custom-dropdown aria-labelledby="foo">...</custom-dropdown>
  1. 每個(gè)圖像都有一個(gè)alt屬性
    信息性圖像應(yīng)該具有alt包含該圖像內(nèi)容的文本描述的屬性。屏幕閱讀器使視覺障礙的用戶能夠通過將文本內(nèi)容轉(zhuǎn)換為可以使用的表格(如合成語音或盲文)來使用您的網(wǎng)站。屏幕閱讀器無法轉(zhuǎn)換圖像。因此,如果您的圖片包含重要信息,那么視覺障礙用戶無法獲取該信息。
    可以在DevTools的Console選項(xiàng)卡中使用以下命令來查找沒有alt屬性的圖片
$$('img:not([alt])');

在Console中$$()相當(dāng)于document.querySelectorAll()

  1. 配置HTML的Viewport meta標(biāo)簽
    如果沒有Viewport meta標(biāo)簽,移動(dòng)設(shè)備將以典型的桌面設(shè)備屏幕寬度渲染頁面,然后對(duì)頁面進(jìn)行縮放以適合移動(dòng)設(shè)備屏幕。通過Viewport meta標(biāo)簽可以控制寬度和縮放比例。
    配置視口 設(shè)置視口
    width=device-width鍵值對(duì)將視口寬度設(shè)置為設(shè)備寬度。在訪問頁面時(shí),initial-scale=1鍵值對(duì)設(shè)置初始縮放級(jí)別。
<head>
  ...
  <meta name="viewport" content="width=device-width, initial-scale=1">
  ...
</head>
  1. 壓縮圖片(僅針對(duì)JPEG)
    將每個(gè)圖像的壓縮級(jí)別設(shè)置為85或更低,像TinyJPG這樣的Web服務(wù)可以幫助自動(dòng)化圖像優(yōu)化的過程
避免頁面存在不成功的HTTP狀態(tài)碼

搜索引擎可能無法正確索引返回不成功的HTTP狀態(tài)碼的頁面。

允許用戶粘貼到密碼字段中

密碼粘貼提高了安全性,因?yàn)樗褂脩裟軌蚴褂妹艽a管理器。密碼管理員通常為用戶生成強(qiáng)密碼,安全地存儲(chǔ)密碼,然后在用戶需要登錄時(shí)自動(dòng)將其粘貼到密碼字段中。
刪除阻止用戶粘貼到密碼字段的代碼。使用事件斷點(diǎn)中的Clipboard paste來打斷點(diǎn),可以快速找到阻止粘貼密碼的代碼。比如下列這種阻止粘貼密碼的代碼:

let input = document.querySelector('input');
input.addEventListener('paste', (e) => {
  e.preventDefault(); // This is what prevents pasting.
});
dom-breakpoint.png
避免DOM過大

大型的DOM樹會(huì)以多種方式降低頁面性能:

  • 網(wǎng)絡(luò)效率和負(fù)載性能,如果你的服務(wù)器發(fā)送一個(gè)大的DOM樹,你可能會(huì)運(yùn)送大量不必要的字節(jié)。這也可能會(huì)減慢頁面加載時(shí)間,因?yàn)闉g覽器可能會(huì)解析許多沒有顯示在屏幕上的節(jié)點(diǎn)。
  • 運(yùn)行時(shí)性能。當(dāng)用戶和腳本與頁面交互時(shí),瀏覽器必須不斷重新計(jì)算節(jié)點(diǎn)的位置和樣式。一個(gè)大的DOM樹與復(fù)雜的樣式規(guī)則相結(jié)合可能會(huì)嚴(yán)重減慢渲染速度。
    內(nèi)存性能。如果使用通用查詢選擇器(例如,document.querySelectorAll('li') 您可能會(huì)無意中將引用存儲(chǔ)到大量的節(jié)點(diǎn)),這可能會(huì)壓倒用戶設(shè)備的內(nèi)存功能。

一個(gè)最佳的DOM樹:

  • 總共少于1500個(gè)節(jié)點(diǎn)。
  • 最大深度為32個(gè)節(jié)點(diǎn)。
  • 沒有超過60個(gè)子節(jié)點(diǎn)的父節(jié)點(diǎn)。
  • 一般來說,只需要在需要時(shí)尋找創(chuàng)建DOM節(jié)點(diǎn)的方法,并在不再需要時(shí)將其銷毀。

如果你不能避免一個(gè)大型的DOM樹,改善渲染性能的另一種方法是簡化你的CSS選擇器。請(qǐng)參閱減少風(fēng)格計(jì)算的范圍和復(fù)雜性。

使用被動(dòng)事件監(jiān)聽器以提升滾動(dòng)性能

被動(dòng)事件是新興的Web標(biāo)準(zhǔn),可以顯著提高滾動(dòng)性能,尤其在移動(dòng)設(shè)備上。當(dāng)使用touch事件監(jiān)聽器(scroll事件不存在這個(gè)問題)進(jìn)行滾動(dòng)時(shí),因?yàn)闉g覽器不知道你是否會(huì)取消滾動(dòng),它們總是等待監(jiān)聽器執(zhí)行完畢后才開始滾動(dòng),這樣就造成了明顯的延遲。事件監(jiān)聽器options中使用passive:true表明監(jiān)聽器永遠(yuǎn)不會(huì)取消滾動(dòng),這樣瀏覽器就可以立即滾動(dòng)。
在支持被動(dòng)事件偵聽器的瀏覽器中,將偵聽器標(biāo)記為passive即可:

document.addEventListener('touchstart', onTouchStart, {passive: true});

參考資料

歡迎訪問我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 14,083評(píng)論 1 92
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,667評(píng)論 25 709
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,500評(píng)論 19 139
  • 楊白勞和黃世仁是舊時(shí)代的人,是勞苦大眾和剝削階級(jí)的典型代表,如此盤剝勞動(dòng)人民的“黃世仁”按說不應(yīng)該在新社會(huì)存在,但...
    愛美如君閱讀 632評(píng)論 0 1

友情鏈接更多精彩內(nèi)容