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 最近中文字幕视频在线资源,免费播放一区二区三区,国产日韩精品视频

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML5與HTML4的區別

          TML5是以HTML4為基礎的,并對HTML4進行了大量的修改。

          首先看看語法上的改變、

          對于HTML4而言,HTML5在語法上發生了很大的變化。對于這些變化,有些人開始有點不安,是不是又要開始重新學習HTML語言了?但是,HTML5中的語法變化,與其他開發語言中的語法變化有根本的不同。因為在HTML5之前幾乎沒有符合標準規范的web瀏覽器導致的。

          HTML的語法是在SGML語言的基礎上建立起來的。但是SGML語法非常之復雜,要開發能夠解析SGML語法的程序也很不容易,因此很多瀏覽器都不包含SGML的分析器。因此,雖然HTML基本上遵從SGML的語法,但是對于HTML的執行在各瀏覽器之間并沒有一個統一的標準。

          為解決各瀏覽器之間的互兼容性和互操作性,就得要有一個統一的標準,所以HTML5就是圍繞這個web標準,重新定義了一套在現有HTML的基礎上修改而來的語法,以便各瀏覽器在運行HTML的時候能夠符合一個通用標準。

          于HTML5 淺析

          前言:

          作為一名Web開發者,可能你并沒有對這個“H5”這個字眼投入太多的關注,但實際上它早已不知不覺進入到你的開發中,并且總有一天會讓你不得不正視它,了解它并運用它

          打個比方:《海賊王》中的主角路飛在“頂上戰爭兩年前”,會在一些危急關頭“不經意”地使用霸王色霸氣,但對”霸氣“的結構體系和具體運用都不太了解,這讓他在香波地群島等諸多重大戰役中大吃苦頭。此后, 他不惜花費兩年時間跟隨雷利修煉霸氣。因為,如果不去了解這個嶄新的戰斗方法的話,他們在殘酷的新世界一天也生存不了。


          為什么學習HTML5?

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

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

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


          H5中的知識點分布

          在下面, 我將學習H5中的知識點分成兩類:主要知識點和針對特定功能的知識點,其中對主要知識點的部分,從學習成本的角度對其進行了難度分級

          (僅屬個人觀點!如有改進意見,歡迎討論)

          一.主要知識點

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

          相對容易的部分:

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

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

          3. history關于歷史狀態管理的API (相對容易)

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

          相對較難的部分:

          5. Web Worker (相對較難)

          6. canvas (相對較難)

          7. indexedDB (相對較難)

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

          9. Web Sockets (相對較難)

          二. 針對特定功能的知識點

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

          1. 對音視頻的支持

          2. Camera API (操作攝像頭)

          3. WebGL (3D圖像)

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

          本文主要講述H5中主要知識點中,學習成本相對較高的四個點(僅個人觀點):

          一.Web Worker

          二.canvas

          三.indexedDB

          四.拖放操作

          【注意】因為下面介紹的H5的特性在一些比較老的瀏覽器里可能遇到兼容性問題,所以你在使用前必須要能力檢測,例如這樣


          Web Worker

          Web Worker的機制讓你能夠創建一個在后臺線程運行的腳本,這個腳本不會對我們當前執行任務的腳本造成任何干擾(例如阻塞),同時Web Worker提供了一套API使你能夠在當前腳本和后臺腳本間進行數據的互相傳輸(worker)

          “一套API, 兩個對象”

          我們現在已知的關于Web Worker的機制是: 有一個當前腳本, 和一個在后臺運行的worker腳本,所以我們問題的關鍵就落在了這兩個腳本的通信(數據交互)上

          通過

          生成了“兩個對象”(你可能會問:為什么是兩個不是一個呢?請往下看

          “第一個”對象是我們在當前腳本中通過構造函數顯式創建出來的worker對象,它擁有一套API:postMessage和onmessage,通過postMessage方法可以向worker腳本(上文worker.js)發送數據, 通過onmessage方法可以從worker腳本接收數據

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

          【注意】關于DedicatedWorkerGlobalScope

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

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

          所以現在數據傳遞方向有兩條:

          1. 調用當前腳本中worker對象的postMessage方法, 然后在Web Worker腳本(上文的worker.js)中通過onmessage這個回調方法接收數據

          2. 調用Web Worker腳本中的this.postMessage方法(this指向DedicatedWorkerGlobalScope),然后在當前腳本中worker對象的onmessage回調方法接收數據

          看到這里可能有點懵,來讓我們通過一個例子看看1中的數據傳遞:

          先看示例吧,這是我們的目錄結構

          index.html:

          main.js:

          worker.js:

          點擊按鈕后,在main.js中調用worker對象的postMessage方法, 這個數據就被發給了work.js中的全局變量對象DedicatedWorkerGlobalScope, 所以我們在work,js中通過this.onmessage接收數據并輸出


          postMessage中的參數會“原封不動”傳遞給onmessage中的event.data

          【注意】postMessage傳遞的參數會被“原封不動”地傳遞給onmessage中event對象的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}


          當前任務腳本和worker腳本完整的通信流程

          我們上面的例子展現的是從當前任務腳本向worker腳本傳遞數據,那么同樣的道理,我們也能從work腳本向當前任務腳本傳遞數據(方式相同)

          例子:

          index.html:

          同上

          main.js:

          worker.js:

          demo如下

          點擊傳遞數據輸出:

          canvas

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

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

          假設這是我們的HTML:

          這樣取得上下文對象:


          繪制基本形狀

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

          上面的x,y代表相對于canvas畫布左上角的橫縱坐標:

          例子:

          html部分:

          JS部分:

          【注意】. canvas標簽內的內容(例如上面的文本)是否呈現取決于瀏覽器是否支持canvas,如果支持,則不出現,如果不支持,則會呈現出來

          demo:


          給畫筆添加顏色和樣式

          我們以上面的為基礎稍作修改:

          demo:


          繪制文本

          demo:

          這里要稍微提一下, 也許上面的那些繪制圖形,繪制文本的操作對你來說都沒有觸動,因為它們離我們的直接需求似乎還有一定的距離,但我想接下來的這幾個上下文API你或許有些興趣。

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


          直接繪制已有圖片

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

          我們可以通過下面的一段代碼動態獲取img元素對象

          廢話不多說,直接上demo!

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

          JS代碼:

          demo:

          我們發現, 圖片加載完成后被寫入了畫布當中!


          圖片裁剪功能

          canvas上下文對象的clip方法可根據路徑對canvas畫布進行裁剪

          讓我們在原來的基礎上添加一點東西:

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

          canvas的保存和導出

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

          toDataURL接受兩個參數:圖片類型和質量參數

          canvas.toDataURL(圖片類型,質量參數)

          看下面的例子

          控制臺輸出了base64格式的數據:

          我們通過網上的還原軟件看看會把這個base64數據還原成什么圖片:

          正是我們想要的圖片

          indexedDB — — H5的“瀏覽器數據庫”

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

          使用open方法創建/打開數據庫

          我們首先要做的事情,當然是創建(或打開)一個數據庫,這要用到indexedDB對象的open方法

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

          調用open方法時候,如果對應名稱的數據庫不存在,則創建一個新的數據庫,如果已存在,則打開已存在的那個數據庫

          需要說明的是, indexedDB里面絕大多數操作都是異步的, 上述的indexedDB.open并不會立即創建一個數據庫, 你需要在異步的回調里面判斷數據庫是否創建成功,并對可能出現的錯誤做判斷和處理

          只有在onsuccess回調中,你才能通過request.result取得創建成功的數據庫

          通過open返回的request對象有三個回調:

          onsuccess 每次創建/打開數據庫時候都會調用

          onerror 創建/打開數據庫發生錯誤的時候調用

          onupgradeneeded 數據庫版本變化的時候調用 (onupgradeneeded 是我們唯一可以修改數據庫結構的地方)

          open一個indexedDB數據庫后,一般在onupgradeneeded回調中初始化(或修改)數據庫結構(劃重點!!)

          這包括兩個方面的操作:

          1. 通過db.createObjectStore創建對象存儲空間,并取得ObjectStore對象(類似于SQL數據庫中的建表操作)

          2. 通過調用ObjectStore.createIndex創建該存儲空間內的索引( 以便于提高查詢時候的速度)

          具體的可看下面的例子:

          運行一下, 然后讓我們看看效果:

          打開chrome的Application面板,點擊左欄的Storage下的indexedDB使其展開

          就可以看到我們新創建的phwDataBase數據庫, 以及它內部的people數據存儲空間了

          (右邊展示的是people數據存儲空間的具體內容,因為現在什么數據都還沒添加,所以key和value兩列下是沒有內容的)

          看了上面的代碼你可能會有些疑惑

          onupgradeneeded 和onsuccess回調的關系是怎樣的? 為什么我們必須在.onupgradeneeded中初始化數據庫的結構,而不是在onsuccess中?

          這主要是由兩個回調調用的時機決定的:

          1.對 onsuccess回調,在每次數據庫創建/打開的時候都會調用(不僅是第一次創建的時候會調用,每次打開的時候也都會調用)

          2. 對onupgradeneeded回調,在open提供第二個版本參數的前提下:

          2.1 第一次調用open方法創建一個新的數據庫的時候,onupgradeneeded一定會被調用

          2.2 第二次或以后open該數據庫,只在版本參數改變的時候, onupgradeneeded才會被調用

          【注意】在缺少第二個版本參數的情況下,onupgradeneeded永遠不會被調用!!

          所以說:

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

          2. 修改數據庫結構(例如創建和刪除對象存儲空間以及構建和刪除索引。)要在onupgradeneeded回調中運行

          (很顯然每次打開都會被調用的onsuccess并不適合用于初始化數據庫結構)

          indexedDB的具體操作

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

          demo:

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

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

          有兩個方法要說一下

          1. transaction方法

          transaction 方法 一般接受兩個參數,并返回一個事務對象。

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

          1.2 第二個參數是一個字符串, 默認是“onlyread”, 如果我們有需要對數據進行寫操作的需求的話可傳入“readwrite”

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

          2. transaction.objectStore方法

          這個方法接受一個參數: 指定的objectStore的名稱, 方法返回的是獲取到的objectStore

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

          寫操作

          寫操作的關鍵在于objectStore.add(XXX);方法,其中XXX是我們初始化objectStore時候寫入的“主鍵”

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

          demo:

          點擊“增加數據”后彈出

          再看看application面板下的indexedDB:

          我們已經成功添加了三條數據進去了

          刪操作

          刪操作的關鍵在于objectStore.delete(XXX);方法,其中XXX是我們初始化objectStore時候寫入的“主鍵”

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

          點擊上面的“刪除數據”按鈕(刪除id = 1的數據)

          再來看看, id為1的那一行已經被刪除了

          查操作

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

          demo:

          點擊“獲取數據”按鈕,彈出

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

          遍歷全部數據

          遍歷數據需要用到游標

          通過 objectStore.openCursor()可創建一個游標對象(cursor), 這個cursor對象包含兩個屬性值: key和value

          key就是我們一直說的那個“主鍵”, 而value是我們存入的時候的那個對象,通過 cursor.continue方法可以使得游標向下移動

          點擊“遍歷全部數據”按鈕,看看控制臺

          通過索引查找

          我們通過objectStore.get方法,通過查找主鍵的方式查找對應的對象數據的方式是很快的。

          但如果我們通過非主鍵的數據去查找對應的那個對象就非常慢了,這個時候我們需要創建一個索引并通過索引來查找, 從而獲得較快的速度:

          點擊“通過索引獲取數據”按鈕:

          好! 現在讓我們對indexedDB做一個小小的總結:

          1. indexedDB是面向對象的, 與傳統的以二維表為基礎的數據庫不同

          2. IndexedDB是一個事務型數據庫系統

          3. indexedDB大多數API都是異步的,這意味著調用一個方法你不能馬上得到關鍵的那個對象,而在對應的success回調中才能取得


          拖放事件

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

          其中我們主要關心的事件有三個:

          1. ondragstart 發生在可拖拽(draggable)的元素上, 在元素被拖動的時候調用

          2. ondragover 發生在可放置(droppable)的元素上, 當某被拖動的對象在可放置對象范圍內(上方)時觸發此事件

          3. ondrop 發生在可放置(droppable)的元素上,當釋放鼠標使可拖拽元素“放進”可放置元素內的瞬間觸發。

          需思考的問題:

          1. 如何使得被拖拽元素可拖拽?(因為元素默認的行為是不可拖拽的),以及如何使得被放置的容器元素可放置? (因為元素默認是不可放置的)

          對前者, 我們可以為元素設置draggable屬性,并且設置為true

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

          2.如何實現“脫 — 放”過程的數據傳遞?

          這里首先需要知道的是,當我們拖動一個圖片到另一個地方的時候,我們是不能“直接把圖片拖拽進去”的,也就是說,我們還是要通過以下的思路實現拖放:

          在被放置的元素中取得被拖拽元素的相關數據(如id),然后通過appendChild之類的API實現添加被拖拽的元素,從而模擬整個拖拽的過程

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

          關鍵在于如何在被拖動元素和被放置元素中傳遞數據,這可以通過event.dataTransfer對象來實現

          dataTransfer可以通過setData方法添加拖動數據,并通過getDate方法取得拖動數據,我們可以在

          ondragstart事件和ondrop事件中調用這兩個方法, 實現關鍵性的數據傳遞。

          具體請看下面的例子:

          拖拽前

          拖拽后

          參考資料:

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

          【完】

          擇器的權重和優先級

          CSS 選擇器有很多,不同的選擇器的權重和優先級不一樣,對于一個元素,如果存在多個選擇器,那么就需要根據權重來計算其優先級。

          權重分為四級,分別是:

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

          需要注意的是:通用選擇器(\*)、子選擇器(>)和相鄰同胞選擇器(+)并不在這四個等級中,所以他們的權值都為 0。 權重值大的選擇器其優先級也高,相同權重的優先級又遵循后定義覆蓋前面定義的情況。

          #盒模型

          1. 什么是“盒子”

          初學 CSS 的朋友,一開始學 CSS 基礎知識的時候一定學過padding bordermargin,即內邊距、邊框和外邊距。它們三者就構成了一個“盒子”。就像我們收到的快遞,本來買了一部小小的手機,收到的卻是那么大一個盒子。因為手機白色的包裝盒和手機機器之間有間隔層(內邊距),手機白色盒子有厚度,雖然很薄(邊框),盒子和快遞箱子之間還有一層泡沫板(外邊距)。這就是一個典型的盒子。

          如上圖,真正的內容就是這些文字,文字外圍有 10px 的內邊距,5px 的邊框,10px 的外邊距。看到盒子了吧?

          題目:盒子模型的寬度如何計算

          2. 固定寬度的盒子

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

          如上圖,得到網頁效果之后,我們可以用截圖工具來量一下文字內容的寬度。發現,文字內容的寬度剛好是 300px,也就是我們設置的寬度。

          因此,在盒子模型中,我們設置的寬度都是內容寬度,不是整個盒子的寬度。而整個盒子的寬度是:(內容寬度 + border寬度 + padding寬度 + margin寬度)之和。這樣我們改四個中的其中一個,都會導致盒子寬度的改變。這對我們來說不友好。

          沒關系,這個東西不友好早就有人發現了,而且已經解決,下文再說。

          3. 充滿父容器的盒子

          默認情況下,divdisplay:block,寬度會充滿整個父容器。如下圖:

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

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

          4. 包裹內容的盒子

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

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

          5. box-sizing:border-box

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

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

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

          * {
              box-sizing:border-box;
          }
          

          大名鼎鼎的 Bootstrap 也把box-sizing:border-box加入到它的*選擇器中,我們為什么不這樣做呢?

          6. 縱向 margin 重疊

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

          #浮動float

          float 用于網頁布局比較多,使用起來也比較簡單,這里總結了一些比較重要、需要注意的知識點,供大家參考。

          1. 誤解和誤用

          float 被設計出來的初衷是用于文字環繞效果,即一個圖片一段文字,圖片float:left之后,文字會環繞圖片。

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

          但是,后來大家發現結合float + div可以實現之前通過table實現的網頁布局,因此就被“誤用”于網頁布局了。

          題目:為何 float 會導致父元素塌陷?

          2. 破壞性

          float破壞性 —— float 破壞了父標簽的原本結構,使得父標簽出現了坍塌現象。導致這一現象的最根本原因在于:被設置了 float 的元素會脫離文檔流。其根本原因在于 float 的設計初衷是解決文字環繞圖片的問題。大家要記住 float 的這個影響。

          3. 包裹性

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

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

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

          4. 清空格

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

          <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 中間是會有空格的,因為多個 img 標簽會有換行,而瀏覽器識別換行為空格,這也是很正常的。第二張圖中,為 img 增加了float:left的樣式,這就使得 img 之間沒有了空格,4 個 img 緊緊挨著。
          • 如果大家之前沒注意,現在想想之前寫過的程序,是不是有這個特性。為什么 float 適合用于網頁排版(俗稱“砌磚頭”)?就是因為 float 排版出來的網頁嚴絲合縫,中間連個蒼蠅都飛不進去。
          • “清空格”這一特性的根本原因是 float 會導致節點脫離文檔流結構。它都不屬于文檔流結構了,那么它身邊的什么換行、空格就都和它沒了關系,它就盡量往一邊靠攏,能靠多近就靠多近,這就是清空格的本質。

          題目:手寫 clearfix

          5. clearfix

          清除浮動的影響,一般使用的樣式如下,統稱clearfix代碼。所有 float 元素的父容器,一般情況下都應該加clearfix這個 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. 小結

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

          #定位 position

          position 用于網頁元素的定位,可設置 static/relative/absolute/fixed 這些值,其中 static 是默認值,不用介紹。

          題目:relative 和 absolute 有何區別?

          1. relative

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

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

          然后我們在第三個<p>上面,加上position:relative并且設置lefttop值,看這個<p>有什么變化。

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

          上圖中,大家應該要識別出兩個信息(相信大部分人會忽略第二個信息)

          • 第三個<p>發生了位置變化,分別向右向下移動了10px;
          • 其他的三個<p>位置沒有發生變化,這一點也很重要。

          可見,relative 會導致自身位置的相對變化,而不會影響其他元素的位置、大小。這是 relative 的要點之一。還有第二個要點,就是 relative 產生一個新的定位上下文。下文有關于定位上下文的詳細介紹,這里可以先通過一個例子來展示一下區別:

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

          2. absolute

          還是先寫一個基本的 demo。

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

          然后,我們把第三個<p>改為position:absolute;,看看會發生什么變化。

          從上面的結果中,我們能看出幾點信息:

          • absolute 元素脫離了文檔結構。和 relative 不同,其他三個元素的位置重新排列了。只要元素會脫離文檔結構,它就會產生破壞性,導致父元素坍塌。(此時你應該能立刻想起來,float 元素也會脫離文檔結構。)
          • absolute 元素具有“包裹性”。之前<p>的寬度是撐滿整個屏幕的,而此時<p>的寬度剛好是內容的寬度。
          • absolute 元素具有“跟隨性”。雖然 absolute 元素脫離了文檔結構,但是它的位置并沒有發生變化,還是老老實實地呆在它原本的位置,因為我們此時沒有設置 top、left 的值。
          • absolute 元素會懸浮在頁面上方,會遮擋住下方的頁面內容。

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

          3. fixed

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

          題目:relativeabsolutefixed 分別依據誰來定位?

          4. 定位上下文

          relative 元素的定位永遠是相對于元素自身位置的,和其他元素沒關系,也不會影響其他元素。

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

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


          #flex布局

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

          1. 基本使用

          任何一個容器都可以使用 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>
          
          

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

          2. 設計原理

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

          將以上文字和圖片結合起來,再詳細看一遍,這樣就能理解 flex 的設計原理,才能更好地實際使用。

          3. 設置主軸的方向

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

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

          以上代碼設置的主軸方向,將依次對應下圖:

          4. 設置主軸的對齊方式

          justify-content屬性定義了項目在主軸上的對齊方式,值如下:

          • flex-start(默認值):向主軸開始方向對齊。
          • flex-end:向主軸結束方向對齊。
          • center: 居中。
          • space-between:兩端對齊,項目之間的間隔都相等。
          • space-around:每個項目兩側的間隔相等。所以,項目之間的間隔比項目與邊框的間隔大一倍。
          .box {
              justify-content: flex-start | flex-end | center | space-between | space-around;
          }
          

          5. 交叉軸的對齊方式

          align-items屬性定義項目在交叉軸上如何對齊,值如下:

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

          #如何實現居中對齊?

          題目:如何實現水平居中?

          1. 水平居中

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

          .container {
             text-align: center;
          }
          

          block 元素可使用margin: auto;,PC 時代的很多網站都這么搞。

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

          絕對定位元素可結合leftmargin實現,但是必須知道寬度。

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

          題目:如何實現垂直居中?

          2. 垂直居中

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

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

          絕對定位元素,可結合leftmargin實現,但是必須知道尺寸。

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

          絕對定位可結合transform實現居中。

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

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

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

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

          #理解語義化

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

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

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

          1. 讓人更易讀懂

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

          2. 讓機器更易讀懂

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

          #CSS3 動畫

          CSS3 可以實現動畫,代替原來的 Flash 和 JavaScript 方案。

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

          @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;}
          }
          
          

          后,針對一個 CSS 選擇器來設置動畫,例如針對div元素設置動畫,如下:

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

          animation-name對應到動畫名稱,animation-duration是動畫時長,還有其他屬性:

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

          題目:CSS 的transitionanimation有何區別?

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

          #重繪和回流

          重繪和回流是面試題經常考的題目,也是性能優化當中應該注意的點,下面筆者簡單介紹下。

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

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

          題目:找出下面代碼的優化點,并且優化它

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

          上面的代碼在循環中每次都獲取dom,然后對其內部的 HTML 進行累加li,每次都會操作 DOM 結構,可以改成使用documentFragment或者先遍歷組成 HTML 的字符串,最后操作一次innerHTML

          #小結

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


          主站蜘蛛池模板: 激情爆乳一区二区三区| 色欲AV蜜桃一区二区三| 国产成人AV区一区二区三| 在线视频亚洲一区| 91福利国产在线观一区二区| 一区二区亚洲精品精华液| 一区二区三区波多野结衣| 国产伦理一区二区| 亚洲中文字幕久久久一区| 国产精品 视频一区 二区三区 | 国产一区二区三区在线观看精品 | 不卡一区二区在线| 色狠狠色狠狠综合一区| 国产精品亚洲一区二区无码| 无码一区二区三区免费| 亚无码乱人伦一区二区| 国产一区三区二区中文在线| 中文字幕一区二区三区有限公司| 无码中文字幕人妻在线一区二区三区 | 韩国福利一区二区美女视频| 国产午夜三级一区二区三| 日韩一区二区三区电影在线观看| 99精品国产高清一区二区三区| 精品一区二区三区在线观看l| 国产在线乱子伦一区二区| 中文字幕精品一区影音先锋| 亚洲一区二区三区在线网站| 影音先锋中文无码一区| 另类ts人妖一区二区三区| 一区二区三区在线免费观看视频| 一区二区三区内射美女毛片| 一区二区三区精品视频| 一区二区中文字幕| 久久精品无码一区二区三区免费 | 国产精品va无码一区二区| 亚洲熟女一区二区三区| 亚洲AV日韩综合一区| 亚洲中文字幕丝袜制服一区 | 日韩在线一区二区三区免费视频| 亚洲国产精品一区二区三区久久| 日本在线观看一区二区三区|