[TOC]
>[info] 這里不討論瀏覽器兼容性
# 語義化
語義化標簽:`<header>, <nav>, <main>, <article>, <aside>, <footer>`以及`<address>, <mark>, <time>`等
語義化的優點:
* 易于用戶閱讀,樣式丟失的時候能讓頁面呈現清晰的結構。
* 有利于 SEO,搜索引擎根據標簽來確定上下文和各個關鍵字的權重。
* 方便其他設備解析,如盲人閱讀器根據語義渲染網頁
* 有利于開發和維護,語義化更具可讀性,代碼更好維護,與 CSS3 關系更和諧。
關于 SEO 優化的可以使用 title 和 meta,比如
``` html
<html>
<head>
<title>標題內容</title>
?<meta name="description" content="描述內容">
?<meta name="keyword" content="關鍵字1,關鍵字2,—">
?</head>
</html>
```
# 表單增強
## input type 屬性擴充
* search: 呈現一個搜索框
* tel: 輸入電話號碼,可以采用 pattern 和 maxlength 來限定輸入的格式,比如
```html
<input type="tel" name="tel" value="" placeholder="請輸入手機號" pattern="1[3-8][0-9]{9}" title="請輸入11位手機號">
```
提交表單時,瀏覽器會校驗輸入結果。如果校驗失敗,會給出提示信息
* url: 輸入 URL 地址
* email: 輸入電子郵件地址
* data: 輸入日期
* color: 輸入顏色, 會調出選色板
* range: 滑塊輸入
## input 通過屬性進行表單驗證
* required: 標記當前 Input 元素為必填
```html
<input type="text" placeholder="此項必填" required>
```
* pattern: 采用正則表達式驗證表單輸入
關于去除`<input type="file">`顯示的"未選擇任何文字"的默認提示的問題,比如下面這樣

這里提供一種思路: `<label>`標簽的 for 屬性可以觸發對應的表單控件,把 input 的樣式隱藏掉(比如 opacity: 0)用一個 button 來代替即可
``` html
<label for="sendImage" class="imageLable">
? <input type="button" value="image" ?/>
? <input id="sendImage" type="file" value="image"/> <!--定義類型為 file 即可讓用戶選擇文件-->
</label>
```
# canvas 與 SVG
canvas 與 svg: canvas 通過 JavaScript 來繪制 2D 圖形,是逐像素進行渲染的;svg(Scalable Vector Graphics)基于 XML,具有可縮放的矢量圖形特性,這意味著在對 SVG 圖形做任何尺寸變化時不會出現模糊和失真。
具體比較如下,來源:w3school
- Canvas
- 依賴分辨率
- 不支持事件處理器
- 弱的文本渲染能力
- 能夠以 .png 或 .jpg 格式保存結果圖像
- 最適合圖像密集型的游戲,其中的許多對象會被頻繁重繪
- Canvas 是逐像素進行渲染的。
在 canvas 中,一旦圖形被繪制完成,它就不會繼續得到瀏覽器的關注。如果其位置發生變化,那么整個場景也需要重新繪制,包括任何或許已被圖形覆蓋的對象。
- SVG
- 不依賴分辨率
- 支持事件處理器
- 最適合帶有大型渲染區域的應用程序(比如谷歌地圖)
- 復雜度高會減慢渲染速度(任何過度使用 DOM 的應用都不快)
- 不適合游戲應用
canvas 相關的文檔正在寫作中:[http://www.hmoore.net/chenmk/canvas/1315494](http://www.hmoore.net/chenmk/canvas/1315494)
# 多媒體相關 API
\<video> 用于加載視頻文件:
```html
<video width="320" height="240" controls="controls">
<source src="movie.ogg" type="video/ogg">
<source src="movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
```
- Ogg 文件適用于 Firefox、Opera 以及 Chrome 瀏覽器。要確保適用于 Safari 瀏覽器,視頻文件必須是 MPEG4 類型。
- video 元素允許多個 source 元素。source 元素可以鏈接不同的視頻文件。瀏覽器將使用第一個可識別的格式。
- controls 屬性供添加播放、暫停和音量控件。
相關鏈接:[https://www.w3school.com.cn/html5/html\_5\_video.asp](https://www.w3school.com.cn/html5/html_5_video.asp)
\<audio> 用于加載音頻文件:
```html
<audio controls="controls">
<source src="song.ogg" type="audio/ogg">
<source src="song.mp3" type="audio/mpeg">
Your browser does not support the audio tag.
</audio>
```
[這篇文章](https://www.jianshu.com/p/1fe701c9179f) 記錄了其相關 API
一般我們都會取消掉瀏覽器提供的默認控件,使用相應的 API 來做自己的視頻、音頻播放器,以后有空做個玩玩...
# history API
| 屬性 | 描述 |
| --- | --- |
| state -> window.history.state | 返回一個表示歷史堆棧頂部的狀態的值 |
| length -> window.history.length | 返回一個整數,表示會話歷史中的元素數目
| 方法 | 描述 |
| --- | --- |
| back() | 返回上一頁 |
| forward() | 在瀏覽器歷史記錄中前往下一頁 |
| go() | 參數為 -1 時前往上一頁,參數為 1 時前往下一頁 |
| pushState(stateObject, title, URL) | 按指定的名稱和 URL(如果提供該參數)將數據 push 進會話歷史棧,數據被 DOM 進行不透明處理;你可以指定任何可以被序列化的 javaScript 對象 |
| replaceState(stateObject, title, URL) | 按指定的數據、名稱和 URL(如果提供該參數)更新歷史棧上最新的入口。這個數據被 DOM 進行了不透明處理。你可以指定任何可以被序列化的 JavaScript 對象 |
| 事件 | 描述 |
| --- | --- |
| popState | 瀏覽器跳轉到新的狀態時會觸發 popState 事件,該事件將攜帶這個 stateObject 參數的副本 |
```js
function nextPage () {
// doSomething...
window.history.pushState({ page: pageIndex }, null, window.location.href)
}
// 用戶單擊返回或前進按鈕時觸發
window.addEventListener('popstate', function (event) {
let page = event.state.page // 從 event 對象中獲取這個“頁面”存儲的狀態
})
```
# 文件 API
總之先看一段代碼,這是寫聊天室時從本地選擇圖片的部分代碼,用戶點擊`<input type="file">`時觸發。
```javaScript
// 選擇圖片時觸發
chooseImage(e) {
// 檢查是否有文件被選中
let _this = this
let file = e.target.files[0] // 獲取到被選中的圖片的路徑
let reader = new FileReader()
if (file && file.type.match('image.*')) {
reader.readAsDataURL(file)
} else {
// not image
}
// 注意是異步讀取
reader.onloadend = function(e) {
// do something after read image
// console.log(reader.result) // blob 類型
let imageData = reader.result
_this.historyMessages.push({
username: _this.username,
time: new Date().toTimeString().substr(0, 8),
content: `<img src="${imageData}" style="width:100%">`, // 本來想把style寫在css里的發現無法選擇到img
ifImage: true
})
_this.$socket.emit('postImg', imageData)
}
}
```
要理解這段代碼,首先要明確 e.target.files 這個數組中的 File 對象的格式,然后要知道FileReader 類型提供了哪些方法。
HTML5 在DOM 中為文件輸入元素添加了一個 files 集合。在通過文件輸入字段選擇了一或多個文件時,files 集合中將包含一組 File 對象,每個 File 對象對應著一個文件。每個 File 對象都有下列只讀屬性。
- name:本地文件系統中的文件名。
- size:文件的字節大小。
- type:字符串,文件的 MIME 類型。
- lastModifiedDate:字符串,文件上一次被修改的時間
FileReader 類型實現的是一種異步文件讀取機制。可以把 FileReader 想象成 XMLHttpRequest,區別只是它讀取的是文件系統,而不是遠程服務器。為了讀取文件中的數據,FileReader 提供了如下幾個方法。
- readAsText(file,encoding):以純文本形式讀取文件,將讀取到的文本保存在 result 屬性中。第二個參數用于指定編碼類型,是可選的。
- readAsDataURL(file):讀取文件并將文件以數據 URI 的形式保存在 result 屬性中。
- readAsBinaryString(file):讀取文件并將一個字符串保存在 result 屬性中,字符串中的每個字符表示一字節。
- readAsArrayBuffer(file):讀取文件并將一個包含文件內容的 ArrayBuffer 保存在
result 屬性中。
`URL:Uniform/Universal Resource Locator` ,統一資源定位符
`URI:Uniform Resource Identifier` ,統一資源標識符(代表一種標準)
>關系:URI 屬于 URL 更高層次的抽象,一種字符串文本標準。就是說,URI 屬于父類,而 URL 屬于 URI 的子類。URL 是 URI 的一個子集。二者的區別在于,URI 表示請求服務器的路徑,定義這么一個資源。而 URL 同時說明要如何訪問這個資源(http://)。
?由于讀取過程是異步的,因此 FileReader 也提供了幾個事件。常用的事件有
- progress 是否又讀取了新數據
- error 是否發生了錯誤
- end 是否已經讀完了整個文件
- load 文件加載成功后觸發
- loadend 該事件發生就意味著已經讀取完整個文件,或者讀取時發生了錯誤,或者讀取過程被中斷。
# 其他 API
## 地理位置
地理位置 API 能夠訪問到用戶的當前位置信息,訪問前必須得到用戶的明確許可。
在瀏覽器中的實現是 navigator.geolocation 對象,這個對象包含 3 個方法
getCurrentPosition(cb1, cb2(option), obj(option)): 調用該方法會觸發請求用戶共享地理位置信息的對話框,接收3個參數:成功的回調、可選的失敗的回調函數和可選的選項對象
成功回調函數會接收到一個 Position 對象參數,該對象有兩個屬性:coords 和 timestamp
coords對象包含以下與位置相關的信息:
- latitude:以十進制度數表示的緯度。
- longitude:以十進制度數表示的經度。
- accuracy:經、緯度坐標的精度,以米為單位。
有些瀏覽器還可能會在 coords 對象中提供如下屬性。
- altitude:以米為單位的海拔高度,如果沒有相關數據則值為 null。
- altitudeAccuracy:海拔高度的精度,以米為單位,數值越大越不精確。
- heading:指南針的方向,0°表示正北,值為 NaN 表示沒有檢測到數據。
- speed:速度,即每秒移動多少米,如果沒有相關數據則值為 null。
在實際開發中,latitude 和 longitude 是大多數 Web 應用最常用到的屬性。例如,以下代碼將在地圖上繪制用戶的位置:
``` js
navigator.geolocation.getCurrentPosition(function (position) {
drawMapCenteredAt(position.coords.latitude, position.coords.longitude)
})
```
完整的示例:
``` js
navigator.geolocation.getCurrentPosition(function (position) { // 成功的回調
drawMapCenteredAt(position.coords.latitude, position.coords.longitude)
}, function (error) { // 失敗的回調
console.log(`Error code: ${error.code}`) // 錯誤類型:1 用戶拒絕共享 2 位置無效 3 超時
console.log(`Error message ${error.message}`)
}, { // 選項對象
enableHighAccuracy: true, // 表示必須盡可能使用最準確的位置信息
timeout: 5000, // 表示等待位置信息的最長時間
maximumAge: 25000 // 表示上一次取得的坐標信息的有效時間,ms 為單位,如果超時則重新獲取
})
```
如果要跟蹤用戶的位置,可以使用 **watchPosition** 方法
## 跨文檔消息傳遞
即來自不同域的頁面間傳遞消息,其核心是 postMessage() 方法,postMessage() 方法接收兩個參數:一條消息和一個表示消息接收方來自哪個域的字符串。第二個參數對保障安全通信非常重要,可以防止瀏覽器把消息發送到不安全的地方。
``` js
// 注意:所有支持 XDM 的瀏覽器也支持 iframe 的 contentWindow 屬性
var iframeWindow = document.getElementById('myframe').contentWindow
iframeWindow.postMessage('A secret', 'http://www.wrox.com')
```
接收到 XDM 消息時,會觸發 window 對象的 message 事件。這個事件是以異步形式觸發的,因此從發送消息到接收消息(觸發接收窗口的 message 事件)可能要經過一段時間的延遲。觸發 message 事件后,傳遞給 onmessage 處理程序的事件對象包含以下三方面的重要信息。
- data:作為 postMessage() 第一個參數傳入的字符串數據。
- origin:發送消息的文檔所在的域,例如`"http://www.wrox.com"`。
- source:發送消息的文檔的 window 對象的代理。這個代理對象主要用于在發送上一條消息的
窗口中調用 postMessage() 方法。如果發送消息的窗口來自同一個域,那這個對象就是 window。
通常用于獲取嵌入頁面中的第三方頁面數據。一個頁面發送消息,另一個頁面判斷來源并接收消息
``` js
// 發送消息端
window.parent.postMessage('message', 'http://test.com')
// 接收消息端
var mc = new MessageChannel()
mc.addEventListener('message', event => {
var origin = event.origin || event.originalEvent.origin
if (origin === 'http://test.com') {
console.log('驗證通過')
}
})
```
更多信息參考<a href="https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel" target="_blank"> MDN</a>
## Web Worker
參考鏈接:[http://www.ruanyifeng.com/blog/2018/07/web-worker.html](http://www.ruanyifeng.com/blog/2018/07/web-worker.html)
Web Worker 的作用,就是為 JavaScript 創造多線程環境,允許主線程創建 Worker 線程,將一些任務分配給后者運行。在主線程運行的同時,Worker 線程在后臺運行,兩者互不干擾。等到 Worker 線程完成計算任務,再把結果返回給主線程。這樣的好處是,一些計算密集型或高延遲的任務,被 Worker 線程負擔了,主線程(通常負責 UI 交互)就會很流暢,不會被阻塞或拖慢。
Worker 線程一旦新建成功,就會始終運行,不會被主線程上的活動(比如用戶點擊按鈕、提交表單)打斷。這樣有利于隨時響應主線程的通信。但是,這也造成了 Worker 比較耗費資源,不應該過度使用,而且一旦使用完畢,就應該關閉。
Web Worker 有以下幾個使用注意點。
(1)**同源限制**
分配給 Worker 線程運行的腳本文件,必須與主線程的腳本文件同源。
(2)**DOM 限制**
Worker 線程所在的全局對象,與主線程不一樣,無法讀取主線程所在網頁的 DOM 對象,也無法使用`document`、`window`、`parent`這些對象。但是,Worker 線程可以訪問`navigator`對象和`location`對象。
(3)**通信聯系**
Worker 線程和主線程不在同一個上下文環境,它們不能直接通信,必須通過消息完成。
(4)**腳本限制**
Worker 線程不能執行`alert()`方法和`confirm()`方法,但可以使用 XMLHttpRequest 對象發出 AJAX 請求。
(5)**文件限制**
Worker 線程無法讀取本地文件,即不能打開本機的文件系統(`file://`),它所加載的腳本,必須來自網絡。
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直線、矩形、多邊形
- Part2-曲線圖形
- Part3-線條操作
- Part4-文本操作
- Part5-圖像操作
- Part6-變形操作
- Part7-像素操作
- Part8-漸變與陰影
- Part9-路徑與狀態
- Part10-物理動畫
- Part11-邊界檢測
- Part12-碰撞檢測
- Part13-用戶交互
- Part14-高級動畫
- CSS
- SCSS
- codePen
- 速查表
- 面試題
- 《CSS Secrets》
- SVG
- 移動端適配
- 濾鏡(filter)的使用
- JS
- 基礎概念
- 作用域、作用域鏈、閉包
- this
- 原型與繼承
- 數組、字符串、Map、Set方法整理
- 垃圾回收機制
- DOM
- BOM
- 事件循環
- 嚴格模式
- 正則表達式
- ES6部分
- 設計模式
- AJAX
- 模塊化
- 讀冴羽博客筆記
- 第一部分總結-深入JS系列
- 第二部分總結-專題系列
- 第三部分總結-ES6系列
- 網絡請求中的數據類型
- 事件
- 表單
- 函數式編程
- Tips
- JS-Coding
- Framework
- Vue
- 書寫規范
- 基礎
- vue-router & vuex
- 深入淺出 Vue
- 響應式原理及其他
- new Vue 發生了什么
- 組件化
- 編譯流程
- Vue Router
- Vuex
- 前端路由的簡單實現
- React
- 基礎
- 書寫規范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 與 Hook
- 《深入淺出React和Redux》筆記
- 前半部分
- 后半部分
- react-transition-group
- Vue 與 React 的對比
- 工程化與架構
- Hybird
- React Native
- 新手上路
- 內置組件
- 常用插件
- 問題記錄
- Echarts
- 基礎
- Electron
- 序言
- 配置 Electron 開發環境 & 基礎概念
- React + TypeScript 仿 Antd
- TypeScript 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs