景:在實際生產(chǎn)中,程序員會遇到導(dǎo)出圖片的需求,通常情況下,前端工程師只要將頁面上canvas轉(zhuǎn)成base64的字符串,通過調(diào)用后端接口,將base64的字符串上傳,由后臺工程師生成文件。但是,遇到剛?cè)腴T的菜鳥后端時,這一切就不是那么順利了。俗話說,求人不如求己,靠人不如靠己。這點小功能,前端工程師通過base64轉(zhuǎn)Blob的方式也可以做到。
下面直接上代碼:
第一步:先把base64字符串轉(zhuǎn)成Blob文件
const base64ToBlob = (code)=> {
const lists = code.split(';base64,')
const contentType = lists[0].split(':')[1]
const raw = window.atob(lists[1])
const rawLength = raw.length
const arraryBuffer = new ArrayBuffer(rawLength)
let uInt8Array = new Uint8Array(arrayBuffer)
for(let i = 0; i < rawLength; i++) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], {type: contentType})
}
第二步:通過生成a標簽,設(shè)置a標簽的href屬性,模擬點擊事件觸發(fā)下載功能
const downloadFile = (content, fileName) => {
const aLink = document.createElement('a')
const blob = base64ToBlob(content)
const evt = document.createEvent('HTMLEvents')
evt.initEvent('click', true, true)
aLink.download = fileName // 設(shè)置下載文件名稱
aLink.href = URL.createObjectURL(blob)
const options={
bubbles: true,
cancelable: true,
view: window
}
const mouseEvent = new MouseEvent('click', options)
aLink.dispatchEvent(mouseEvent)
}
最后,完成!
文章來聊聊瀏覽器到底是如何對待下載資源的,比如說 JS、CSS、字體、圖片等文件。
CSS、JS 文件冤家路窄
HTML 在解析的過程中遇到同步的 script 會卡住 DOM 解析這個知識點我相信讀者們應(yīng)該都知道。
<!DOCTYPE html> <html lang="en"> <body> <script>console.log(1)</script> <div>1</div> </body> </html>
上述代碼中,HTML 遇到 <script>console.log(1)</script> 代碼就會停止 DOM 解析了。當(dāng)然現(xiàn)代瀏覽器不是說就這樣停住啥也不干了,會有個 preload scanner 去掃描底下的文件,然后根據(jù)文件類型去制定優(yōu)先級(這個下面再說)。
上面舉得例子是內(nèi)聯(lián)代碼,如果是一個 JS 文件的話,那么就得等這個 JS 文件下完以后執(zhí)行代碼才行。
但是一般我們文件結(jié)構(gòu)不會那么單一,CSS 文件也肯定是有的。因為 JS 不僅能動 DOM 也能改 style,所以如果遇到 script 之前還有別的 CSS 文件的話,瀏覽器還得等 CSS 文件下完以后再去執(zhí)行 JS。
所以說不只是 JS 會阻塞 DOM 解析,CSS 也會。
當(dāng)然我想現(xiàn)在應(yīng)該很少再有人直接寫同步的 script 了吧。
文件同時遇到,那會同時開始下載嘛?
舉個例子,在可以同時下載多個文件的情況下,瀏覽器在 HTML、CSS 文件中解析到了 img、font、background-image 資源,那么們會同時開始下載嘛?
答案是不會!
這里只有 img 會最先開始下載,其它兩塊內(nèi)容都得等到 layout 以后才會開始下載。不信的話我們來看圖:
這里以 font 為例
圖中右下角框出來的是字體文件,上面是 CSS 文件,字體是從 CSS 文件中得知需要去加載的。
大家可以在圖中發(fā)現(xiàn) CSS 文件早早開始下載解析了,但是 font 文件遲遲未開始下載,直到 FP 指標即將出現(xiàn)的時候才開始下載動作,這個時間點是在 layout 完成以后。
圖中是以掘金為例,大家可以多試試別的網(wǎng)站,應(yīng)該能發(fā)現(xiàn)是符合預(yù)期的。
那么讀者可能會有個疑問,按照這個邏輯意思是說能用 img 的都用 img,因為background-image 不是馬上開始下載的?道理是這個道理,但是還是得分情況來說,如果圖片出現(xiàn)的位置不是首屏,用 background-image 也沒啥問題,當(dāng)然給 img 用上懶加載也能解決問題。
那么到底文件的優(yōu)先級是如何的?
如果大家有使用過 Performance 測試網(wǎng)站性能的話,可以在 Network 那欄里 hover 下載的資源,此時你能發(fā)現(xiàn)資源有優(yōu)先級的顯示。
從圖中大家可以發(fā)現(xiàn) CSS 和字體資源的優(yōu)先級的最高的,JS 文件有高有低(這和類型有關(guān)),圖片、svg 的優(yōu)先級為低。
這部分的優(yōu)先級是指某個時間點上的優(yōu)先級,而不是適應(yīng)于整個周期。對于 CSS 文件優(yōu)先級最高還是挺好理解的,畢竟 JS 文件依賴于 CSS 文件,更加詳細的內(nèi)容大家可以參考 從Chrome源碼看瀏覽器如何加載資源 中的「3. 資源優(yōu)先級」內(nèi)容。
網(wǎng)絡(luò)協(xié)議才是最大元兇
瀏覽器要下載資源,TCP 協(xié)議肯定得用上,但是 TCP 協(xié)議天生就是一個慢的東西。
先得握手,然后慢開始算法,就和我們用迅雷下載東西一樣,帶寬很大沒用,速度都是得爬升上去的。如果再加個 HTTPS 的話,還得再多個 TLS 的握手。
然后說回 HTTP1.1 協(xié)議。Chrome 只支持同個 domain 同時并發(fā) 6 個請求,所以在之前的協(xié)議中一堆請求都得 block 住等之前的下載完成。
當(dāng)然現(xiàn)在不同了,HTTP2 的概念基本大家都知道了,沒見過豬跑但吃過豬肉,對于這塊的知識點聊上幾句沒啥問題。什么多路復(fù)用,header 合并、二進制幀啥的。
得利于 HTTP2 協(xié)議中的多路復(fù)用,我們不再被瀏覽器的六個并發(fā)所限制,所有同一個 domain 上的請求都能跑在復(fù)用的六個網(wǎng)絡(luò)通道上,下載耗時瞬間減少了幾個量級,但是大家有沒有考慮過這個 HTTP2 到底是如何對待這些資源的?
如何分配它們的優(yōu)先級?依賴?帶寬或者別的?畢竟一堆資源占用同一個網(wǎng)絡(luò)通道,那么到底該誰先下載,誰享有的帶寬多點都是需要協(xié)調(diào)的。否則假如一堆圖片占用了大部分帶寬,其他 CSS、JS 文件下的很慢的話,就會影響整個網(wǎng)頁的性能了。
比如說我現(xiàn)在需要下載 CSS、JS、圖片和字體這些文件。舉個例子在這些文件中我希望 CSS 文件能最先開始下載,并且能分配到的帶寬多點;JS 文件呢可以等 CSS 文件下完再去下;其他文件呢優(yōu)先級比 CSS 文件低點,但是也能夠享受到帶寬去進行下載。
這個需求我們可以通過二進制幀去實現(xiàn)。HTTP2 協(xié)議共存在十個二進制幀,其中你可以通過 HEADERS 幀分配新的優(yōu)先級,也可以通過 PRIORITY 幀更改優(yōu)先級。
對于流的優(yōu)先級,我們可以通過兩個方式來實現(xiàn)調(diào)整:
如圖所示(丑了點)。第一排的文件開始一起下載,weight 相加為 20,那么通過計算可得 CSS 文件享有帶寬的一半,其他各占有 1 / 4,JS 文件得等 CSS 完成以后才開始。
那么該如何設(shè)置這些東西呢?當(dāng)然得服務(wù)端支持啦,一般都指 CDN 服務(wù)商了。
最后
查找了很多資料,如有遺漏,還請見諒。文中如果有誤,還望及時指出,感謝
學(xué)習(xí)Java之前,我們需要了解一定的前端知識。畢竟頁面才是用戶真正看到的,而且也是體現(xiàn)Java后端邏輯結(jié)果的地方。
學(xué)習(xí)HTML后,能夠制作界面美觀大方的靜態(tài)網(wǎng)站(更復(fù)雜的功能需要JavaScript腳本一起來實現(xiàn))。
HTML制作的網(wǎng)頁。
所需要的Html開發(fā)工具,可使用Hbuilder。
下載路徑:https://www.dcloud.io/
第一次寫文章,不知道鏈接會不會被屏蔽,如果看不到可以自行百度,直接搜索Hbuilder,進入官網(wǎng)下載安裝,安裝完打開軟件后,點擊暫不登陸,你懂的(免費使用)。
網(wǎng)頁一般使用Chrome,IE的兼容性比較差,學(xué)習(xí)建議使用Chrome。
下載路徑:https://www.google.cn/chrome/
作者推薦的學(xué)習(xí)用軟件,都為免費,放心下載使用。
一、在Hbuilder中如何來創(chuàng)建頁面
1、文件->新建->web項目
2、給項目起名(也可以修改路徑,命名用英文或者拼音縮寫,用中文可能開發(fā)會出錯)
Hbulider創(chuàng)建項目
3、完成
4、右擊新建的項目:新建->HTML文件
5、為新的文件重命名,以html作為后綴
6、完成
Hbuilder創(chuàng)建Html文件
7、選擇頁面,點擊在瀏覽器中運行按鈕
在瀏覽器中運行按鈕
以下新手筆試或者面試容易考
HTML是HyperText Markup Language縮寫,意為超文本標記語言,“超文本”就是指頁面內(nèi)可以包含圖片、鏈接,甚至音樂、程序等非文字元素。
特點:
1、簡易性
2、可擴展性
3、平臺無關(guān)性
4、通用性
HTML的結(jié)構(gòu)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h1>Hello Java</h1>
<h2>Hello Html</h2>
</body>
</html>
HTML的結(jié)構(gòu)詳解:(了解即可,一般開發(fā)軟件會自動生成,如不生成,那就找個會生成的軟件,復(fù)制黏貼)
<!DOCTYPE html>:文件類型聲明,H5中就這么一種寫法。
<html>:告知瀏覽器其自身是一個 HTML 文檔,限定了文檔的開始點和結(jié)束點
<head>:文檔的頭部描述了文檔的各種屬性和信息,包括文檔的標題、字符集等信息。絕大多數(shù)文檔頭部包含的數(shù)據(jù)都不會真正作為內(nèi)容顯示給讀者。在head中可以定義樣式,引用樣式,也可以定義腳本和引用腳本
<body>:文檔的主體部分,包含文檔的所有內(nèi)容(比如文本、超鏈接、圖像、表格和列表等等。),body部分的內(nèi)容一般就是直接呈現(xiàn)給用戶的部分
網(wǎng)頁中的亂碼問題:
<!DOCTYPE html>
<html>
<head>
<meta charset="gb2312">
<title></title>
</head>
<body>
<h1>Hello Java</h1>
<h2>Hello Html</h2>
你好
</body>
</html>
運行以上代碼,可以在網(wǎng)頁中看到,“你好”兩個字為亂碼。這是<meta charset="gb2312">搞的鬼。
當(dāng)文件本身的字符集編碼以與網(wǎng)頁head部分指定的字符集編碼不一致時,就會產(chǎn)生亂碼問題,可以在head部分的meta標簽中指定和文件一樣的字符集編碼來解決這一問題。<meta charset="utf-8" />
從執(zhí)行上面的代碼也可以看出,html是按從上到下的順序來顯示的。
下一篇內(nèi)容:Html各種標簽的認識和使用。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。