H5.2

_______________________________________________________________________________________________

HTML5新特性之七 ——— 拖放API

? Drag&Drop: 拖動&釋放,H5提供了7個拖放事件API,分為2組,可以實現類似于桌面軟件中的拖放效果,無需像以前那樣使用鼠標事件來代替

img和a元素默認可拖動,其它元素加一個draggable=true屬性可以使其拖動

拖放的源對象(可能發生移動)可以觸發的事件?——— 3個

?dragstart: 拖動開始

?drag: ?拖動中

?dragend: 拖動結束

? 整個拖動過程的組成: dragstart*1 + drag*n + dragend*1

實現用鼠標拖動元素的功能:

drag事件中獲取拖動事件相對于頁面的坐標(e.clientX),即時修改事件源的位置(left/top)

使事件源絕對定位(通過修改top/left修改位置),并且其最近的祖先元素要相對定位

elem.ondragstart=function(e){

? startx=e.offsetX; ? ? ? ?//拖動事件相對于飛機左上角偏移量,elem:飛機元素

? starty= e.offsetY;

};

elem.ondrag=function(e){

? var ex=e.clientX; ? ? ? ?//獲得拖動事件相對于頁面(body)的坐標(文檔顯示區左上角)

? var ey=e.clientY;

? if(ex<=0&&ey<=0){?return; } ? ? ?? //防止拖動事件最后觸發(0,0)坐標

? p3.style.left=(ex-startx)+"px"; ? ?//拖動后元素相對于距其最近的已定位祖先元素的偏移量 =

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?拖動后鼠標的client - 拖動前鼠標的offset

? p3.style.top=(ey-starty)+"px";

};

拖放的目標對象(不會發生移動)可以觸發的事件 ——— 4個(源對象被拖動時,目標元素可觸發的事件)

?dragenter:源對象被拖動著進入目標對象

?dragover: ?源對象被拖動著懸停在目標對象上方

?dragleave:源對象被拖動著離開了目標對象

?drop: ?源對象在目標對象上方釋放

? 整個拖動過程的組成1:? dragenter*1 + dragover*n + dragleave*1

? 整個拖動過程的組成2:? dragenter*1 + dragover*n + drop*1

注意: dragover事件的默認行為是必須觸發dragleave,若不阻止此默認行為,drop無法觸發

?在dragover事件中,阻止默認行為: e.preventDefault();

H5拖放API: 如何在拖動源對象和目標對象間傳遞數據

dataTransfer: ?用于數據傳遞的"拖拉機"對象

e.dataTransfer.setData(k,v): ?在拖動源對象事件中使用e.dataTransfer屬性保存數據

var value = e.dataTransfer.getData(k): ?在拖動目標對象事件中使用e.dataTransfer屬性讀取數據

第六章*****************************************************************************************

H5新特性之八 ——— Web Worker: 執行耗時JS任務

操作系統基礎概念

程序: Program,可供CPU執行的代碼,存儲在外存中,如.exe

進程:?Process/Task,把程序從外存調入內存,分配執行空間(必需數據段和可執行代碼段)

? ? ? 隨時供CPU調用執行,進程是程序的可執行狀態

線程:?Thread,線程是進程內部執行代碼的基本單位

問題:進程和線程間的關系

① 進程是操作系統分配內存的基本單位

② 線程是CPU執行代碼的基本單位

③ 線程必須處于某個進程內部

④ 一個進程內至少一個,也可以同時存在多個線程

⑤ 每個線程也需要自己獨立的內存空間,至少2MB

⑥ 一個操作系統中存在多個線程,在宏觀上看是"同時執行",微觀上看是"依次執行" ——— 并發執行

? ? 宏觀和微觀都是"同時執行" ——— 并行

問題: Chrome瀏覽器中的線程模型

一個Chrome進程內,至少有6個并發線程,"并發"向web服務器發起http請求,獲取資源?———?資源請求線程

還有1個線程負責將所有內容繪制到瀏覽器頁面中 ———?UI渲染主線程: 不允許多線程同時繪圖,防止內容布局沖突

_______________________________________________________________________________________________

若頁面中需要執行一段很"耗時"的JS任務,出現的現象:

? <button>按鈕1</button>

? <script src="x.js"></script>

? < button>按鈕2</button>

x.js執行過程中,按鈕1可見但可能沒有事件處理,按鈕2不可見

產生原因: 瀏覽器中執行代碼只使用1個線程: ?UI主線程

解決辦法: 創建一個新線程,讓它去執行耗時的JS任務,UI主線程繼續執行頁面渲染和事件監聽

? ? ? ? ? 瀏覽器作為宿主環境提供了JS一個多線程運行的環境

H5中創建新的執行線程的方法:

<button>按鈕1</button>

? <script> var elem =?new Worker('x.js')?</script> ? ?//在網絡環境下(apache/nodejs)才生效

<button>按鈕2</button>

Worker線程的缺陷: 瀏覽器不允許Worker線程操作任何的DOM、BOM對象

原因: 瀏覽器只允許UI主線程操作DOM、BOM對象,若多個線程同時都可以操作DOM、BOM,頁面可能混亂

解決辦法: 類似jQuery操作DOM、BOM的腳本不使用Worker來加載執行

UI主線程給Worker線程發數據消息:

UI主線程: ?var w2 = new Worker('x.js', options);? //構造函數

? ? ? ? ??w2.postMessage(發送的數據);

Worker線程:?onmessage= function(e){ e.data } ? ?//e.data: 接收的數據

Worker()構造函數,第一個參數是腳本的網址(必須遵守同源政策),該參數是必需的,且只能加載JS腳本,否則報錯。第二個參數是配置對象,可選。作用是指定 Worker 的名稱,用來區分多個 Worker 線程(如{ name:'w2' })

Worker線程給UI主線程發數據消息:

UI主線程:? var w1 = new Worker('x.js');

? ? ? ? ??w1.onmessage= function(e){ e.data } ? ?//e.data: 接收的數據

Worker線程: ?postMessage(發送的數據);

主線程中的API: worker是 Worker 的實例

worker.postMessage(aMessage, transferList): 主線程往worker線程發消息,消息可以是任意類型數據,包括二進制數據,接受兩個參數,aMessage 是可以傳遞任何類型數據的,包括對象。這種通信是拷貝關系,即是傳值而不是傳址,Worker 對通信內容的修改,不會影響到主線程

worker.terminate: 主線程關閉worker線程

worker.onmessage: 指定worker線程發消息時的回調,也可通過worker.addEventListener('message', cb)

worker.onerror: 指定worker線程發生錯誤時的回調,也可通過worker.addEventListener('error', cb)

Worker線程中全局對象為self,代表子線程自身,this指向self,其上有一些API

self.postMessage: worker線程往主線程發消息,消息可以是任意類型數據,包括二進制數據

self.close: worker線程關閉自己

self.onmessage: 指定主線程發worker線程消息時的回調,也可以self.addEventListener('message', cb)

self.onerror: 指定worker線程發生錯誤時的回調,也可以self.addEventListener('error', cb)

worker的使用注意點

① 同源限制: worker線程執行的腳本文件必須和主線程的腳本文件同源

② 文件限制: 為了安全,worker線程無法讀取本地文件,它所加載的腳本必須來自網絡,且需要與主線程的腳本同源

③ DOM操作限制: worker線程在與主線程的window不同的另一個全局上下文中運行,其中無法讀取主線程所在網頁的DOM對象,也不能獲取 document、window等對象,但是可以獲取navigator、location(只讀)、XMLHttpRequest、setTimeout族等瀏覽器API

④ 通信限制: worker線程與主線程不在同一個上下文,不能直接通信,需要通過postMessage方法來通信

⑤ 腳本限制: worker線程不能執行alert、confirm,但可以使用XMLHttpRequest對象發出ajax請求

⑥ 雖然使用worker線程不會占用主線程,但是啟動worker會比較耗費資源

⑦ 主線程中使用XMLHttpRequest在請求過程中瀏覽器另開了一個異步http請求線程,但是交互過程中還是要消耗主線程資源

總結: 項目中使用Worker的場景

當在UI主線程中執行會導致頁面內容"卡死"時,可以使用Worker線程與UI主線程并發執行

比如: 復雜計算(如深度的遞歸、循環嵌套)、加密/解密、大數據統計、路徑規則、預加載

_______________________________________________________________________________________________

H5新特性之九 ——— Web Storage—————key是關鍵字,不能作為屬性名

作用: 在瀏覽器中存儲當前用戶專有的數據,比如: 訪問歷史、內容定制、樣式定制

注意:?存儲Number類型時,取出來會變成String類型

Web項目中項目數據的存儲位置:

服務器端存儲: 業務數據(如商品、用戶、訂單、帖子、評論、儲戶等)

客戶端存儲: ? 客戶端專有數據(歷史記錄、內容定制、樣式偏好等)

① Cookie技術: ?瀏覽器兼容性好,大小不能超過4KB,操作復雜,使用較普遍

② Flash存儲: ? 依賴于Flash播放器,不推薦使用

③ IndexedDB技術: 可以存取大量數據,還不是技術標準

④ H5 Web Storage技術: ?大小不能超過8MB,操作簡單,H5新特性

Session:會話,從瀏覽器打開某個網站的某個頁面開始,中間可能打開多個頁面,不斷的發出請求、接收響應,直至關閉瀏覽器 ——— 整個過程稱為瀏覽器和Web服務器之間的一次"會話"

H5的Web Storage技術中,瀏覽器為用戶提供了2個對象:

①window.sessionStorage:?存儲在瀏覽器內存中的類數組對象,會話級數據存儲,會話結束,數據刪除

作用: ?在同一個會話中所有頁面共享數據,如登錄用戶名

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //訪問對象的屬性: 對象.屬性名 或對象["屬性名"]

sessionStorage['key']= value ? ? ? ?//保存一個數據

var v = sessionStorage['key'] ? ? ? ? ? //讀取一個數據

sessionStorage.setItem('key',value)? //保存一個數據

var v = sessionStorage.getItem('key') ? //讀取一個數據

sessionStorage.removeItem('key') ? ? //刪除一個數據

sessionStorage.clear() ? ? ? ? ? ? ? ? ?//清除所有的數據

var count = sessionStorage.length ? ? ? //查看保存的數據個數

var key =sessionStorage.key(i)? ?? //獲取第i個key,第i個屬性名

②window.localStorage:跨會話級數據存儲

本質就是一個存儲在瀏覽器硬盤文件中的類數組對象,專用于永久存儲當前網站在當前瀏覽器中的專用數據,即使關閉瀏覽器/重啟電腦數據也不會刪除

作用: 在當前客戶端所對應的所有會話中共享數據

localStorage['key'] = value ? ? ? ? //保存一個數據

var v = localStorage['key'] ? ? ? ? ?//讀取一個數據

localStorage.setItem('key',value) ? //保存一個數據

var v = localStorage.getItem('key')? //讀取一個數據

localStorage.removeItem('key') ? ?? //刪除一個數據

localStorage.clear() ? ? ? ? ? ? ? ? //清除所有的數據

var count = localStorage.length ? ? ?//查看保存的數據個數

var key =localStorage.key(i) ? ? ? //獲取第i個key,即第i個屬性名

localStorage['key']=JSON.stringify(obj);? //把對象/數組轉成json字符串,存進localStorage

var obj=JSON.parse(localStorage.getItem('key'));? //將存進去的json字符串轉成對象/數組

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//此時,對象或數組中的Number不會變為String

if(localStorage['key']){ ? ?//在iPhone/iPad上有時設置setItem()時會出現詭異的QUOTA_EXCEEDED_ERR錯誤,這時在setItem之前,先removeItem()就好了

??localStorage.removeItem('key');

}

localStorage.setItem('key',value);

window.onstorage事件: ?當 localStorage 中數據發生改變時會自動觸發

注意: 該事件只能用于監聽 localStorage 中數據的改變,而不能監聽sessionStorage中數據的改變

for(var i=0;i<localStorage.length;i++){ ?? //遍歷客戶端 內存/硬盤 中存儲的數據

? var key = localStorage.key(i); ? ? ? ? ? //獲取第i個key

? var value = localStorage[key]; ? ? ? ? ? //獲取第i個value

}

第七章*****************************************************************************************

H5新特性之十 ——— Web Socket

Socket: 插座、套接字,源自于90+年代C語言,所有的網絡通訊底層都是基于套接字編程,套接字用于"接收數據&發送數據"

HTTP協議特點: 屬于"請求 — 響應"模型的協議,必須客戶端先發請求,服務器才會給出響應。一個請求,只能得到一個響應。在有些應用場景,此模型有缺陷: 實時走勢、聊天室 ——— 即使客戶端不發送請求,服務器只要數據有更新也應該立即給客戶端

解決辦法:長輪詢(Long Polling)/心跳請求: 定時器 + XHR

該辦法并不完美,請求過于頻繁服務器壓力太大;不夠頻繁,客戶端數據延遲較大,時效性差

Web Socket協議: 屬于于"廣播 — 收聽"模型的協議,只要客戶端連接到服務器就不再斷開(永久連接),雙方建立"全雙工通信通道"(雙方向),一方可以不停的給對方發消息,同時對方也可以發送/不發送消息,可以解決"實時走勢、聊天室"應用中的問題

Web Socket協議的應用分為客戶端和服務器端程序

基于WS協議的服務器端程序:?Java、PHP、Node.js都可以編寫

? 監聽指定端口,接收客戶請求,向對方發消息,并接受消息

基于WS協議的客戶端程序: ? Java、PHP、HTML5都可以編寫

? 主動發起連接請求,保持永久連接,向對方發消息,并接收消息

使用Node.js編寫一個WS協議的服務器端應用

① 下載第三方ws協議模塊:? npm? i? ws

② 仿照ws模塊自帶的說明文檔 README,編寫WS服務器端程序

創建WebSocket服務器程序

const ws = require("ws");? ? ? ? ? ? ? ? ? //加載相應模塊 ws

var server = new ws.Server( {port:9001} );//創建WebSocket服務器,指定端口

server.on("connection",(socket)=>{? ? ? ? //接收客戶端連接請求

? console.log("WS服務器接收到一個連接");

? var counter = 0;

? var timer = setInterval(()=>{

? ? counter++;

? ?socket.send("I am Server - "+counter);? ? //每隔一定時間,ws服務器向客戶端發送一次消息

? },1000);

? socket.on("message",(msg)=>{//WS服務器接收客戶端發來的消息

? ? console.log("服務器接收消息"+msg);

? });

? socket.on("close",()=>{//WS服務器接收到客戶端發來的斷開連接請求

? ? console.log("客戶端斷開連接");

? ? clearInterval(timer); ? ? ? ? ? ? ? ? ? ? ? //不再繼續發送消息

? });

});

使用HTML5編寫一個WS協議的客戶端應用

var socket = null; ? ? ? ? //創建變量保存socket對象

socket =new WebSocket('ws://127.0.0.1:9001'); ? ?//連接WS服務器

socket.onmessage= function(e){ e.data }; //.onmessage:從服務器接收消息,e.data: 接收的數據

socket.send( msg ); ? ? ?? //向服務器發送消息

socket.close(); ? ? ? ? ? ?//斷開與服務器的連接

Web SQL***************************************************************************************

Web Storage、Web SQL不能跨域名存儲數據,不同域名下存儲的數據互不影響

Web Storage對于存儲較少量的數據有用,但無法存儲更大量的結構化數據,可以使用Web SQL或IndexedDB

Web SQL Database API 未包含在 HTML5 規范之中,它是一個獨立的規范,它引入了一套使用 SQL 操作客戶端數據庫的API,這些 API 有同步的,也有異步的,同步版本的 API 只在工作線程(Worker Threads)上有用,由于并不是所有的瀏覽器都支持工作線程,一般情況下,都會使用異步 API

它的核心方法有三個: openDatabase、transaction 和 executeSql,這些 API 已經被廣泛的實現在了不同的瀏覽器里,尤其是手機端瀏覽器。W3C 官方在2011年11月聲明已經不再維護Web SQL Database 規范

瀏覽器對Web SQL Database的支持情況

IEFirefoxChromeSafariOperaIOS SafariAndroid

6.0(×)7.0(×)13.0(√)3.2(√)11.0(√)3.2(√)2.1(√)

10.0(×)11.0(×)

12.0(×)

規范中定義的三個核心方法:

openDatabase: 使用現有的數據庫或新建的數據庫創建一個數據庫對象

? ? ? ? ? ? ? 需要連接數據庫后才能在 F12→Application→Web SQL中看到數據庫

transaction:? 控制一個事務,以及基于這種情況執行提交或回滾

executeSql: ? 用于執行實際的SQL查詢

var db = openDatabase('mydb'數據庫名稱, '1.0'版本號, 'Test DB'描述文本, 2*1024*1024數據庫大小, [創建回調]); ? ? ? ? ? ? ? ? ? //第五個參數'創建回調'會在創建數據庫后被調用

db.transaction(function(tx){ ? ? ? ?//插入數據

? tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); ?? //創建1個名為LOGS的表

? tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鳥教程")'); ? //插入數據

? tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');

? tx.executeSql('INSERT INTO LOGS (id, log) VALUES (?, ?)', [e_id, e_log]); ? ?//動態插入數據

? ? ? ? ? ? ? ? ? ? ? ? ?? //e_id、e_log是外部變量,executeSql會映射數組參數中的每個條目給'?'

});

db.transaction(function(tx){ ? ? ? ?//查詢數據

? tx.executeSql('SELECT * FROM LOGS', [], function(tx,results){

? ? console.log(results); ? ? ? ? ? //result是查詢到的表的數據

? }, null);

});

db.transaction(function(tx){ ? ? ? ?//刪除記錄

? tx.executeSql('DELETE FROM LOGS WHERE id=1');

? tx.executeSql('DELETE FROM LOGS WHERE id=?', [id]); ? ?//動態刪除指定的數據

});

db.transaction(function(tx){ ? ? ? ?//更新記錄

? tx.executeSql('UPDATE LOGS SET log=\'www.w3cschool.cc\' WHERE id=2');

? tx.executeSql('UPDATE LOGS SET log=\'www.w3cschool.cc\' WHERE id=?', [id]); ? ?//刪除動態的id

});

IndexedDB************************************************************************************

單頁應用基本需要 web service?裝載數據,數據通過控制器注入DOM中,大多數前端框架都這么做

可以緩存靜態網頁和資源文件,尤其是瀏覽的數據,在沒有網絡的時候,可以從當地數據庫緩存中進行讀取

IndexedDB 是被廢棄的 Web SQL 數據庫的代替品。一個鍵值對的 NoSQL 且支持超大儲存(上浮20-50%硬盤空間)的數據庫。支持數據類型 number、string、JSON、blob 等

特點:

①?鍵值對存儲,主鍵獨一無二,不能重復

②?異步,不會鎖死瀏覽器,而localStorage是同步的,會拖慢網頁速度

③?支持事務,只要有一步失敗,整個事務就會取消,數據庫回滾到事務發生之前的狀態,不存在只改寫一部分數據庫的情況(數據記錄的讀寫和刪除,都需要通過事務完成,事務對象提供error、abort、complete三個事件,用來監聽操作結果)

④?同源限制,受同源限制,每個數據庫對應創建它的域名,網頁只能訪問自身域名下的數據庫,不能訪問跨域的數據庫

⑤?存儲空間大,一般不少于250MB

⑥?支持二進制存儲,不僅可以存儲字符串,還可以存儲二進制數據

Indexed Database也可簡稱為 IndexedDB(以前被稱作 WebSimpleDB),是一個Web客戶端存儲結構化數據的規范,在 2009 年由 Oracle 提出。如果說 Web SQL Databae 在客戶端實現了傳統的SQL數據庫操作,那么 Indexed Database 更類似于 NoSQL 的形式來操作數據庫,其中最重要的是 Indexed Database 不使用 SQL 作為查詢語言。其數據存儲可以不需要固定的表格模式,也經常會避免使用SQL的 JOIN 操作,并且一般具有水平可擴展性。目前 W3C 官方也把焦點投到對 Indexed Database 規范的制定當中來,而Microsoft和 Mozilla是對這個規范重要的兩個推動者,Firefox 4 以上已經部分實現了 Indexed DB API,并且 IE 10 中也將實現 Indexed DB API。由于在手機等移動設備的瀏覽器中都沒有實現 Indexed DB API,所以其還有一定的局限性

IEFirefoxChromeSafariOperaIOS SafariAndroid

6.0(×)7.0(√)13.0(√)3.2(×)11.0(×)3.2(×)2.1(×)

9.0(×)5.1(×)11.6(×)5.0(×)4.0(×)

10.0(√)16.0(√)10(√)15(√)10(√)

var request = window.indexedDB.open(databaseName數據庫名, version版本);? ? //打開數據庫

返回IDBRequest對象,通過3種事件(error、success、upgradeneeded)處理打開數據庫的操作結果:

數據庫打開報錯:

request.onerror = function(err){ console.log(err); };

數據庫打開成功

request.onsuccess = function(event){ console.log(request.result); };

如果指定的版本號,大于數據庫的實際版本號,就會發生數據庫升級事件upgradeneeded

request.onupgradeneeded = function(event){ console.log(event.target.result); }

var db = null;

新建對象倉庫(新建表)

request.onupgradeneeded = function(event){

? db = event.target.result;

? var objectStore = null;

? if(!db.objectStoreNames.contains('person')){

? ? objectStore = db.createObjectStore('person', { keyPath: 'id' });

? }

}

新建索引

request.onupgradeneeded = function(event){

? db = event.target.result;

? var objectStore = db.createObjectStore('person', { keyPath: 'id' });

? objectStore.createIndex('name索引名', 'name索引所在屬性', { unique: false }配置對象(該屬性是否包含重復的值));

? objectStore.createIndex('email', 'email', { unique: true });

}

新增數據: 向對象倉庫寫入數據記錄,需要通過事務完成

function add(){

? var request = db.transaction(['person'], 'readwrite')

? .objectStore('person')

? .add({ id: 1, name: '張三', age: 24, email: 'zhangsan@example.com' });

? request.onsuccess = function (event){ console.log('數據寫入成功'); };

? request.onerror = function (event){ console.log('數據寫入失敗'); }

}

讀取數據: 通過事務完成

function read(){

? var transaction = db.transaction(['person']);

? var objectStore = transaction.objectStore('person');

? var request = objectStore.get(1);

? request.onerror = function(event){?console.log('事務失敗'); };

? request.onsuccess = function(event){

? ? if(request.result){

? ? ? console.log('Name: ' + request.result.name);

? ? ? console.log('Age: ' + request.result.age);

? ? ? console.log('Email: ' + request.result.email);

? ? }else{

? ? ? console.log('未獲得數據記錄');

? ? }

? };

}

遍歷數據表格的所有記錄: 使用指針對象 IDBCursor

function readAll(){

? var objectStore = db.transaction('person').objectStore('person');

??objectStore.openCursor().onsuccess = function(event){

? ? var cursor = event.target.result;

? ? if(cursor){

? ? ? console.log('Id: ' + cursor.key);

? ? ? console.log('Name: ' + cursor.value.name);

? ? ? console.log('Age: ' + cursor.value.age);

? ? ? console.log('Email: ' + cursor.value.email);

? ? ? cursor.continue();

? ? }else{

? ? ? console.log('沒有更多數據了!');

? ? }

? };

}

更新數據: 使用 IDBObject.put() 方法

function update(){

? var request = db.transaction(['person'], 'readwrite')

? .objectStore('person').put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' });

?request.onsuccess = function(event){ console.log('數據更新成功'); };

? request.onerror = function(event){ console.log('數據更新失敗'); }

}

刪除記錄:?IDBObjectStore.delete()方法

function remove(){

? var request = db.transaction(['person'], 'readwrite')

? .objectStore('person').delete(1);

? request.onsuccess = function(event){ console.log('數據刪除成功'); };

}

新建表格的時候,對name字段建立了索引,就可以從name找到對應的數據記錄

var transaction = db.transaction(['person'], 'readonly');

var store = transaction.objectStore('person');

var index = store.index('name');

var request = index.get('李四');

request.onsuccess = function(e){

? var result = e.target.result;

? if(result){

? ? // ...

? }else{

? ? // ...

? }

}

文件的讀取和下載*******************************************************************************

文件的讀取:

在html5中,DOM給文件中添加了一個files集合,在選取文件中,files中包含一個File對象,每個對象都有下列4個屬性:

① name: 本地文件的文件名

② size: 文件的大小

③?type: 字符串,文件的MIME類型

④ lastModifiedDate: 字符串,文件上一次被修改的時間

同時,使用FileReader對象,web應用程序可以異步的讀取存儲在用戶計算機上的文件(或者原始數據緩沖)內容,可以使用File對象或者Blob對象來指定所要處理的文件或數據

FileReader提供了以下4個方法:

① readAsText(file, encoding): 以純文本形式讀取文件,將讀取到的文本保存在 result 屬性中。第二個參數用于指定編碼類型,是可選的

② readAsDataURL(file): 讀取文件并將文件以數據 URI 的形式保存在 result 屬性中

③ readAsBinaryString(file): 讀取文件并將一個字符串保存在 result 屬性中,字符串中的每個字符表示一字節

④ readAsArrayBuffer(file): 讀取文件并將一個包含文件內容的 ArrayBuffer 保存在 result 屬性中

文件的下載:

<a href="./file/log.text" download="log.text">下載文件</a>

屬性:

① download: 用于指定下載的文件名

② href:? ? ?要下載的文件的鏈接(需為本地鏈接)

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容