整合營銷服務(wù)商

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

          免費(fèi)咨詢熱線:

          HTML5與HTML4的區(qū)別

          TML5是以HTML4為基礎(chǔ)的,并對(duì)HTML4進(jìn)行了大量的修改。

          首先看看語法上的改變、

          對(duì)于HTML4而言,HTML5在語法上發(fā)生了很大的變化。對(duì)于這些變化,有些人開始有點(diǎn)不安,是不是又要開始重新學(xué)習(xí)HTML語言了?但是,HTML5中的語法變化,與其他開發(fā)語言中的語法變化有根本的不同。因?yàn)樵贖TML5之前幾乎沒有符合標(biāo)準(zhǔn)規(guī)范的web瀏覽器導(dǎo)致的。

          HTML的語法是在SGML語言的基礎(chǔ)上建立起來的。但是SGML語法非常之復(fù)雜,要開發(fā)能夠解析SGML語法的程序也很不容易,因此很多瀏覽器都不包含SGML的分析器。因此,雖然HTML基本上遵從SGML的語法,但是對(duì)于HTML的執(zhí)行在各瀏覽器之間并沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)。

          為解決各瀏覽器之間的互兼容性和互操作性,就得要有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),所以HTML5就是圍繞這個(gè)web標(biāo)準(zhǔn),重新定義了一套在現(xiàn)有HTML的基礎(chǔ)上修改而來的語法,以便各瀏覽器在運(yùn)行HTML的時(shí)候能夠符合一個(gè)通用標(biāo)準(zhǔn)。

          于HTML5 淺析

          前言:

          作為一名Web開發(fā)者,可能你并沒有對(duì)這個(gè)“H5”這個(gè)字眼投入太多的關(guān)注,但實(shí)際上它早已不知不覺進(jìn)入到你的開發(fā)中,并且總有一天會(huì)讓你不得不正視它,了解它并運(yùn)用它

          打個(gè)比方:《海賊王》中的主角路飛在“頂上戰(zhàn)爭兩年前”,會(huì)在一些危急關(guān)頭“不經(jīng)意”地使用霸王色霸氣,但對(duì)”霸氣“的結(jié)構(gòu)體系和具體運(yùn)用都不太了解,這讓他在香波地群島等諸多重大戰(zhàn)役中大吃苦頭。此后, 他不惜花費(fèi)兩年時(shí)間跟隨雷利修煉霸氣。因?yàn)椋?strong>如果不去了解這個(gè)嶄新的戰(zhàn)斗方法的話,他們?cè)跉埧岬男率澜缫惶煲采娌涣恕?/strong>


          為什么學(xué)習(xí)HTML5?

          咳咳, 回到主題,為什么我們要學(xué)HTML5呢?

          1. 了解HTML5的囊括范圍的一大好處是:當(dāng)你不小心使用了一個(gè)H5的東東的時(shí)候(例如你試圖通過百度找到的答案解決一個(gè)緊張的需求),你會(huì)很及時(shí)的關(guān)注它的兼容性

          2. H5有些新增的特性也許你從沒接觸過,也感覺無需用到它。但就在不久的將來,你可能就會(huì)用到,甚至依賴于它(畢竟這就是HTML的未來)


          H5中的知識(shí)點(diǎn)分布

          在下面, 我將學(xué)習(xí)H5中的知識(shí)點(diǎn)分成兩類:主要知識(shí)點(diǎn)和針對(duì)特定功能的知識(shí)點(diǎn),其中對(duì)主要知識(shí)點(diǎn)的部分,從學(xué)習(xí)成本的角度對(duì)其進(jìn)行了難度分級(jí)

          (僅屬個(gè)人觀點(diǎn)!如有改進(jìn)意見,歡迎討論)

          一.主要知識(shí)點(diǎn)

          (從需求層面上來說,普及范圍相對(duì)較廣)

          相對(duì)容易的部分:

          1.在線和離線事件(Online/Offline) (相對(duì)容易)

          2. 眾多的新增元素 如<output>, <progress>等 (相對(duì)容易)

          3. history關(guān)于歷史狀態(tài)管理的API (相對(duì)容易)

          4 Storage(localStorage和sessionStorage) (相對(duì)容易)

          相對(duì)較難的部分:

          5. Web Worker (相對(duì)較難)

          6. canvas (相對(duì)較難)

          7. indexedDB (相對(duì)較難)

          8. 拖放操作 (相對(duì)較難)

          9. Web Sockets (相對(duì)較難)

          二. 針對(duì)特定功能的知識(shí)點(diǎn)

          (對(duì)需求來說,主要針對(duì)某一方面的特殊需求場景)

          1. 對(duì)音視頻的支持

          2. Camera API (操作攝像頭)

          3. WebGL (3D圖像)

          4. 地理位置定位 (geolocation對(duì)象)

          本文主要講述H5中主要知識(shí)點(diǎn)中,學(xué)習(xí)成本相對(duì)較高的四個(gè)點(diǎn)(僅個(gè)人觀點(diǎn)):

          一.Web Worker

          二.canvas

          三.indexedDB

          四.拖放操作

          【注意】因?yàn)橄旅娼榻B的H5的特性在一些比較老的瀏覽器里可能遇到兼容性問題,所以你在使用前必須要能力檢測(cè),例如這樣


          Web Worker

          Web Worker的機(jī)制讓你能夠創(chuàng)建一個(gè)在后臺(tái)線程運(yùn)行的腳本,這個(gè)腳本不會(huì)對(duì)我們當(dāng)前執(zhí)行任務(wù)的腳本造成任何干擾(例如阻塞),同時(shí)Web Worker提供了一套API使你能夠在當(dāng)前腳本和后臺(tái)腳本間進(jìn)行數(shù)據(jù)的互相傳輸(worker)

          “一套API, 兩個(gè)對(duì)象”

          我們現(xiàn)在已知的關(guān)于Web Worker的機(jī)制是: 有一個(gè)當(dāng)前腳本, 和一個(gè)在后臺(tái)運(yùn)行的worker腳本,所以我們問題的關(guān)鍵就落在了這兩個(gè)腳本的通信(數(shù)據(jù)交互)上

          通過

          生成了“兩個(gè)對(duì)象”(你可能會(huì)問:為什么是兩個(gè)不是一個(gè)呢?請(qǐng)往下看

          “第一個(gè)”對(duì)象是我們?cè)诋?dāng)前腳本中通過構(gòu)造函數(shù)顯式創(chuàng)建出來的worker對(duì)象,它擁有一套API:postMessage和onmessage,通過postMessage方法可以向worker腳本(上文worker.js)發(fā)送數(shù)據(jù), 通過onmessage方法可以從worker腳本接收數(shù)據(jù)

          “第二個(gè)”對(duì)象是在Web Worker腳本(上文的worker.js)中隱式創(chuàng)建出來的全局變量對(duì)象,它叫DedicatedWorkerGlobalScope(這個(gè)時(shí)候在work.js全局變量對(duì)象是它而不是Window!!),而它也擁有一套API:postMessage和onmessage,通過postMessage方法可以向當(dāng)前執(zhí)行任務(wù)的腳本發(fā)送數(shù)據(jù), 通過onmessage方法可以從當(dāng)前執(zhí)行任務(wù)的腳本接收數(shù)據(jù)

          【注意】關(guān)于DedicatedWorkerGlobalScope

          1. 它是在Web Worker腳本中生成的特殊的全局變量對(duì)象,也就是在全局執(zhí)行環(huán)境中使用this指向的不是Window而是它

          2. 它不能像Windows那樣通過變量名直接訪問,但在Web Worker腳本中你能通過this取到它

          所以現(xiàn)在數(shù)據(jù)傳遞方向有兩條:

          1. 調(diào)用當(dāng)前腳本中worker對(duì)象的postMessage方法, 然后在Web Worker腳本(上文的worker.js)中通過onmessage這個(gè)回調(diào)方法接收數(shù)據(jù)

          2. 調(diào)用Web Worker腳本中的this.postMessage方法(this指向DedicatedWorkerGlobalScope),然后在當(dāng)前腳本中worker對(duì)象的onmessage回調(diào)方法接收數(shù)據(jù)

          看到這里可能有點(diǎn)懵,來讓我們通過一個(gè)例子看看1中的數(shù)據(jù)傳遞:

          先看示例吧,這是我們的目錄結(jié)構(gòu)

          index.html:

          main.js:

          worker.js:

          點(diǎn)擊按鈕后,在main.js中調(diào)用worker對(duì)象的postMessage方法, 這個(gè)數(shù)據(jù)就被發(fā)給了work.js中的全局變量對(duì)象DedicatedWorkerGlobalScope, 所以我們?cè)趙ork,js中通過this.onmessage接收數(shù)據(jù)并輸出


          postMessage中的參數(shù)會(huì)“原封不動(dòng)”傳遞給onmessage中的event.data

          【注意】postMessage傳遞的參數(shù)會(huì)被“原封不動(dòng)”地傳遞給onmessage中event對(duì)象的data屬性

          例如:

          postMessage([1,2,3]) ——> this.onmessage = function (e) { } 中 e.data === [1,2,3]

          postMessage({a:1,b: 2}) ——> this.onmessage = function (e) { } 中 e.data === {a:1,b: 2}


          當(dāng)前任務(wù)腳本和worker腳本完整的通信流程

          我們上面的例子展現(xiàn)的是從當(dāng)前任務(wù)腳本向worker腳本傳遞數(shù)據(jù),那么同樣的道理,我們也能從work腳本向當(dāng)前任務(wù)腳本傳遞數(shù)據(jù)(方式相同)

          例子:

          index.html:

          同上

          main.js:

          worker.js:

          demo如下

          點(diǎn)擊傳遞數(shù)據(jù)輸出:

          canvas

          cancas是H5新增的一個(gè)標(biāo)簽,把canvas翻譯過來就是畫布,顧名思義,這是用來”畫畫的“,畫畫的”畫筆“是什么呢? 它就是和canvas元素對(duì)象對(duì)應(yīng)的一個(gè)”上下文對(duì)象“(context),這里的這個(gè)上下文對(duì)象可能和你印象中的”上下文“有較大的差異,它只是個(gè)單純的包含了一系列“繪畫”方法的對(duì)象,下面我們介紹的關(guān)于canvas的內(nèi)容都要圍繞這個(gè)"canvas上下文對(duì)象"展開

          我們可以通過這種方式取得canvas上下文對(duì)象:

          假設(shè)這是我們的HTML:

          這樣取得上下文對(duì)象:


          繪制基本形狀

          下面展現(xiàn)的是上下文對(duì)象的一些繪制圖形的方法(它們都可以被ctx調(diào)用)

          上面的x,y代表相對(duì)于canvas畫布左上角的橫縱坐標(biāo):

          例子:

          html部分:

          JS部分:

          【注意】. canvas標(biāo)簽內(nèi)的內(nèi)容(例如上面的文本)是否呈現(xiàn)取決于瀏覽器是否支持canvas,如果支持,則不出現(xiàn),如果不支持,則會(huì)呈現(xiàn)出來

          demo:


          給畫筆添加顏色和樣式

          我們以上面的為基礎(chǔ)稍作修改:

          demo:


          繪制文本

          demo:

          這里要稍微提一下, 也許上面的那些繪制圖形,繪制文本的操作對(duì)你來說都沒有觸動(dòng),因?yàn)樗鼈冸x我們的直接需求似乎還有一定的距離,但我想接下來的這幾個(gè)上下文API你或許有些興趣。

          例如我們可能有一個(gè)需求是載入已有的圖片,對(duì)它截圖(裁剪)后保存為一張新的圖片,這個(gè)時(shí)候我們就可以使用到canvas的繪制圖片,裁剪圖片,保存圖片的API了


          直接繪制已有圖片

          通過canvas上下文對(duì)象的drawImage方法可直接繪制圖片

          我們可以通過下面的一段代碼動(dòng)態(tài)獲取img元素對(duì)象

          廢話不多說,直接上demo!

          在相同目錄下有這么一張圖片

          JS代碼:

          demo:

          我們發(fā)現(xiàn), 圖片加載完成后被寫入了畫布當(dāng)中!


          圖片裁剪功能

          canvas上下文對(duì)象的clip方法可根據(jù)路徑對(duì)canvas畫布進(jìn)行裁剪

          讓我們?cè)谠瓉淼幕A(chǔ)上添加一點(diǎn)東西:

          【注意】clip方法的調(diào)用要在drawImage方法之前,否則不能成功! 也就是說要“先裁剪,再畫圖”

          canvas的保存和導(dǎo)出

          我們通過document.getElementById("canvas")取得的畫布對(duì)象,有一個(gè)toDataURL()方法,可將當(dāng)前畫布作為一張圖片,并返回其base64編碼格式的數(shù)據(jù),這在保存圖片的時(shí)候非常有用

          toDataURL接受兩個(gè)參數(shù):圖片類型和質(zhì)量參數(shù)

          canvas.toDataURL(圖片類型,質(zhì)量參數(shù))

          看下面的例子

          控制臺(tái)輸出了base64格式的數(shù)據(jù):

          我們通過網(wǎng)上的還原軟件看看會(huì)把這個(gè)base64數(shù)據(jù)還原成什么圖片:

          正是我們想要的圖片

          indexedDB — — H5的“瀏覽器數(shù)據(jù)庫”

          indexedDB是存在于瀏覽器中的數(shù)據(jù)庫,它和一般的數(shù)據(jù)庫一樣有寫改刪查的功能,不同之處在于:常見的數(shù)據(jù)庫一般是在服務(wù)器上,并且要求我們的應(yīng)用在線時(shí)才可以工作,而indexedDB使得在離線的時(shí)候讀取數(shù)據(jù)成為了可能。下面,我就給大家介紹一下這個(gè)“駐扎”在瀏覽器上的特殊的數(shù)據(jù)庫吧

          使用open方法創(chuàng)建/打開數(shù)據(jù)庫

          我們首先要做的事情,當(dāng)然是創(chuàng)建(或打開)一個(gè)數(shù)據(jù)庫,這要用到indexedDB對(duì)象的open方法

          它接收兩個(gè)參數(shù): 數(shù)據(jù)庫名稱和數(shù)據(jù)庫版本(第二個(gè)參數(shù)是可選的)

          調(diào)用open方法時(shí)候,如果對(duì)應(yīng)名稱的數(shù)據(jù)庫不存在,則創(chuàng)建一個(gè)新的數(shù)據(jù)庫,如果已存在,則打開已存在的那個(gè)數(shù)據(jù)庫

          需要說明的是, indexedDB里面絕大多數(shù)操作都是異步的, 上述的indexedDB.open并不會(huì)立即創(chuàng)建一個(gè)數(shù)據(jù)庫, 你需要在異步的回調(diào)里面判斷數(shù)據(jù)庫是否創(chuàng)建成功,并對(duì)可能出現(xiàn)的錯(cuò)誤做判斷和處理

          只有在onsuccess回調(diào)中,你才能通過request.result取得創(chuàng)建成功的數(shù)據(jù)庫

          通過open返回的request對(duì)象有三個(gè)回調(diào):

          onsuccess 每次創(chuàng)建/打開數(shù)據(jù)庫時(shí)候都會(huì)調(diào)用

          onerror 創(chuàng)建/打開數(shù)據(jù)庫發(fā)生錯(cuò)誤的時(shí)候調(diào)用

          onupgradeneeded 數(shù)據(jù)庫版本變化的時(shí)候調(diào)用 (onupgradeneeded 是我們唯一可以修改數(shù)據(jù)庫結(jié)構(gòu)的地方)

          open一個(gè)indexedDB數(shù)據(jù)庫后,一般在onupgradeneeded回調(diào)中初始化(或修改)數(shù)據(jù)庫結(jié)構(gòu)(劃重點(diǎn)?。。?/strong>

          這包括兩個(gè)方面的操作:

          1. 通過db.createObjectStore創(chuàng)建對(duì)象存儲(chǔ)空間,并取得ObjectStore對(duì)象(類似于SQL數(shù)據(jù)庫中的建表操作)

          2. 通過調(diào)用ObjectStore.createIndex創(chuàng)建該存儲(chǔ)空間內(nèi)的索引( 以便于提高查詢時(shí)候的速度)

          具體的可看下面的例子:

          運(yùn)行一下, 然后讓我們看看效果:

          打開chrome的Application面板,點(diǎn)擊左欄的Storage下的indexedDB使其展開

          就可以看到我們新創(chuàng)建的phwDataBase數(shù)據(jù)庫, 以及它內(nèi)部的people數(shù)據(jù)存儲(chǔ)空間了

          (右邊展示的是people數(shù)據(jù)存儲(chǔ)空間的具體內(nèi)容,因?yàn)楝F(xiàn)在什么數(shù)據(jù)都還沒添加,所以key和value兩列下是沒有內(nèi)容的)

          看了上面的代碼你可能會(huì)有些疑惑

          onupgradeneeded 和onsuccess回調(diào)的關(guān)系是怎樣的? 為什么我們必須在.onupgradeneeded中初始化數(shù)據(jù)庫的結(jié)構(gòu),而不是在onsuccess中?

          這主要是由兩個(gè)回調(diào)調(diào)用的時(shí)機(jī)決定的:

          1.對(duì) onsuccess回調(diào),在每次數(shù)據(jù)庫創(chuàng)建/打開的時(shí)候都會(huì)調(diào)用(不僅是第一次創(chuàng)建的時(shí)候會(huì)調(diào)用,每次打開的時(shí)候也都會(huì)調(diào)用)

          2. 對(duì)onupgradeneeded回調(diào),在open提供第二個(gè)版本參數(shù)的前提下:

          2.1 第一次調(diào)用open方法創(chuàng)建一個(gè)新的數(shù)據(jù)庫的時(shí)候,onupgradeneeded一定會(huì)被調(diào)用

          2.2 第二次或以后open該數(shù)據(jù)庫,只在版本參數(shù)改變的時(shí)候, onupgradeneeded才會(huì)被調(diào)用

          【注意】在缺少第二個(gè)版本參數(shù)的情況下,onupgradeneeded永遠(yuǎn)不會(huì)被調(diào)用??!

          所以說:

          1.open數(shù)據(jù)庫的時(shí)候,最(yi)好(ding)要帶上第二個(gè)參數(shù)(版本參數(shù))

          2. 修改數(shù)據(jù)庫結(jié)構(gòu)(例如創(chuàng)建和刪除對(duì)象存儲(chǔ)空間以及構(gòu)建和刪除索引。)要在onupgradeneeded回調(diào)中運(yùn)行

          (很顯然每次打開都會(huì)被調(diào)用的onsuccess并不適合用于初始化數(shù)據(jù)庫結(jié)構(gòu))

          indexedDB的具體操作

          首先說一下,在下面的展示例子中,我們的HTML是這樣的

          demo:

          這里要說明一下的是,indexedDB的操作是以事務(wù)為基礎(chǔ)的。 所以,對(duì)存儲(chǔ)空間(objectStore)的操作都要基于事務(wù)來進(jìn)行。 具體點(diǎn)說,就是需要先通過db.transaction()方法取得transaction對(duì)象,然后再通過transaction.objectStore()方法取得目標(biāo)objectStore,再然后才能調(diào)用objectStore的API進(jìn)行“寫改刪查”

          打個(gè)比方, 如果說我們存儲(chǔ)的數(shù)據(jù)是糧食的話, objectStore就是一個(gè)個(gè)并排的糧倉,你可以往里面運(yùn)糧食,也可以把糧食運(yùn)出去, 但你對(duì)“糧食”做任何行為前, 都要和糧倉門前的守衛(wèi)—— transaction(事務(wù))“打聲招呼”,得到準(zhǔn)許才能進(jìn)入糧倉

          有兩個(gè)方法要說一下

          1. transaction方法

          transaction 方法 一般接受兩個(gè)參數(shù),并返回一個(gè)事務(wù)對(duì)象。

          1.1第一個(gè)參數(shù)是一個(gè)數(shù)組, 一個(gè)我們希望事務(wù)能夠操作的objectStore所組成的數(shù)組,如果你希望這個(gè)事務(wù)能夠操作所有的objectStore,那么傳入空數(shù)組[]即可

          1.2 第二個(gè)參數(shù)是一個(gè)字符串, 默認(rèn)是“onlyread”, 如果我們有需要對(duì)數(shù)據(jù)進(jìn)行寫操作的需求的話可傳入“readwrite”

          例如我們下面的一行代碼:

          2. transaction.objectStore方法

          這個(gè)方法接受一個(gè)參數(shù): 指定的objectStore的名稱, 方法返回的是獲取到的objectStore

          例如我們下面的一行代碼:

          寫操作

          寫操作的關(guān)鍵在于objectStore.add(XXX);方法,其中XXX是我們初始化objectStore時(shí)候?qū)懭氲摹爸麈I”

          也就是 var objectStore = db.createObjectStore("people", { keyPath: "id" }); (這段代碼在上面)中keyPath的值——id

          demo:

          點(diǎn)擊“增加數(shù)據(jù)”后彈出

          再看看application面板下的indexedDB:

          我們已經(jīng)成功添加了三條數(shù)據(jù)進(jìn)去了

          刪操作

          刪操作的關(guān)鍵在于objectStore.delete(XXX);方法,其中XXX是我們初始化objectStore時(shí)候?qū)懭氲摹爸麈I”

          也就是 var objectStore = db.createObjectStore("people", { keyPath: "id" }); 中keyPath的值——id

          點(diǎn)擊上面的“刪除數(shù)據(jù)”按鈕(刪除id = 1的數(shù)據(jù))

          再來看看, id為1的那一行已經(jīng)被刪除了

          查操作

          刪操作的關(guān)鍵在于objectStore.get(XXX);方法

          demo:

          點(diǎn)擊“獲取數(shù)據(jù)”按鈕,彈出

          (這里固定查找id為2的數(shù)據(jù))

          遍歷全部數(shù)據(jù)

          遍歷數(shù)據(jù)需要用到游標(biāo)

          通過 objectStore.openCursor()可創(chuàng)建一個(gè)游標(biāo)對(duì)象(cursor), 這個(gè)cursor對(duì)象包含兩個(gè)屬性值: key和value

          key就是我們一直說的那個(gè)“主鍵”, 而value是我們存入的時(shí)候的那個(gè)對(duì)象,通過 cursor.continue方法可以使得游標(biāo)向下移動(dòng)

          點(diǎn)擊“遍歷全部數(shù)據(jù)”按鈕,看看控制臺(tái)

          通過索引查找

          我們通過objectStore.get方法,通過查找主鍵的方式查找對(duì)應(yīng)的對(duì)象數(shù)據(jù)的方式是很快的。

          但如果我們通過非主鍵的數(shù)據(jù)去查找對(duì)應(yīng)的那個(gè)對(duì)象就非常慢了,這個(gè)時(shí)候我們需要?jiǎng)?chuàng)建一個(gè)索引并通過索引來查找, 從而獲得較快的速度:

          點(diǎn)擊“通過索引獲取數(shù)據(jù)”按鈕:

          好! 現(xiàn)在讓我們對(duì)indexedDB做一個(gè)小小的總結(jié):

          1. indexedDB是面向?qū)ο蟮模?與傳統(tǒng)的以二維表為基礎(chǔ)的數(shù)據(jù)庫不同

          2. IndexedDB是一個(gè)事務(wù)型數(shù)據(jù)庫系統(tǒng)

          3. indexedDB大多數(shù)API都是異步的,這意味著調(diào)用一個(gè)方法你不能馬上得到關(guān)鍵的那個(gè)對(duì)象,而在對(duì)應(yīng)的success回調(diào)中才能取得


          拖放事件

          一個(gè)典型的拖放操作是這樣開始的:用戶用鼠標(biāo)選中一個(gè)可拖動(dòng)的(draggable)元素,移動(dòng)鼠標(biāo)到一個(gè)可放置的(droppable)元素,然后釋放鼠標(biāo)。 在操作期間,會(huì)觸發(fā)一系列的拖放類型的事件

          其中我們主要關(guān)心的事件有三個(gè):

          1. ondragstart 發(fā)生在可拖拽(draggable)的元素上, 在元素被拖動(dòng)的時(shí)候調(diào)用

          2. ondragover 發(fā)生在可放置(droppable)的元素上, 當(dāng)某被拖動(dòng)的對(duì)象在可放置對(duì)象范圍內(nèi)(上方)時(shí)觸發(fā)此事件

          3. ondrop 發(fā)生在可放置(droppable)的元素上,當(dāng)釋放鼠標(biāo)使可拖拽元素“放進(jìn)”可放置元素內(nèi)的瞬間觸發(fā)。

          需思考的問題:

          1. 如何使得被拖拽元素可拖拽?(因?yàn)樵啬J(rèn)的行為是不可拖拽的),以及如何使得被放置的容器元素可放置? (因?yàn)樵啬J(rèn)是不可放置的)

          對(duì)前者, 我們可以為元素設(shè)置draggable屬性,并且設(shè)置為true

          對(duì)后者, 我們可以在被放置的容器元素中的ondragover事件里通過event.preventDefault();阻止默認(rèn)行為——禁止放置

          2.如何實(shí)現(xiàn)“脫 — 放”過程的數(shù)據(jù)傳遞?

          這里首先需要知道的是,當(dāng)我們拖動(dòng)一個(gè)圖片到另一個(gè)地方的時(shí)候,我們是不能“直接把圖片拖拽進(jìn)去”的,也就是說,我們還是要通過以下的思路實(shí)現(xiàn)拖放:

          在被放置的元素中取得被拖拽元素的相關(guān)數(shù)據(jù)(如id),然后通過appendChild之類的API實(shí)現(xiàn)添加被拖拽的元素,從而模擬整個(gè)拖拽的過程

          也就是說, 拖拽其實(shí)可分為三個(gè)過程: 拖動(dòng)—傳遞被拖動(dòng)元素的數(shù)據(jù)(如id)—在容器元素中添加該元素

          關(guān)鍵在于如何在被拖動(dòng)元素和被放置元素中傳遞數(shù)據(jù),這可以通過event.dataTransfer對(duì)象來實(shí)現(xiàn)

          dataTransfer可以通過setData方法添加拖動(dòng)數(shù)據(jù),并通過getDate方法取得拖動(dòng)數(shù)據(jù),我們可以在

          ondragstart事件和ondrop事件中調(diào)用這兩個(gè)方法, 實(shí)現(xiàn)關(guān)鍵性的數(shù)據(jù)傳遞。

          具體請(qǐng)看下面的例子:

          拖拽前

          拖拽后

          參考資料:

          HTML5-MDN https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/HTML5

          【完】

          擇器的權(quán)重和優(yōu)先級(jí)

          CSS 選擇器有很多,不同的選擇器的權(quán)重和優(yōu)先級(jí)不一樣,對(duì)于一個(gè)元素,如果存在多個(gè)選擇器,那么就需要根據(jù)權(quán)重來計(jì)算其優(yōu)先級(jí)。

          權(quán)重分為四級(jí),分別是:

          1. 代表內(nèi)聯(lián)樣式,如style="xxx",權(quán)值為 1000;
          2. 代表 ID 選擇器,如#content,權(quán)值為 100;
          3. 代表類、偽類和屬性選擇器,如.content、:hover、[attribute],權(quán)值為 10;
          4. 代表元素選擇器和偽元素選擇器,如div、p,權(quán)值為 1。

          需要注意的是:通用選擇器(\*)、子選擇器(>)和相鄰?fù)x擇器(+)并不在這四個(gè)等級(jí)中,所以他們的權(quán)值都為 0。 權(quán)重值大的選擇器其優(yōu)先級(jí)也高,相同權(quán)重的優(yōu)先級(jí)又遵循后定義覆蓋前面定義的情況。

          #盒模型

          1. 什么是“盒子”

          初學(xué) CSS 的朋友,一開始學(xué) CSS 基礎(chǔ)知識(shí)的時(shí)候一定學(xué)過padding bordermargin,即內(nèi)邊距、邊框和外邊距。它們?nèi)呔蜆?gòu)成了一個(gè)“盒子”。就像我們收到的快遞,本來買了一部小小的手機(jī),收到的卻是那么大一個(gè)盒子。因?yàn)槭謾C(jī)白色的包裝盒和手機(jī)機(jī)器之間有間隔層(內(nèi)邊距),手機(jī)白色盒子有厚度,雖然很?。ㄟ吙颍凶雍涂爝f箱子之間還有一層泡沫板(外邊距)。這就是一個(gè)典型的盒子。

          如上圖,真正的內(nèi)容就是這些文字,文字外圍有 10px 的內(nèi)邊距,5px 的邊框,10px 的外邊距??吹胶凶恿税??

          題目:盒子模型的寬度如何計(jì)算

          2. 固定寬度的盒子

          <div style="padding:10px; border:5px solid blue; margin: 10px; width:300px;">
              文章言簡意賅的介紹的瀏覽器的工作過程,web前端
          </div>
          
          

          如上圖,得到網(wǎng)頁效果之后,我們可以用截圖工具來量一下文字內(nèi)容的寬度。發(fā)現(xiàn),文字內(nèi)容的寬度剛好是 300px,也就是我們?cè)O(shè)置的寬度。

          因此,在盒子模型中,我們?cè)O(shè)置的寬度都是內(nèi)容寬度,不是整個(gè)盒子的寬度。而整個(gè)盒子的寬度是:(內(nèi)容寬度 + border寬度 + padding寬度 + margin寬度)之和。這樣我們改四個(gè)中的其中一個(gè),都會(huì)導(dǎo)致盒子寬度的改變。這對(duì)我們來說不友好。

          沒關(guān)系,這個(gè)東西不友好早就有人發(fā)現(xiàn)了,而且已經(jīng)解決,下文再說。

          3. 充滿父容器的盒子

          默認(rèn)情況下,divdisplay:block,寬度會(huì)充滿整個(gè)父容器。如下圖:

          <div style="padding:10px; border:5px solid blue; margin: 10px; width:300px;">
              之前看過一篇文章,叫做《瀏覽器工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘》,
              文章言簡意賅的介紹的瀏覽器的工作過程,web前端
              之前看過一篇文章,叫做《瀏覽器工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘》,
              文章言簡意賅的介紹的瀏覽器的工作過程,web前端
          </div>
          
          

          • 但是別忘記,這個(gè) div 是個(gè)盒子模型,它的整個(gè)寬度包括(內(nèi)容寬度 + border寬度 + padding寬度 + margin寬度),整個(gè)的寬度充滿父容器。
          • 問題就在這里。如果父容器寬度不變,我們手動(dòng)增大marginborderpadding其中一項(xiàng)的寬度值,都會(huì)導(dǎo)致內(nèi)容寬度的減少。極端情況下,如果內(nèi)容的寬度壓縮到不能再壓縮了(例如一個(gè)字的寬度),那么瀏覽器會(huì)強(qiáng)迫增加父容器的寬度。這可不是我們想要看到的。

          4. 包裹內(nèi)容的盒子

          這種情況下比較簡單,內(nèi)容的寬度按照內(nèi)容計(jì)算,盒子的寬度將在內(nèi)容寬度的基礎(chǔ)上再增加(padding寬度 + border寬度 + margin寬度)之和。

          <div style="padding:10px; border:5px solid blue; margin: 10px; width:300px;">
              之前看過一篇文章,叫做《瀏覽器工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘》
          </div>
          
          

          5. box-sizing:border-box

          前面提到,為盒子模型設(shè)置寬度,結(jié)果只是設(shè)置了內(nèi)容的寬度,這個(gè)不合理。如何解決這一問題?答案就是為盒子指定樣式:box-sizing:border-box。

          <div style="padding:10px; border:5px solid blue; margin: 10px; width:300px; box-sizing:border-box;">
              之前看過一篇文章,叫做《瀏覽器工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘》
          </div>
          
          

          上圖中,為div設(shè)置了box-sizing:border-box之后,300px 的寬度是內(nèi)容 + padding + 邊框的寬度(不包括margin,這樣就比較符合我們的實(shí)際要求了。建議大家在為系統(tǒng)寫 CSS 時(shí)候,第一個(gè)樣式是:

          * {
              box-sizing:border-box;
          }
          

          大名鼎鼎的 Bootstrap 也把box-sizing:border-box加入到它的*選擇器中,我們?yōu)槭裁床贿@樣做呢?

          6. 縱向 margin 重疊

          這里提到 margin,就不得不提一下 margin 的這一特性——縱向重疊。如<p>的縱向 margin 是 16px,那么兩個(gè)<p>之間縱向的距離是多少?—— 按常理來說應(yīng)該是 16 + 16 = 32px,但是答案仍然是 16px。因?yàn)榭v向的 margin 是會(huì)重疊的,如果兩者不一樣大的話,大的會(huì)把小的“吃掉”。

          #浮動(dòng)float

          float 用于網(wǎng)頁布局比較多,使用起來也比較簡單,這里總結(jié)了一些比較重要、需要注意的知識(shí)點(diǎn),供大家參考。

          1. 誤解和誤用

          float 被設(shè)計(jì)出來的初衷是用于文字環(huán)繞效果,即一個(gè)圖片一段文字,圖片float:left之后,文字會(huì)環(huán)繞圖片。

          <div>
              <img src="image/1.png" style="float:left">
              一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字一段文字
          </div>
          

          但是,后來大家發(fā)現(xiàn)結(jié)合float + div可以實(shí)現(xiàn)之前通過table實(shí)現(xiàn)的網(wǎng)頁布局,因此就被“誤用”于網(wǎng)頁布局了。

          題目:為何 float 會(huì)導(dǎo)致父元素塌陷?

          2. 破壞性

          float破壞性 —— float 破壞了父標(biāo)簽的原本結(jié)構(gòu),使得父標(biāo)簽出現(xiàn)了坍塌現(xiàn)象。導(dǎo)致這一現(xiàn)象的最根本原因在于:被設(shè)置了 float 的元素會(huì)脫離文檔流。其根本原因在于 float 的設(shè)計(jì)初衷是解決文字環(huán)繞圖片的問題。大家要記住 float 的這個(gè)影響。

          3. 包裹性

          包裹性也是 float 的一個(gè)非常重要的特性,大家用 float 時(shí)一定要熟知這一特性。咱們還是先從一個(gè)小例子看起:

          如上圖,普通的 div 如果沒有設(shè)置寬度,它會(huì)撐滿整個(gè)屏幕,在之前的盒子模型那一節(jié)也講到過。而如果給 div 增加float:left之后,它突然變得緊湊了,寬度發(fā)生了變化,把內(nèi)容中的三個(gè)字包裹了——這就是包裹性。為 div 設(shè)置了 float 之后,其寬度會(huì)自動(dòng)調(diào)整為包裹住內(nèi)容寬度,而不是撐滿整個(gè)父容器。

          • 注意,此時(shí) div 雖然體現(xiàn)了包裹性,但是它的 display 樣式是沒有變化的,還是display: block
          • float 為什么要具有包裹性?其實(shí)答案還是得從 float 的設(shè)計(jì)初衷來尋找,float 是被設(shè)計(jì)用于實(shí)現(xiàn)文字環(huán)繞效果的。文字環(huán)繞圖片比較好理解,但是如果想要讓文字環(huán)繞一個(gè) div 呢?此時(shí) div 不被“包裹”起來的話,就無法實(shí)現(xiàn)環(huán)繞效果了。

          4. 清空格

          float 還有一個(gè)大家可能不是很熟悉的特性——清空格。按照慣例,咱還是先舉例子說明。

          <div style="border: 2px solid blue; padding:3px;">
              <img src="image/1.png"/>
              <img src="image/2.png"/>
              <img src="image/3.png"/>
              <img src="image/4.png"/>
          </div>
          

          加上float:left之后:

          • 上面第一張圖中,正常的 img 中間是會(huì)有空格的,因?yàn)槎鄠€(gè) img 標(biāo)簽會(huì)有換行,而瀏覽器識(shí)別換行為空格,這也是很正常的。第二張圖中,為 img 增加了float:left的樣式,這就使得 img 之間沒有了空格,4 個(gè) img 緊緊挨著。
          • 如果大家之前沒注意,現(xiàn)在想想之前寫過的程序,是不是有這個(gè)特性。為什么 float 適合用于網(wǎng)頁排版(俗稱“砌磚頭”)?就是因?yàn)?float 排版出來的網(wǎng)頁嚴(yán)絲合縫,中間連個(gè)蒼蠅都飛不進(jìn)去。
          • “清空格”這一特性的根本原因是 float 會(huì)導(dǎo)致節(jié)點(diǎn)脫離文檔流結(jié)構(gòu)。它都不屬于文檔流結(jié)構(gòu)了,那么它身邊的什么換行、空格就都和它沒了關(guān)系,它就盡量往一邊靠攏,能靠多近就靠多近,這就是清空格的本質(zhì)。

          題目:手寫 clearfix

          5. clearfix

          清除浮動(dòng)的影響,一般使用的樣式如下,統(tǒng)稱clearfix代碼。所有 float 元素的父容器,一般情況下都應(yīng)該加clearfix這個(gè) class。

          .clearfix:after {
              content: '';
              display: table;
              clear: both;
          }
          .clearfix {
              *zoom: 1; /* 兼容 IE 低版本 */
          }
          
          <div class="clearfix">
              <img src="image/1.png" style="float: left"/>
              <img src="image/2.png" style="float: left"/>
          </div>
          
          

          6. 小結(jié)

          float 的設(shè)計(jì)初衷是解決文字環(huán)繞圖片的問題,后來誤打誤撞用于做布局,因此有許多不合適或者需要注意的地方,上文基本都講到了需要的知識(shí)點(diǎn)。如果是剛開始接觸 float 的同學(xué),學(xué)完上面的基礎(chǔ)知識(shí)之后,還應(yīng)該做一些練習(xí)實(shí)戰(zhàn)一下 —— 經(jīng)典的“圣杯布局”和“雙飛翼布局”。這里就不再展開講了,網(wǎng)上資料非常多,例如淺談面試中??嫉膬煞N經(jīng)典布局——圣杯與雙飛翼(此文的最后兩張圖清晰地展示了這兩種布局)。

          #定位 position

          position 用于網(wǎng)頁元素的定位,可設(shè)置 static/relative/absolute/fixed 這些值,其中 static 是默認(rèn)值,不用介紹。

          題目:relative 和 absolute 有何區(qū)別?

          1. relative

          相對(duì)定位 relative 可以用一個(gè)例子很輕松地演示出來。例如我們寫 4 個(gè)<p>,出來的樣子大家不用看也能知道。

          <p>第一段文字</p>
          <p>第二段文字</p>
          <p>第三段文字</p>
          <p>第四段文字</p>
          

          然后我們?cè)诘谌齻€(gè)<p>上面,加上position:relative并且設(shè)置lefttop值,看這個(gè)<p>有什么變化。

          <p>第一段文字</p>
          <p>第二段文字</p>
          <p style="position:relative; top: 10px; left: 10px">第三段文字</p>
          <p>第四段文字</p>
          

          上圖中,大家應(yīng)該要識(shí)別出兩個(gè)信息(相信大部分人會(huì)忽略第二個(gè)信息)

          • 第三個(gè)<p>發(fā)生了位置變化,分別向右向下移動(dòng)了10px;
          • 其他的三個(gè)<p>位置沒有發(fā)生變化,這一點(diǎn)也很重要。

          可見,relative 會(huì)導(dǎo)致自身位置的相對(duì)變化,而不會(huì)影響其他元素的位置、大小。這是 relative 的要點(diǎn)之一。還有第二個(gè)要點(diǎn),就是 relative 產(chǎn)生一個(gè)新的定位上下文。下文有關(guān)于定位上下文的詳細(xì)介紹,這里可以先通過一個(gè)例子來展示一下區(qū)別:

          注意看這兩圖的區(qū)別,下文將有解釋。

          2. absolute

          還是先寫一個(gè)基本的 demo。

          <p>第一段文字</p>
          <p>第二段文字</p>
          <p style="background: yellow">第三段文字</p>
          <p>第四段文字</p>
          
          

          然后,我們把第三個(gè)<p>改為position:absolute;,看看會(huì)發(fā)生什么變化。

          從上面的結(jié)果中,我們能看出幾點(diǎn)信息:

          • absolute 元素脫離了文檔結(jié)構(gòu)。和 relative 不同,其他三個(gè)元素的位置重新排列了。只要元素會(huì)脫離文檔結(jié)構(gòu),它就會(huì)產(chǎn)生破壞性,導(dǎo)致父元素坍塌。(此時(shí)你應(yīng)該能立刻想起來,float 元素也會(huì)脫離文檔結(jié)構(gòu)。)
          • absolute 元素具有“包裹性”。之前<p>的寬度是撐滿整個(gè)屏幕的,而此時(shí)<p>的寬度剛好是內(nèi)容的寬度。
          • absolute 元素具有“跟隨性”。雖然 absolute 元素脫離了文檔結(jié)構(gòu),但是它的位置并沒有發(fā)生變化,還是老老實(shí)實(shí)地呆在它原本的位置,因?yàn)槲覀兇藭r(shí)沒有設(shè)置 top、left 的值。
          • absolute 元素會(huì)懸浮在頁面上方,會(huì)遮擋住下方的頁面內(nèi)容。

          最后,通過給 absolute元素設(shè)置 top、left 值,可自定義其內(nèi)容,這個(gè)都是平時(shí)比較常用的了。這里需要注意的是,設(shè)置了 top、left 值時(shí),元素是相對(duì)于最近的定位上下文來定位的,而不是相對(duì)于瀏覽器定位。

          3. fixed

          其實(shí) fixedabsolute 是一樣的,唯一的區(qū)別在于:absolute 元素是根據(jù)最近的定位上下文確定位置,而 fixed 根據(jù) window (或者 iframe)確定位置。

          題目:relative、absolutefixed 分別依據(jù)誰來定位?

          4. 定位上下文

          relative 元素的定位永遠(yuǎn)是相對(duì)于元素自身位置的,和其他元素沒關(guān)系,也不會(huì)影響其他元素。

          fixed 元素的定位是相對(duì)于 window (或者 iframe)邊界的,和其他元素沒有關(guān)系。但是它具有破壞性,會(huì)導(dǎo)致其他元素位置的變化。

          absolute 的定位相對(duì)于前兩者要復(fù)雜許多。如果為 absolute 設(shè)置了 topleft,瀏覽器會(huì)根據(jù)什么去確定它的縱向和橫向的偏移量呢?答案是瀏覽器會(huì)遞歸查找該元素的所有父元素,如果找到一個(gè)設(shè)置了position:relative/absolute/fixed的元素,就以該元素為基準(zhǔn)定位,如果沒找到,就以瀏覽器邊界定位。如下兩個(gè)圖所示:


          #flex布局

          布局的傳統(tǒng)解決方案基于盒子模型,依賴 display 屬性 + position 屬性 + float 屬性。它對(duì)于那些特殊布局非常不方便,比如,垂直居中(下文會(huì)專門講解)就不容易實(shí)現(xiàn)。在目前主流的移動(dòng)端頁面中,使用 flex 布局能更好地完成需求,因此 flex 布局的知識(shí)是必須要掌握的。

          1. 基本使用

          任何一個(gè)容器都可以使用 flex 布局,代碼也很簡單。

          <style type="text/css">
              .container {
                display: flex;
              }
              .item {
                  border: 1px solid #000;
                  flex: 1;
              }
          </style>
          
          <div class="container">
              <div class="item">aaa</div>
              <div class="item" style="flex: 2">bbb</div>
              <div class="item">ccc</div>
              <div class="item">ddd</div>
          </div>
          
          

          注意,第三個(gè)<div>flex: 2,其他的<div>flex: 1,這樣第二個(gè)<div>的寬度就是其他的<div>的兩倍。

          2. 設(shè)計(jì)原理

          設(shè)置了display: flex的元素,我們稱為“容器”(flex container),其所有的子節(jié)點(diǎn)我們稱為“成員”(flex item)。容器默認(rèn)存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點(diǎn))叫做 main start,結(jié)束位置叫做 main end;交叉軸的開始位置叫做 cross start,結(jié)束位置叫做cross end。項(xiàng)目默認(rèn)沿主軸排列。單個(gè)項(xiàng)目占據(jù)的主軸空間叫做 main size,占據(jù)的交叉軸空間叫做 cross size。

          將以上文字和圖片結(jié)合起來,再詳細(xì)看一遍,這樣就能理解 flex 的設(shè)計(jì)原理,才能更好地實(shí)際使用。

          3. 設(shè)置主軸的方向

          flex-direction可決定主軸的方向,有四個(gè)可選值:

          • row(默認(rèn)值):主軸為水平方向,起點(diǎn)在左端。
          • row-reverse:主軸為水平方向,起點(diǎn)在右端。
          • column:主軸為垂直方向,起點(diǎn)在上沿。
          • column-reverse:主軸為垂直方向,起點(diǎn)在下沿。
          .box {
            flex-direction: column-reverse| column | row | row-reverse;
          }
          

          以上代碼設(shè)置的主軸方向,將依次對(duì)應(yīng)下圖:

          4. 設(shè)置主軸的對(duì)齊方式

          justify-content屬性定義了項(xiàng)目在主軸上的對(duì)齊方式,值如下:

          • flex-start(默認(rèn)值):向主軸開始方向?qū)R。
          • flex-end:向主軸結(jié)束方向?qū)R。
          • center: 居中。
          • space-between:兩端對(duì)齊,項(xiàng)目之間的間隔都相等。
          • space-around:每個(gè)項(xiàng)目兩側(cè)的間隔相等。所以,項(xiàng)目之間的間隔比項(xiàng)目與邊框的間隔大一倍。
          .box {
              justify-content: flex-start | flex-end | center | space-between | space-around;
          }
          

          5. 交叉軸的對(duì)齊方式

          align-items屬性定義項(xiàng)目在交叉軸上如何對(duì)齊,值如下:

          • flex-start:交叉軸的起點(diǎn)對(duì)齊。
          • flex-end:交叉軸的終點(diǎn)對(duì)齊。
          • center:交叉軸的中點(diǎn)對(duì)齊。
          • baseline: 項(xiàng)目的第一行文字的基線對(duì)齊。
          • stretch(默認(rèn)值):如果項(xiàng)目未設(shè)置高度或設(shè)為 auto,將占滿整個(gè)容器的高度。
          .box {
              align-items: flex-start | flex-end | center | baseline | stretch;
          }
          

          #如何實(shí)現(xiàn)居中對(duì)齊?

          題目:如何實(shí)現(xiàn)水平居中?

          1. 水平居中

          inline 元素用text-align: center;即可,如下:

          .container {
             text-align: center;
          }
          

          block 元素可使用margin: auto;,PC 時(shí)代的很多網(wǎng)站都這么搞。

          .container {
              text-align: center; 
          }
          .item {
              width: 1000px;
              margin: auto; 
          }
          

          絕對(duì)定位元素可結(jié)合leftmargin實(shí)現(xiàn),但是必須知道寬度。

          .container {
              position: relative;
              width: 500px;
          }
          .item {
              width: 300px;
              height: 100px;
              position: absolute;
              left: 50%;
              margin: -150px;
          }
          
          

          題目:如何實(shí)現(xiàn)垂直居中?

          2. 垂直居中

          inline 元素可設(shè)置line-height的值等于height值,如單行文字垂直居中:

          .container {
             height: 50px;
             line-height: 50px;
          }
          

          絕對(duì)定位元素,可結(jié)合leftmargin實(shí)現(xiàn),但是必須知道尺寸。

          • 優(yōu)點(diǎn):兼容性好
          • 缺點(diǎn):需要提前知道尺寸
          .container {
              position: relative;
              height: 200px;
          }
          .item {
              width: 80px;
              height: 40px;
              position: absolute;
              left: 50%;
              top: 50%;
              margin-top: -20px;
              margin-left: -40px;
          }
          

          絕對(duì)定位可結(jié)合transform實(shí)現(xiàn)居中。

          • 優(yōu)點(diǎn):不需要提前知道尺寸
          • 缺點(diǎn):兼容性不好
          .container {
              position: relative;
              height: 200px;
          }
          .item {
              width: 80px;
              height: 40px;
              position: absolute;
              left: 50%;
              top: 50%;
              transform: translate(-50%, -50%);
              background: blue;
          }
          
          

          絕對(duì)定位結(jié)合margin: auto,不需要提前知道尺寸,兼容性好。

          .container {
              position: relative;
              height: 300px;
          }
          .item {
              width: 100px;
              height: 50px;
              position: absolute;
              left: 0;
              top: 0;
              right: 0;
              bottom: 0;
              margin: auto;
          }
          

          其他的解決方案還有,不過沒必要掌握太多,能說出上文的這幾個(gè)解決方案即可。

          #理解語義化

          題目:如何理解 HTML 語義化?

          所謂“語義”就是為了更易讀懂,這要分兩部分:

          • 讓人(寫程序、讀程序)更易讀懂
          • 讓機(jī)器(瀏覽器、搜索引擎)更易讀懂

          1. 讓人更易讀懂

          • 對(duì)于人來說,代碼可讀性、語義化就是一個(gè)非常廣泛的概念了,例如定義 JS 變量的時(shí)候使用更易讀懂的名稱,定義 CSS class 的時(shí)候也一樣,例如length list等,而不是使用a b這種誰都看不懂的名稱。
          • 不過我們平常考查的“語義化”并不會(huì)考查這么廣義、這么泛的問題,而是考查 HTML 的語義化,是為了更好地讓機(jī)器讀懂 HTML。

          2. 讓機(jī)器更易讀懂

          • HTML 符合 XML 標(biāo)準(zhǔn),但又和 XML 不一樣 —— HTML 不允許像 XML 那樣自定義標(biāo)簽名稱,HTML 有自己規(guī)定的標(biāo)簽名稱。問題就在這里 —— HTML 為何要自己規(guī)定那么多標(biāo)簽名稱呢,例如p div h1 ul等 —— 就是為了語義化。其實(shí),如果你精通 CSS 的話,你完全可以全部用<div>標(biāo)簽來實(shí)現(xiàn)所有的網(wǎng)頁效果,其他的p h1 ul等標(biāo)簽可以一個(gè)都不用。但是我們不推薦這么做,這樣做就失去了 HTML 語義化的意義。
          • 拿搜索引擎來說,爬蟲下載到我們網(wǎng)頁的 HTML 代碼,它如何更好地去理解網(wǎng)頁的內(nèi)容呢?—— 就是根據(jù) HTML 既定的標(biāo)簽。h1標(biāo)簽就代表是標(biāo)題;p里面的就是段落詳細(xì)內(nèi)容,權(quán)重肯定沒有標(biāo)題高;ul里面就是列表;strong就是加粗的強(qiáng)調(diào)的內(nèi)容 …… 如果我們不按照 HTML 語義化來寫,全部都用<div>標(biāo)簽,那搜索引擎將很難理解我們網(wǎng)頁的內(nèi)容。
          • 為了加強(qiáng) HTML 語義化,HTML5 標(biāo)準(zhǔn)中又增加了header section article等標(biāo)簽。因此,書寫 HTML 時(shí),語義化是非常重要的,否則 W3C 也沒必要辛辛苦苦制定出這些標(biāo)準(zhǔn)來。

          #CSS3 動(dòng)畫

          CSS3 可以實(shí)現(xiàn)動(dòng)畫,代替原來的 Flash 和 JavaScript 方案。

          首先,使用@keyframes定義一個(gè)動(dòng)畫,名稱為testAnimation,如下代碼,通過百分比來設(shè)置不同的 CSS 樣式,規(guī)定動(dòng)畫的變化。所有的動(dòng)畫變化都可以這么定義出來。

          @keyframes testAnimation
          {
              0%   {background: red; left:0; top:0;}
              25%  {background: yellow; left:200px; top:0;}
              50%  {background: blue; left:200px; top:200px;}
              75%  {background: green; left:0; top:200px;}
              100% {background: red; left:0; top:0;}
          }
          
          

          后,針對(duì)一個(gè) CSS 選擇器來設(shè)置動(dòng)畫,例如針對(duì)div元素設(shè)置動(dòng)畫,如下:

          div {
              width: 100px;
              height: 50px;
              position: absolute;
          
              animation-name: myfirst;
              animation-duration: 5s;
          }
          
          

          animation-name對(duì)應(yīng)到動(dòng)畫名稱,animation-duration是動(dòng)畫時(shí)長,還有其他屬性:

          • animation-timing-function:規(guī)定動(dòng)畫的速度曲線。默認(rèn)是ease
          • animation-delay:規(guī)定動(dòng)畫何時(shí)開始。默認(rèn)是 0
          • animation-iteration-count:規(guī)定動(dòng)畫被播放的次數(shù)。默認(rèn)是 1
          • animation-direction:規(guī)定動(dòng)畫是否在下一周期逆向地播放。默認(rèn)是normal
          • animation-play-state :規(guī)定動(dòng)畫是否正在運(yùn)行或暫停。默認(rèn)是running
          • animation-fill-mode:規(guī)定動(dòng)畫執(zhí)行之前和之后如何給動(dòng)畫的目標(biāo)應(yīng)用,默認(rèn)是none,保留在最后一幀可以用forwards

          題目:CSS 的transitionanimation有何區(qū)別?

          首先transitionanimation都可以做動(dòng)效,從語義上來理解,transition是過渡,由一個(gè)狀態(tài)過渡到另一個(gè)狀態(tài),比如高度100px過渡到200px;而animation是動(dòng)畫,即更專業(yè)做動(dòng)效的,animation有幀的概念,可以設(shè)置關(guān)鍵幀keyframe,一個(gè)動(dòng)畫可以由多個(gè)關(guān)鍵幀多個(gè)狀態(tài)過渡組成,另外animation也包含上面提到的多個(gè)屬性。

          #重繪和回流

          重繪和回流是面試題經(jīng)??嫉念}目,也是性能優(yōu)化當(dāng)中應(yīng)該注意的點(diǎn),下面筆者簡單介紹下。

          • 重繪:指的是當(dāng)頁面中的元素不脫離文檔流,而簡單地進(jìn)行樣式的變化,比如修改顏色、背景等,瀏覽器重新繪制樣式
          • 回流:指的是處于文檔流中 DOM 的尺寸大小、位置或者某些屬性發(fā)生變化時(shí),導(dǎo)致瀏覽器重新渲染部分或全部文檔的情況

          相比之下,回流要比重繪消耗性能開支更大。另外,一些屬性的讀取也會(huì)引起回流,比如讀取某個(gè) DOM 的高度和寬度,或者使用getComputedStyle方法。在寫代碼的時(shí)候要避免回流和重繪。比如在筆試中可能會(huì)遇見下面的題目:

          題目:找出下面代碼的優(yōu)化點(diǎn),并且優(yōu)化它

          var data = ['string1', 'string2', 'string3'];
          for(var i = 0; i < data.length; i++){
              var dom = document.getElementById('list');
              dom.innerHTML += '<li>' + data[i] + '</li>';
          }
          
          

          上面的代碼在循環(huán)中每次都獲取dom,然后對(duì)其內(nèi)部的 HTML 進(jìn)行累加li,每次都會(huì)操作 DOM 結(jié)構(gòu),可以改成使用documentFragment或者先遍歷組成 HTML 的字符串,最后操作一次innerHTML。

          #小結(jié)

          本小節(jié)總結(jié)了 CSS 和 HTML 常考的知識(shí)點(diǎn),包括 CSS 中比較重要的定位、布局的知識(shí),也介紹了一些 CSS3 的知識(shí)點(diǎn)概念和題目,以及 HTML 的語義化。


          主站蜘蛛池模板: 波多野结衣AV一区二区三区中文 | 亚洲欧美日韩国产精品一区| 日韩精品一区二区三区国语自制| 秋霞鲁丝片一区二区三区| 丰满人妻一区二区三区视频| 波多野结衣一区二区三区88| 亚洲丰满熟女一区二区v| 久久青草国产精品一区| 国产高清在线精品一区二区三区| 日韩精品无码一区二区中文字幕 | 亚洲一区二区三区免费观看| 国产麻豆剧果冻传媒一区| 末成年女AV片一区二区| 亚洲bt加勒比一区二区| 久久国产一区二区三区| 亚洲综合一区二区精品导航| 一本一道波多野结衣AV一区| 国产一区二区三区小说| 无码人妻少妇色欲AV一区二区| 一区二区视频在线免费观看| 无码夜色一区二区三区| 国产午夜精品一区二区三区极品| 白丝爆浆18禁一区二区三区 | 国产视频一区在线观看| 亚洲一区AV无码少妇电影| 国产一区二区在线观看app| 久久久人妻精品无码一区| 日本高清成本人视频一区| 91午夜精品亚洲一区二区三区| 无码国产精品一区二区免费式直播| 无码乱码av天堂一区二区| 精品国产一区二区三区AV性色| 国产福利电影一区二区三区久久久久成人精品综合 | 国产一区二区在线| 国产成人一区二区精品非洲| 国产一区二区免费| 国产精品电影一区二区三区| 日本在线一区二区| 精品一区二区三区3d动漫| 国产成人精品第一区二区| 精品无码人妻一区二区三区不卡|