精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

從 23.9K 的前端開源項目我學到了啥?

開發 開發工具
在 7年技術寫作,分享6點心得體會 這篇文章中,阿寶哥介紹了自己經常使用的一款不錯的在線繪圖工具 — Excalidraw。

[[430695]]

在 7年技術寫作,分享6點心得體會 這篇文章中,阿寶哥介紹了自己經常使用的一款不錯的在線繪圖工具 — Excalidraw。使用它你可以輕松地繪制各種漂亮的手繪示意圖,目前在 Github 上 Excalidraw 的 Star 數已達 23.9 K,因此它也是一個很不錯的開源項目。

在平時使用 Excalidraw 的時候,阿寶哥發現了該在線工具提供了一些不錯的功能。比如保存 *.excalidraw 文件到指定目錄、拖拽打開 *.excalidraw 文件并保存至當前文件、復制圖片到剪貼板、分享只讀鏈接和實時協作等功能。

提示:上圖演示了拖拽打開 *.excalidraw 文件并保存至當前文件的功能

上述的這些功能,很多都是跟文件操作相關。關于文件處理,阿寶哥之前寫了 文件上傳,搞懂這8種場景就夠了 和 文件下載,搞懂這9種場景就夠了 這兩篇文章。而第三篇文章,阿寶哥就帶大家來分析一下 Excalidraw 背后與文件操作相關的技術。

了解并掌握了這些相關技術之后,在今后的工作中也許就會有用武之地,特別是對于一些在線 Web 編輯器的場景,利用這些技術將會大大提高產品的用戶體驗。比如在支持相關 Web 技術的平臺上,你們開發的在線編輯器就能完美支持 打開->編輯->保存 這個常見的文件處理流程。

話不多說,我們馬上步入正題,這里我們先來分析 保存 .excalidraw 文件到指定目錄 的功能。

一、保存文件到指定目錄

圖片

提示:本文所有演示示例使用的 Chrome 版本為:版本 92.0.4515.159(正式版本) (x86_64)

以上 Gif 動圖演示了保存文件到指定目錄的過程,因為 Excalidraw 這個在線工具是開源的,所以通過分析它的源碼,我們找到了實現 保存文件到指定目錄 功能的實現函數:

  1. // https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L31 
  2. import { fileOpen, fileSave } from "browser-fs-access"
  3.  
  4. export const saveAsJSON = async ( 
  5.   elements: readonly ExcalidrawElement[], 
  6.   appState: AppState, 
  7. ) => { 
  8.   const serialized = serializeAsJSON(elements, appState); 
  9.   const blob = new Blob([serialized], { 
  10.     type: MIME_TYPES.excalidraw, 
  11.   }); 
  12.   
  13.   const fileHandle = await fileSave( 
  14.     blob, 
  15.     { 
  16.       fileName: `${appState.name}.excalidraw`, 
  17.       description: "Excalidraw file"
  18.       extensions: [".excalidraw"], 
  19.     }, 
  20.     isImageFileHandle(appState.fileHandle) ? null : appState.fileHandle, 
  21.   ); 
  22.   return { fileHandle }; 
  23. }; 

由以上代碼可知,在 saveAsJSON 函數內部是通過調用 fileSave 函數來保存文件。fileSave 函數是從 browser-fs-access 這個第三庫導入的。該庫封裝了 File_System_Access_API,該 API 為開發者提供了 讀、寫文件和文件管理 的能力。而 保存文件到指定目錄 的功能,就是通過 showSaveFilePicker 方法來實現的。在 showSaveFilePicker 方法出現之前,在客戶端實現保存文件的功能,比較常見的方案是使用 a 標簽 或 FileSaver.js 這個庫。

  1. const saveFile = async (blob, filename) => { 
  2.   const a = document.createElement('a'); 
  3.   a.download = filename; 
  4.   a.href = URL.createObjectURL(blob); 
  5.   a.addEventListener('click', (e) => { 
  6.     setTimeout(() => URL.revokeObjectURL(a.href), 30 * 1000); 
  7.   }); 
  8.   a.click(); 
  9. }; 

提示:如果你想了解其他的文件下載方式,可以閱讀 文件下載,搞懂這9種場景就夠了 這篇文章。

對于前面介紹的客戶端文件保存的方案來說,它最大的問題就是沒有辦法實現 打開->編輯->保存 這種常見的文件操作流程。因為我們沒有辦法覆蓋原始的文件,只能創建一個新的文件。而使用新的 File_System_Access_API 就可以解決上述的問題,比如我們可以使用 window.showOpenFilePicker 方法來打開文件,在文件編輯完成之后,再使用 window.showSaveFilePicker 來保存文件。

圖片

(文本編輯器地址:https://googlechromelabs.github.io/text-editor/)

下面我們來介紹一下 showSaveFilePicker API,它是 Window 接口中定義的方法,調用該方法后會顯示允許用戶選擇保存路徑的文件選擇器。該方法的簽名如下所示:

  1. let FileSystemFileHandle = Window.showSaveFilePicker(options); 

showSaveFilePicker 方法支持一個對象類型的可選參數,可包含以下屬性:

excludeAcceptAllOption:布爾類型,默認值為 false。默認情況下,選擇器應包含一個不應用任何文件類型過濾器的選項(由下面的 types 選項啟用)。將此選項設置為 true 意味著 types 選項不可用。

types:數組類型,表示允許保存的文件類型列表。數組中的每一項是包含以下屬性的配置對象:

  • description(可選):用于描述允許保存文件類型類別。
  • accept:是一個對象,該對象的 key 是 MIME 類型,值是文件擴展名列表。

調用 showSaveFilePicker 方法之后,會返回一個 FileSystemFileHandle 對象。有了該對象,你就可以調用該對象上的方法來操作文件。比如調用該對象上的 createWritable 方法之后,就會返回 FileSystemWritableFileStream 對象,就可以把數據寫入到文件中。具體的使用方式如下所示:

  1. async function saveFile(blob, filename) { 
  2.   try { 
  3.     const handle = await window.showSaveFilePicker({ 
  4.       suggestedName: filename, 
  5.       types: [ 
  6.         { 
  7.           description: "PNG file"
  8.           accept: { 
  9.             "image/png": [".png"], 
  10.           }, 
  11.         }, 
  12.       ], 
  13.      }); 
  14.     const writable = await handle.createWritable(); 
  15.     await writable.write(blob); 
  16.     await writable.close(); 
  17.     return handle; 
  18.   } catch (err) { 
  19.      console.error(err.name, err.message); 
  20.   } 
  21.  
  22. saveFile(imgBlob, "face.png"); 

當你使用以上的 saveFile 函數,來保存圖片時,就會顯示以下保存文件選擇器:

看到這里是不是覺得 showSaveFilePicker API 功能挺強大的,不過可惜的是該 API 目前的兼容性還不是很好,具體如下圖所示:

(圖片來源:https://caniuse.com/?search=showSaveFilePicker)

showSaveFilePicker 是 File System Access API 中定義的方法,除了 showSaveFilePicker 之外,還有 showOpenFilePicker 和 showDirectoryPicker 等方法。接下來,阿寶哥來簡單介紹一下另外這兩個比較有用的 API。

showOpenFilePicker API,它是 Window 接口中定義的方法,調用該方法后會顯示一個允許用戶選擇一個或多個文件的文件選擇器。該方法的簽名如下所示:

  1. let FileSystemHandles = Window.showOpenFilePicker(); 

showOpenFilePicker 方法支持一個對象類型的可選參數,可包含以下屬性:

multiple:布爾類型,默認值為 false。若設置為 true,則允許選擇多個文件。

excludeAcceptAllOption:布爾類型,默認值為 false。默認情況下,選擇器應包含一個不應用任何文件類型過濾器的選項(由下面的 types 選項啟用)。將此選項設置為 true 意味著 types 選項不可用。

  • types:數組類型,表示允許保存的文件類型列表。數組中的每一項是包含以下屬性的配置對象:
  • description(可選):用于描述允許保存文件類型類別。

accept:是一個對象,該對象的 key 是 MIME 類型,值是文件擴展名列表。

調用 showOpenFilePicker 方法之后,會返回 FileSystemHandles 即 FileSystemFileHandle 對象數組。有了 FileSystemFileHandle 對象,你就可以調用該對象上的方法來操作文件。下面我們來舉一個簡單的使用示例:

  1. <div> 
  2.    <textarea id="container" rows="5" cols="30"></textarea> 
  3. </div> 
  4. <button onclick="openFile()">打開文件</button> 
  5. <script> 
  6.    const container = document.querySelector("#container"); 
  7.    
  8.    async function openFile() { 
  9.      let [fileHandle] = await window.showOpenFilePicker(); 
  10.      const file = await fileHandle.getFile(); 
  11.      const contents = await file.text(); 
  12.      container.value = contents; 
  13.    } 
  14. </script> 

在以上示例中,當用戶點擊 打開文件 按鈕時,就會顯示一個文件選擇器。在選擇文本文件之后,就會把文件中的內容,顯示在 textarea#container 文本框中。對于非文本文件,你可以通過調用 arrayBuffer 方法來讀取文件中的二進制內容。

(圖片來源:https://caniuse.com/?search=showOpenFilePicker)

由上圖可知,目前 showOpenFilePicker API 的兼容性還比較差。但如果你想在支持 File System Access API 的平臺中,優先使用這些 API 的話,可以考慮使用 GoogleChromeLabs 開源的 browser-fs-access 這個庫,該庫可以讓你在支持 File System Access API 的平臺上更方便地使用 File System Access API,而對于不支持的平臺會自動降級使用 <input type="file"> 和 <a download> 的方式。

除了選擇文件之外,我們也可以選擇目錄。針對這種場景,我們就可以使用 showDirectoryPicker API。它是 Window 接口中定義的方法,調用該方法后會顯示一個允許用戶選擇目錄的選擇器。該方法的簽名如下所示:

  1. var FileSystemDirectoryHandle = Window.showDirectoryPicker(); 

與前面介紹的 showOpenFilePicker 方法不同的是,調用 showDirectoryPicker 方法后是,返回的是 FileSystemDirectoryHandle 對象。利用該對象,我們就可以執行一些目錄的相關操作操作。比如讀取目錄的信息、讀取目錄下的指定文件、刪除目錄下的指定文件或在目錄下新建文件等。同樣,我們也來舉一些簡單的示例。

讀取目錄的信息

  1. async function readDirectory() { 
  2.   const dirHandle = await window.showDirectoryPicker(); 
  3.   for await (const entry of dirHandle.values()) { 
  4.     console.log(entry.kind, entry.name); 
  5.   } 

讀取目錄下的指定文件

  1. const container = document.querySelector("#container"); 
  2.  
  3. async function readFile() { 
  4.   const dirHandle = await window.showDirectoryPicker(); 
  5.   const fileHandle = await dirHandle.getFileHandle("hello.txt"); 
  6.   const file = await fileHandle.getFile(); 
  7.   const contents = await file.text(); 
  8.   container.value = contents; 

刪除目錄下的指定文件

  1. async function removeFile() { 
  2.   const dirHandle = await window.showDirectoryPicker(); 
  3.   const result = await dirHandle.removeEntry("hello.copy.txt"); 
  4.   container.value = `刪除hello.copy.txt文件${ 
  5.     typeof result == "undefined" ? "成功" : "失敗" 
  6.   }`; 

需要注意的是,removeEntry 方法除了支持刪除指定文件之外,還可以支持刪除指定目錄。

創建指定文件

  1. async function createFile() { 
  2.   const dirHandle = await window.showDirectoryPicker(); 
  3.   const fileHandle = await dirHandle.getFileHandle("hello.new.txt", { 
  4.     createtrue
  5.   }); 
  6.   container.value = "hello.new.txt文件創建成功!"
  7.   const writable = await fileHandle.createWritable(); 
  8.   await writable.write(new Blob(["大家好,我是阿寶哥!"])); 
  9.   await writable.close(); 

在以上代碼中,我們通過調用 getFileHandle 方法來獲取指定文件,對應的 FileSystemFileHandle 對象。create: true 表示如果在當前目錄下未找到指定文件,則創建新的文件。了解完以上的示例,是不是覺得瀏覽器的文件處理能力越來越強大了。同樣,我們也來看一下 showDirectoryPicker API 的兼容性:

(圖片來源:https://caniuse.com/?search=showDirectoryPicker)

二、拖拽打開 *.excalidraw 文件并保存至當前文件

以上 Gif 動圖演示了拖拽打開 *.excalidraw 文件并保存至當前文件的過程,可以發現在編輯完文件之后,我們只需確認是否保存文件,而無需選擇文件的保存路徑,在大大提高了用戶的使用體驗。

  1. class App extends React.Component<AppProps, AppState> { 
  2.    // 省略大部分代碼 
  3.     const file = event.dataTransfer?.files[0]; 
  4.     if ( 
  5.       file?.type === MIME_TYPES.excalidrawlib || 
  6.       file?.name?.endsWith(".excalidrawlib"
  7.     ) { 
  8.       // 處理導入的控件庫的邏輯 
  9.     } else { 
  10.       this.setState({ isLoading: true }); 
  11.       if (fsSupported) { // 判斷是否支持File System Access API 
  12.         try { 
  13.           const item = event.dataTransfer.items[0]; 
  14.           // 關鍵點:獲取FileSystemHandle對象 
  15.           (file as any).handle = await (item as any).getAsFileSystemHandle(); 
  16.         } catch (error) { 
  17.           console.warn(error.name, error.message); 
  18.         } 
  19.       } 
  20.       // 加載.excalidraw文件到Canvas 
  21.       await this.loadFileToCanvas(file); 
  22.     } 
  23.   }; 

以上代碼的關鍵點是,調用 DataTransferItem.getAsFileSystemHandle() 方法來獲取 FileSystemFileHandle 對象。擁有該對象之后,我們就可以對文件進行讀、寫操作。具體的使用方式如下所示:

讀文件示例

  1. async function getTheFile() { 
  2.   // open file picker 
  3.   [fileHandle] = await window.showOpenFilePicker(pickerOpts); 
  4.  
  5.   // get file contents 
  6.   const fileData = await fileHandle.getFile(); 

寫文件示例

  1. async function writeFile(fileHandle, contents) { 
  2.   // Create a FileSystemWritableFileStream to write to
  3.   const writable = await fileHandle.createWritable(); 
  4.  
  5.   // Write the contents of the file to the stream. 
  6.   await writable.write(contents); 
  7.  
  8.   // Close the file and write the contents to disk. 
  9.   await writable.close(); 

三、復制圖片到剪貼板

  1. // https://github.com/excalidraw/excalidraw/blob/master/src/clipboard.ts 
  2. export const copyBlobToClipboardAsPng = async (blob: Blob) => { 
  3.   await navigator.clipboard.write([ 
  4.     new window.ClipboardItem({ "image/png": blob }), 
  5.   ]); 
  6. }; 

在以上代碼中,copyBlobToClipboardAsPng 函數支持一個 blob 參數,在該函數內部會調用 navigator.clipboard.write 方法,來實現把圖片復制到剪貼板。而對于普通文本來說,你可以通過 navigator.clipboard.writeText 方法,把它們寫入到系統的剪貼板。

其實 navigator.clipboard.write 和 navigator.clipboard.writeText 方法是 Clipboard 接口定義的方法,該接口實現了 Clipboard API,如果用戶授予了相應的權限,就能提供系統剪貼板的讀寫訪問。在 Web 應用程序中,Clipboard API 可用于實現剪切、復制和粘貼功能。該 API 用于取代通過 document.execCommand API 來實現剪貼板的操作。

在實際工作中,我們不需要手動創建 Clipboard 對象,而是通過 navigator.clipboard 來獲取 Clipboard 對象:

在獲取 Clipboard 對象之后,我們就可以利用該對象提供的 API 來訪問剪貼板。比如,通過 navigator.clipboard.readText 方法來讀取剪貼板的內容:

  1. navigator.clipboard.readText().then
  2.   clipText => document.querySelector(".editor").innerText = clipText 
  3. ); 

以上代碼將 HTML 中含有 .editor 類的第一個元素的內容替換為剪貼板的內容。如果剪貼板為空,或者不包含任何文本,則元素的內容將被清空。這是因為在剪貼板為空或者不包含文本時,readText 方法會返回一個空字符串。

異步剪貼板 API 是一個相對較新的 API,瀏覽器仍在逐漸實現它。由于潛在的安全問題和技術復雜性,大多數瀏覽器正在逐步集成這個 API。目前 Navigator API: clipboard 的兼容性如下圖所示:

(圖片來源:https://caniuse.com/mdn-api_navigator_clipboard)

對于瀏覽器擴展來說,你可以請求 clipboardRead 和 clipboardWrite 權限以使用 clipboard.readText() 和 clipboard.writeText()。如果你對 Clipboard 其他 API 感興趣的話,可以閱讀 想要復制圖像?Clipboard API 了解一下 這篇文章。

其實除了上面介紹的技術, Excalidraw 還使用了其他 Web API 來實現特定的功能。比如利用 window.crypto API 來實現導出只讀鏈接時,對畫布數據進行加密保護。利用 WebSocket API 來實現協同編輯和利用 Share API 實現文件共享的功能,感興趣的小伙伴可以閱讀一下 Excalidraw 的相關源碼。

四、總結

本文阿寶哥分析了 Excalidraw 這款在線繪圖工具,所提供的一些不錯功能背后使用的技術。希望閱讀完本文后,你對 File_System_Access_API 中定義的 window.showOpenFilePicker、window.showSaveFilePicker、window.showDirectoryPicker 和 DataTransferItem.getAsFileSystemHandle 這些方法都有一定的了解。

由于目前 File_System_Access_API 的兼容性還不是很好,如果你想在項目中使用它的話。建議你使用 GoogleChromeLabs 開源的 browser-fs-access 這個庫,該庫不僅為我們提供了更簡潔的 API,而且還提供了自動降級的方案。在今后的項目中,有機會的話,小伙伴們可以嘗試一下。

五、參考資源

  • web.dev — excalidraw-and-fugu
  • web.dev — browser-fs-access
  • web.dev — file-system-access
  • MDN — File_System_Access_API
  • MDN — FileSystemFileHandle

 

責任編輯:姜華 來源: 全棧修仙之路
相關推薦

2020-09-25 06:32:25

前端

2021-03-09 09:55:02

Vuejs前端代碼

2020-02-22 15:01:51

后端前端開發

2020-07-07 08:52:16

機器學習機器學習工具人工智能

2022-03-27 09:06:04

React類型定義前端

2020-12-31 10:47:03

開發Vuejs技術

2016-01-18 10:06:05

編程

2021-04-15 08:15:27

Vue.js源碼方法

2024-04-12 08:54:13

從庫數據庫應用

2020-02-22 14:49:30

畢業入職半年感受

2020-11-04 07:13:57

數據工程代碼編程

2021-07-28 07:01:09

薅羊毛架構Vue+SSR

2021-01-02 09:48:13

函數運算js

2020-10-30 12:40:04

Reac性能優化

2019-08-27 10:49:30

跳槽那些事兒技術Linux

2019-08-16 17:14:28

跳槽那些事兒技術Linux

2013-06-27 10:31:39

2015-06-29 13:47:19

創業創業智慧

2011-10-18 11:43:25

UNIXC語言丹尼斯·里奇

2023-06-06 08:14:18

核心Docker應用程序
點贊
收藏

51CTO技術棧公眾號

国产精品日韩av| 精品国产乱码久久久久久夜甘婷婷 | 717成人午夜免费福利电影| 中国一级黄色录像| 日本毛片在线观看| 日韩不卡手机在线v区| 久久精品99无色码中文字幕| 日韩精品视频一区二区| 精品视频在线一区二区在线| 亚洲女爱视频在线| 久久久久久久久久久一区| 在线播放国产一区| 夜夜嗨一区二区| 日韩在线视频播放| 亚洲中文字幕一区| 国产高清日韩| 欧美性猛交xxxx偷拍洗澡| 在线免费观看一区二区三区| 天天操天天干天天操| 美腿丝袜亚洲色图| 3344国产精品免费看| 永久免费看片直接| 国产成人一区| 日韩美一区二区三区| 美女喷白浆视频| 51漫画成人app入口| 最新中文字幕一区二区三区| 日本不卡一区| 天堂在线视频免费| 国产精品综合在线视频| 国产精品电影在线观看| 国产系列精品av| 91精品国产91久久久久久密臀| 亚洲裸体xxxx| 国产一级免费片| 免费观看性欧美大片无片| 91国产成人在线| 日本日本19xxxⅹhd乱影响| 超碰在线免费播放| 国产精品成人免费| 日韩久久在线| 看电影就来5566av视频在线播放| 成人av电影在线观看| 91免费在线视频网站| 中文字幕一区二区三区四区免费看 | 日韩精品人妻中文字幕| 伊人久久大香线蕉综合四虎小说| 中文字幕国产日韩| 无码一区二区三区在线| 天堂99x99es久久精品免费| 精品三级av在线| 国产精品igao网网址不卡| 999色成人| 精品视频在线看| 网站一区二区三区| jizzjizz少妇亚洲水多| 91成人国产精品| 男人的天堂日韩| 日韩欧美精品电影| 欧美亚洲免费在线一区| 亚洲男人天堂色| 欧美电影免费看| 色菇凉天天综合网| 2025韩国理伦片在线观看| 激情亚洲小说| 91精品国产色综合久久| 91欧美一区二区三区| 国模大尺度视频一区二区| 欧美精品tushy高清| 手机av在线网站| 深夜激情久久| 日韩电视剧在线观看免费网站| 特级西西人体wwwww| 美女少妇全过程你懂的久久| 亚洲人线精品午夜| jizz日本在线播放| 影视一区二区| 久久人人爽人人爽人人片av高请| 日韩精品一区三区| 丝袜亚洲另类欧美综合| 91精品美女在线| 99热这里只有精品66| 丁香亚洲综合激情啪啪综合| 激情小说网站亚洲综合网| 久久综合九色综合久| 国产精品免费丝袜| 日韩黄色片在线| 自拍偷拍亚洲视频| 欧美日韩国产成人在线免费| 欧美一级片在线免费观看| 青青操综合网| 日韩有码片在线观看| 久久久久久久久久久久久久久久久| 亚洲深夜福利| 国产日韩欧美影视| 欧美一级在线免费观看| 国产欧美一区二区精品性 | 欧美日韩一视频区二区| 青青精品视频播放| 在线观看免费视频a| 国产69精品一区二区亚洲孕妇| 久久综合一区| av毛片在线看| 日本电影亚洲天堂一区| 亚洲成a人无码| 久久激情电影| 97在线视频精品| 亚洲一区中文字幕永久在线| 不卡在线视频中文字幕| 亚洲一区二区三区免费看| segui88久久综合| 欧美精选在线播放| 午夜一区二区三区免费| 午夜天堂精品久久久久| 国产精品96久久久久久又黄又硬 | 亚洲高清不卡av| 亚洲不卡的av| 一区二区三区国产盗摄| 亚洲一区二区久久久久久久| 国产鲁鲁视频在线观看免费| 亚洲图片欧美视频| 国产成人在线综合| 国产欧美日韩一区二区三区四区| 久久人人爽人人| 99久久久久久久| 日本一区二区综合亚洲| 国产亚洲综合视频| av综合网址| 久久亚洲精品中文字幕冲田杏梨| 日韩一级在线视频| 99久久久久免费精品国产 | 激情成人亚洲| 成人av电影天堂| av大片在线播放| 色94色欧美sute亚洲线路二| 99re久久精品国产| 午夜精品亚洲| 51国偷自产一区二区三区的来源| av色图一区| 欧美综合久久久| 久久成人激情视频| 久久视频一区| 欧洲av一区| 欧美momandson| 亚洲另类图片色| 无码人妻丰满熟妇奶水区码| 2021国产精品久久精品| 亚洲熟妇av一区二区三区漫画| 白白在线精品| 欧美精品videosex性欧美| 成 人片 黄 色 大 片| 亚洲免费电影在线| 麻豆精品国产传媒| 欧美午夜不卡| 国产亚洲欧美另类一区二区三区| 久久一卡二卡| 亚洲成年人影院在线| 国产情侣自拍av| 91网站视频在线观看| 久久9精品区-无套内射无码| 亚洲免费观看高清完整版在线观| 日本精品免费一区二区三区| 美国一级片在线免费观看视频| 色综合视频在线观看| 久久久久亚洲av无码专区桃色| 久久久综合网| 小说区图片区图片区另类灬| 日本一区二区三区中文字幕| 久久久精品中文字幕| 国产夫妻自拍av| 亚洲第一在线综合网站| 亚洲av无码一区二区三区观看| 国产亚洲成人一区| 亚洲精品人成| 日韩三级久久| 97国产精品视频| 男人天堂综合| 欧美午夜精品一区二区三区| 国产av无码专区亚洲av毛网站| 懂色av中文字幕一区二区三区| 黄页网站大全在线观看| 国产日产精品_国产精品毛片| 国产日韩精品电影| 激情网站在线| 国产一区二区av| www天堂在线| 精品久久久久久久久久久| 丰满的亚洲女人毛茸茸| 国产精品 欧美精品| 一本大道熟女人妻中文字幕在线 | 综合网五月天| 红杏aⅴ成人免费视频| 国产精品国内视频| 久草在线视频资源| 综合国产在线视频| 黄色成人一级片| 欧美日韩成人在线| 国产精品99精品| 国产精品麻豆欧美日韩ww| 无码人妻一区二区三区精品视频| 石原莉奈一区二区三区在线观看| 超碰10000| 精品一区二区三区中文字幕老牛| 97超碰资源| 欧美日韩亚洲国产| 久久久久久一区二区三区| seseavlu视频在线| 亚洲精品mp4| 99久久国产热无码精品免费| 日韩欧美主播在线| 欧美日韩激情在线观看| 国产精品天干天干在线综合| 风间由美一二三区av片| 国产精一品亚洲二区在线视频| 激情内射人妻1区2区3区| 狠狠爱成人网| 特色特色大片在线| 日韩在线精品| 欧美国产视频在线观看| a看欧美黄色女同性恋| 成人免费网站在线看| 国模一区二区| 91超碰中文字幕久久精品| 污片视频在线免费观看| 日韩在线视频免费观看高清中文 | 日韩中文字幕不卡视频| 青青免费在线视频| 亚洲精品一区二区三区精华液| 亚洲视频在线观看一区二区| 一本一道波多野结衣一区二区| 亚洲国产综合久久| 亚洲国产另类av| 麻豆亚洲av熟女国产一区二 | 亚洲欧美综合一区| 国产91久久精品一区二区| 精品乱码一区二区三区| 亚洲国产中文在线| 亚洲一区久久久| 久久gogo国模啪啪裸体| 亚洲a中文字幕| 视频91a欧美| 国产精品男人的天堂| 欧美性理论片在线观看片免费| 奇米4444一区二区三区| 午夜久久中文| 欧美一级bbbbb性bbbb喷潮片| cao在线视频| 午夜精品一区二区三区在线播放| 欧美性猛片xxxxx免费中国| 久久av.com| av在线官网| 欧美成年人视频网站欧美| 黄色网页在线免费看| 久久婷婷国产麻豆91天堂| 精品国产99久久久久久| 久久在线观看视频| 污视频网站免费在线观看| 欧美激情2020午夜免费观看| 欧美v亚洲v| 91精品国产免费久久久久久 | 成人妇女免费播放久久久| 亚洲精品tv| 亚洲资源在线看| 91亚洲无吗| 久久另类ts人妖一区二区| 要久久电视剧全集免费| 日韩久久在线| 91精品精品| 无码av天堂一区二区三区| 国产麻豆综合| 色国产在线视频| 极品少妇xxxx精品少妇| 国产一精品一aⅴ一免费| 成人动漫一区二区| 中文字幕网站在线观看| 一区免费观看视频| 国产在线欧美在线| 日韩欧美精品中文字幕| 在线观看视频中文字幕| 日韩欧美国产一二三区| 日本中文字幕电影在线观看 | 黄色片视频免费观看| 国产嫩草影院久久久久| 婷婷色中文字幕| 精品国产精品自拍| 一本一道精品欧美中文字幕| 欧美一级国产精品| 久草视频视频在线播放| 欧美尺度大的性做爰视频| 欧美gv在线观看| 成人av在线网址| 欧美重口另类| 中国成人亚色综合网站| 国产欧美丝祙| 亚洲在线观看网站| 久久久久久久久久美女| 精品自拍偷拍视频| 一本大道av伊人久久综合| 国产视频一区二区三区四区五区| 日韩电视剧在线观看免费网站 | 久久久久九九九九| yiren22亚洲综合| 国产精品久久精品国产| 日韩欧美一区免费| 成年人视频观看| 国产乱色国产精品免费视频| 神马久久久久久久久久久| 亚洲成人一区在线| 国产精品热久久| 国产亚洲精品久久| 欧美极品videos大乳护士| 91视频免费网站| 欧美性感美女一区二区| 精品国产免费av| 国产成人av自拍| 中文国语毛片高清视频| 日韩欧亚中文在线| 午夜福利理论片在线观看| 久久99精品久久久久久琪琪| 国精品产品一区| 日本精品一区二区| 亚洲在线观看| 精品人妻一区二区三区日产| 亚洲黄色免费电影| 国产精选久久久| 中文字幕久久亚洲| jizz亚洲女人高潮大叫| 日韩伦理一区二区三区av在线| 在线亚洲伦理| 精品人妻一区二区三区日产| 亚洲一区视频在线观看视频| 99热这里只有精品5| 久久综合88中文色鬼| 福利视频一区| 亚洲欧洲国产日韩精品| 日韩在线a电影| 免费毛片视频网站| 色综合久久综合网欧美综合网| 日本波多野结衣在线| 欧美丰满少妇xxxxx| 日韩中文字幕| 屁屁影院ccyy国产第一页| 国产传媒一区在线| 久久久久成人精品无码| 日韩免费高清av| 国产美女情趣调教h一区二区| 91久久伊人青青碰碰婷婷| 在线精品国产| 中文字幕1区2区| 亚洲黄色尤物视频| 成人毛片在线精品国产| 久久久欧美一区二区| 日韩欧美ww| 欧美日韩一区二区在线免费观看 | 91麻豆精品91久久久久久清纯| 免费网站黄在线观看| 91久热免费在线视频| 综合久久十次| 亚洲婷婷在线观看| 一本久久a久久免费精品不卡| 国产玉足榨精视频在线观看| 国产精品美女在线| 国产精品99一区二区三| 欧美一级免费在线| 亚洲国产成人91porn| 色视频精品视频在线观看| 国产成人综合精品在线| 色婷婷色综合| www日本在线观看| 黄色一区二区三区| 高h视频在线| 91视频免费网站| 国产日韩一区| 嘿嘿视频在线观看| 日韩一区二区三区观看| 99thz桃花论族在线播放| 日韩精品伦理第一区| 国产自产高清不卡| 国产精品suv一区二区| 亚洲欧洲视频在线| 中文字幕日本一区| 国产素人在线观看| 国产精品福利av| 日本xxxxxwwwww| 国产精品人成电影| 红桃视频亚洲| 蜜桃av乱码一区二区三区| 欧美一区二区国产| 成人黄色免费短视频| 99热这里只有精品7| 91最新地址在线播放| 国产乱人乱偷精品视频a人人澡| 欧美国产中文字幕| 国产精品一国产精品| 中文字幕一二三| 在线免费亚洲电影| 黄网av在线| 伊人久久av导航| 91麻豆精品视频| 99国产精品一区二区三区|