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