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

從零開發一款輕量級滑動驗證碼插件(深度復盤)

開發 前端
今天繼續和大家分享一款非常有趣且實用的前端實戰項目——從零基于 react + canvas 實現一個滑動驗證碼,并將其發布到 npm 上供他人使用。

[[425863]]

之前一直在分享 低代碼 和 可視化 的文章,其中涉及到很多有意思的知識點和設計思想,今天繼續和大家分享一款非常有趣且實用的前端實戰項目——從零基于 react + canvas 實現一個滑動驗證碼,并將其發布到 npm 上供他人使用。當然如果大家更喜歡 vue 的開發方式,也不用擔心,文中的設計思想和思路都是通用的,如果大家想學習如何封裝 vue 組件并發布到 npm 上,也可以參考我之前的文章: 從零到一教你基于vue開發一個組件庫。

從這個實戰項目中我們可以學到如下知識點:

  • 前端組件設計的基本思路和技巧
  • canvas 基本知識和使用
  • react hooks 基本知識和使用
  • 滑動驗證碼基本設計原理
  • 如何封裝一款可擴展的滑動驗證碼組件
  • 如何使用 dumi 搭建組件文檔
  • 如何發布自己第一個npm組件包

如果你對以上任意知識點感興趣,相信這篇文章都會給你帶來啟發。

效果演示

圖片

滑動驗證組件基本使用和技術實現

上圖是實現的滑動驗證組件的一個效果演示,當然還有很多配置項可以選擇,以便支持更多 定制化 的場景。接下來我先介紹一下如何安裝和使用這款驗證碼插件,讓大家有一個直觀的體驗,然后我會詳細介紹一下滑動驗證碼的實現思路,如果大家有一定的技術基礎,也可以直接跳到技術實現部分。

基本使用

因為 react-slider-vertify 這款組件我已經發布到 npm 上了,所以大家可以按照如下方式安裝和使用:

1.安裝

  1. # 或者 yarn add @alex_xu/react-slider-vertify 
  2. npm i @alex_xu/react-slider-vertify -S 

2.使用

  1. import React from 'react'
  2. import { Vertify } from '@alex_xu/react-slider-vertify'
  3.  
  4. export default () => { 
  5.     return <Vertify  
  6.             width={320} 
  7.             height={160} 
  8.             onSuccess={() => alert('success')}  
  9.             onFail={() => alert('fail')}  
  10.             onRefresh={() => alert('refresh')}  
  11.         /> 
  12. }; 

通過以上兩步我們就可以輕松使用這款滑動驗證碼組件了,是不是很簡單?

當然我也暴露了很多可配置的屬性,讓大家對組件有更好的控制。參考如下:

技術實現

在做這個項目之前我也研究了一些滑動驗證碼的知識以及已有的技術方案,收獲很多。接下來我會以我的組件設計思路來和大家介紹如何用 react 來實現和封裝滑動驗證碼組件,如果大家有更好的想法和建議, 也可以在評論區隨時和我反饋。

1.組件設計的思路和技巧

每個人都有自己設計組件的方式和風格,但最終目的都是更 優雅 的設計組件。這里我大致列舉一下 優雅 組件的設計指標:

  • 可讀性(代碼格式統一清晰,注釋完整,代碼結構層次分明,編程范式使用得當)
  • 可用性(代碼功能完整,在不同場景都能很好兼容,業務邏輯覆蓋率)
  • 復用性(代碼可以很好的被其他業務模塊復用)
  • 可維護性(代碼易于維護和擴展,并有一定的向下/向上兼容性)
  • 高性能

以上是我自己設計組件的考量指標,大家可以參考一下。

另外設計組件之前我們還需要明確需求,就拿滑動驗證碼組件舉例,我們需要先知道它的使用場景(用于登錄注冊、活動、論壇、短信等高風險業務場景的人機驗證服務)和需求(交互邏輯,以什么樣的方式驗證,需要暴露哪些屬性)。

以上就是我梳理的一個大致的組件開發需求,在開發具體組件之前,如果遇到復雜的業務邏輯,我們還可以將每一個實現步驟列舉出來,然后一一實現,這樣有助于整理我們的思路和更高效的開發。

2.滑動驗證碼基本實現原理

在介紹完組件設計思路和需求分析之后,我們來看看滑動驗證碼的實現原理。

我們都知道設計驗證碼的主要目的是為了防止機器非法暴力地入侵我們的應用,其中核心要解決的問題就是判斷應用是誰在操作(人 or 機器),所以通常的解決方案就是隨機識別。

上圖我們可以看到只有用戶手動將滑塊拖拽到對應的鏤空區域,才算驗證成功,鏤空區域的位置是隨機的(隨機性測試這里暫時以前端的方式來實現,更安全的做法是通過后端來返回位置和圖片)。

基于以上分析我們就可以得出一個基本的滑動驗證碼設計原理圖:

接下來我們就一起封裝這款可擴展的滑動驗證碼組件。

3.封裝一款可擴展的滑動驗證碼組件

按照我開發組件一貫的風格,我會先基于需求來編寫組件的基本框架:

  1. import React, { useRef, useState, useEffect, ReactNode } from 'react'
  2.  
  3. interface IVertifyProp { 
  4.     /** 
  5.      * @description   canvas寬度   
  6.      * @default       320 
  7.      */ 
  8.     width:number,  
  9.     /** 
  10.      * @description   canvas高度   
  11.      * @default       160 
  12.      */ 
  13.     height:number,  
  14.     /** 
  15.      * @description   滑塊邊長   
  16.      * @default       42 
  17.      */ 
  18.      l:number, 
  19.      /** 
  20.      * @description   滑塊半徑  
  21.      * @default       9 
  22.      */ 
  23.       r:number, 
  24.      /** 
  25.      * @description   是否可見 
  26.      * @default       true 
  27.      */ 
  28.       visible:boolean, 
  29.      /** 
  30.      * @description   滑塊文本 
  31.      * @default       向右滑動填充拼圖 
  32.      */ 
  33.       text:string | ReactNode, 
  34.       /** 
  35.      * @description   刷新按鈕icon, 為icon的url地址 
  36.      * @default       - 
  37.      */ 
  38.        refreshIcon:string, 
  39.      /** 
  40.      * @description   用于獲取隨機圖片的url地址 
  41.      * @default       https://picsum.photos/${id}/${width}/${height}, 具體參考https://picsum.photos/, 只需要實現類似接口即可 
  42.      */ 
  43.        imgUrl:string, 
  44.     /** 
  45.      * @description   驗證成功回調   
  46.      * @default       ():void => {} 
  47.      */ 
  48.     onSuccess:VoidFunction,  
  49.     /** 
  50.      * @description   驗證失敗回調   
  51.      * @default       ():void => {} 
  52.      */ 
  53.     onFail:VoidFunction,  
  54.     /** 
  55.      * @description   刷新時回調   
  56.      * @default       ():void => {} 
  57.      */ 
  58.     onRefresh:VoidFunction 
  59.  
  60. export default ({  
  61.     width = 320, 
  62.     height = 160, 
  63.     l = 42, 
  64.     r = 9, 
  65.     imgUrl, 
  66.     text, 
  67.     refreshIcon = 'http://yourimgsite/icon.png'
  68.     visible = true
  69.     onSuccess, 
  70.     onFail, 
  71.     onRefresh 
  72.  }: IVertifyProp) => { 
  73.      return <div className="vertifyWrap"
  74.         <div className="canvasArea"
  75.             <canvas width={width} height={height}></canvas> 
  76.             <canvas className="block" width={width} height={height}></canvas> 
  77.         </div> 
  78.         <div className={sliderClass}> 
  79.             <div className="sliderMask"
  80.                 <div className="slider"
  81.                     <div className="sliderIcon">&rarr;</div> 
  82.                 </div> 
  83.             </div> 
  84.             <div className="sliderText">{ textTip }</div> 
  85.         </div> 
  86.         <div className="refreshIcon" onClick={handleRefresh}></div> 
  87.         <div className="loadingContainer"
  88.             <div className="loadingIcon"></div> 
  89.             <span>加載中...</span> 
  90.         </div> 
  91.     </div> 
  92.  } 

以上就是我們組件的基本框架結構。從代碼中可以發現組件屬性一目了然,這都是提前做好需求整理帶來的好處,它可以讓我們在編寫組件時思路更清晰。在編寫好基本的 css 樣式之后我們看到的界面是這樣的:

接下來我們需要實現以下幾個核心功能:

  • 鏤空效果的 canvas 圖片實現
  • 鏤空圖案 canvas 實現
  • 滑塊移動和驗證邏輯實現

上面的描述可能比較抽象,我畫張圖示意一下:

因為組件實現完全采用的 react hooks ,如果大家對 hooks 不熟悉也可以參考我之前的文章:

10分鐘教你手寫8個常用的自定義hooks

一.實現鏤空效果的 canvas 圖片

在開始 coding 之前我們需要對 canvas 有個基本的了解,建議不熟悉的朋友可以參考高效 canvas 學習文檔: Canvas of MDN。

由上圖可知首先要解決的問題就是如何用 canvas 畫不規則的圖形,這里我簡單的畫個草圖:

我們只需要使用 canvas 提供的 路徑api 畫出上圖的路徑,并將路徑填充為任意半透明的顏色即可。建議大家不熟悉的可以先了解如下 api :

  • beginPath() 開始路徑繪制
  • moveTo() 移動筆觸到指定點
  • arc() 繪制弧形
  • lineTo() 畫線
  • stroke() 描邊
  • fill() 填充
  • clip() 裁切路徑

實現方法如下:

  1. const drawPath  = (ctx:any, x:number, y:number, operation: 'fill' | 'clip') => { 
  2.     ctx.beginPath() 
  3.     ctx.moveTo(x, y) 
  4.     ctx.arc(x + l / 2, y - r + 2, r, 0.72 * PI, 2.26 * PI) 
  5.     ctx.lineTo(x + l, y) 
  6.     ctx.arc(x + l + r - 2, y + l / 2, r, 1.21 * PI, 2.78 * PI) 
  7.     ctx.lineTo(x + l, y + l) 
  8.     ctx.lineTo(x, y + l) 
  9.     // anticlockwise為一個布爾值。為true時,是逆時針方向,否則順時針方向 
  10.     ctx.arc(x + r - 2, y + l / 2, r + 0.4, 2.76 * PI, 1.24 * PI, true
  11.     ctx.lineTo(x, y) 
  12.     ctx.lineWidth = 2 
  13.     ctx.fillStyle = 'rgba(255, 255, 255, 0.8)' 
  14.     ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)' 
  15.     ctx.stroke() 
  16.     ctx.globalCompositeOperation = 'destination-over' 
  17.     // 判斷是填充還是裁切, 裁切主要用于生成圖案滑塊 
  18.     operation === 'fill'? ctx.fill() : ctx.clip() 

這塊實現方案也是參考了 yield 大佬的原生 js 實現,這里需要補充的一點是 canvas 的 globalCompositeOperation 屬性,它的主要目的是設置如何將一個源(新的)圖像繪制到目標(已有)的圖像上。

  • 源圖像 = 我們打算放置到畫布上的繪圖
  • 目標圖像 = 我們已經放置在畫布上的繪圖

w3c上有個形象的例子:

這里之所以設置該屬性是為了讓鏤空的形狀不受背景底圖的影響并覆蓋在背景底圖的上方。如下:

接下來我們只需要將圖片繪制到畫布上即可:

  1. const canvasCtx = canvasRef.current.getContext('2d'
  2. // 繪制鏤空形狀 
  3. drawPath(canvasCtx, 50, 50, 'fill'
  4.  
  5. // 畫入圖片 
  6. canvasCtx.drawImage(img, 0, 0, width, height) 

當然至于如何生成隨機圖片和隨機位置,實現方式也很簡單,前端實現的話采用 Math.random 即可。

二.實現鏤空圖案 canvas

上面實現了鏤空形狀,那么鏤空圖案也類似,我們只需要使用 clip() 方法將圖片裁切到形狀遮罩里,并將鏤空圖案置于畫布左邊即可。代碼如下:

  1. const blockCtx = blockRef.current.getContext('2d'
  2. drawPath(blockCtx, 50, 50, 'clip'
  3. blockCtx.drawImage(img, 0, 0, width, height) 
  4.  
  5. // 提取圖案滑塊并放到最左邊 
  6. const y1 = 50 - r * 2 - 1 
  7. const ImageData = blockCtx.getImageData(xRef.current - 3, y1, L, L) 
  8. // 調整滑塊畫布寬度 
  9. blockRef.current.width = L 
  10. blockCtx.putImageData(ImageData, 0, y1) 

上面的代碼我們用到了 getImageData 和 putImageData,這兩個 api 主要用來獲取 canvas 畫布場景像素數據和對場景進行像素數據的寫入。實現后 的效果如下:

三.實現滑塊移動和驗證邏輯

實現滑塊移動的方案也比較簡單,我們只需要利用鼠標的 event 事件即可:

  • onMouseDown
  • onMouseMove
  • onMouseUp

以上是一個簡單的示意圖,具體實現代碼如下:

  1. const handleDragMove = (e) => { 
  2.     if (!isMouseDownRef.currentreturn false 
  3.     e.preventDefault() 
  4.     // 為了支持移動端, 可以使用e.touches[0] 
  5.     const eventX = e.clientX || e.touches[0].clientX 
  6.     const eventY = e.clientY || e.touches[0].clientY 
  7.     const moveX = eventX - originXRef.current 
  8.     const moveY = eventY - originYRef.current 
  9.     if (moveX < 0 || moveX + 36 >= width) return false 
  10.     setSliderLeft(moveX) 
  11.     const blockLeft = (width - l - 2r) / (width - l) * moveX 
  12.     blockRef.current.style.left = blockLeft + 'px' 

當然我們還需要對拖拽停止后的事件做監聽,來判斷是否驗證成功,并埋入成功和失敗的回調。代碼如下:

  1. const handleDragEnd = (e) => { 
  2.     if (!isMouseDownRef.currentreturn false 
  3.     isMouseDownRef.current = false 
  4.     const eventX = e.clientX || e.changedTouches[0].clientX 
  5.     if (eventX === originXRef.currentreturn false 
  6.     setSliderClass('sliderContainer'
  7.     const { flag, result } = verify() 
  8.     if (flag) { 
  9.       if (result) { 
  10.         setSliderClass('sliderContainer sliderContainer_success'
  11.         // 成功后的自定義回調函數 
  12.         typeof onSuccess === 'function' && onSuccess() 
  13.       } else { 
  14.         // 驗證失敗, 刷新重置 
  15.         setSliderClass('sliderContainer sliderContainer_fail'
  16.         setTextTip('請再試一次')  
  17.         reset() 
  18.       } 
  19.     } else { 
  20.       setSliderClass('sliderContainer sliderContainer_fail'
  21.       // 失敗后的自定義回調函數 
  22.       typeof onFail === 'function' && onFail() 
  23.       setTimeout(reset.bind(this), 1000) 
  24.     } 

實現后的效果如下:

[[425875]]

當然還有一些細節需要優化處理,這里在 github 上有完整的代碼,大家可以參考學習一下,如果大家想對該組件參與貢獻,也可以隨時提 issue。

四.如何使用 dumi 搭建組件文檔

為了讓組件能被其他人更好的理解和使用,我們可以搭建組件文檔。作為一名熱愛開源的前端 coder,編寫組件文檔也是個很好的開發習慣。接下來我們也為 react-slider-vertify 編寫一下組件文檔,這里我使用 dumi 來搭建組件文檔,當然大家也可以用其他方案(比如storybook)。我們先看一下搭建后的效果:

dumi 搭建組件文檔非常簡單,接下來和大家介紹一下安裝使用方式。

1.安裝

  1. $ npx @umijs/create-dumi-lib        # 初始化一個文檔模式的組件庫開發腳手架 
  2. or 
  3. $ yarn create @umijs/dumi-lib 
  4.  
  5. $ npx @umijs/create-dumi-lib --site # 初始化一個站點模式的組件庫開發腳手架 
  6. or 
  7. $ yarn create @umijs/dumi-lib --site 

2.本地運行

  1. npm run dev 
  2. or 
  3. yarn dev 

3.編寫文檔

dumi 約定式的定義了文檔編寫的位置和方式,其官網上也有具體的飯介紹,這里簡單給大家上一個 dumi 搭建的組件目錄結構圖:

 

 

我們可以在 docs 下編寫組件庫文檔首頁和引導頁的說明,在單個組件的文件夾下使用 index.md 來編寫組件自身的使用文檔,當然整個過程非常簡單,我這里舉一個文檔的例子:

通過這種方式 dumi 就可以幫我們自動渲染一個組件使用文檔。如果大家想學習更多組件文檔搭建的內容,也可以在 dumi 官網學習。

五.發布自己第一個npm組件包

最后一個問題就是組件發布。之前很多朋友問我如何將自己的組件發布到 npm 上讓更多人使用,這塊的知識網上有很多資料可以學習,那今天就以滑動驗證碼 @alex_xu/react-slider-vertify 的例子,來和大家做一個簡單的介紹。

1.擁有一個 npm 賬號并登錄

如果大家之前沒有 npm 賬號,可以在 npm 官網 注冊一個,然后用我們熟悉的 IDE 終端登錄一次:

  1. npm login 

跟著提示輸入完用戶名密碼之后我們就能通過命令行發布組件包了:

  1. npm publish --access public 

之所以指令后面會加 public 參數,是為了避免權限問題導致組件包無法發布成功。我們為了省事也可以把發布命令配置到 package.json 中,在組件打包完成后自動發布:

  1.     "scripts": { 
  2.         "start""dumi dev"
  3.         "release""npm run build && npm publish --access public"
  4.   } 

這樣我們就能將組件輕松發布到 npm 上供他人使用啦! 我之前也開源了很多組件庫,如果大家對組件打包細節和構建流程有疑問,也可以參考我之前開源項目的方案。發布到 npm 后的效果:

本文轉載自微信公眾號「趣談前端」

 

責任編輯:姜華 來源: 趣談前端
相關推薦

2023-12-08 08:02:40

開箱React?組件

2018-01-17 15:05:22

框架設計爬蟲Scrapy

2022-07-14 11:31:04

SQLToolsVScode數據庫

2021-09-26 05:00:11

Vscode插件

2021-08-26 05:15:22

圖片編輯器 H5-DooringMitu-Doorin

2022-08-31 08:32:22

數據可視化項目nocode

2021-09-11 21:03:09

可視化搭建框架

2023-12-12 13:50:00

代碼業務狀態

2013-11-28 15:02:34

Ubuntu技巧Geary

2021-09-14 08:38:57

組件開源前端

2022-04-18 19:02:53

chrome擴展瀏覽器

2019-11-26 08:43:44

平臺桌面軟件

2024-01-11 08:19:17

開源界驗證碼滑動類

2022-01-24 11:02:27

PySimpleGUPython計算器

2015-03-17 09:28:04

2016-11-14 15:40:01

Android

2023-06-27 16:42:18

Tinygrad深度學習工具

2022-05-27 10:00:06

C++游戲引擎

2013-06-19 10:19:59

點贊
收藏

51CTO技術棧公眾號

亚洲乱码电影| 国产盗摄一区二区| 日韩中文字幕区一区有砖一区| 日韩高清有码在线| 国产福利影院在线观看| 日韩理伦片在线| 韩国精品久久久| 欧美精品激情在线观看| 狠狠人妻久久久久久综合蜜桃| 性欧美1819sex性高清| 中文字幕不卡在线| 91久久大香伊蕉在人线| 中文字幕亚洲精品在线| 人人狠狠综合久久亚洲婷婷| 欧美一区午夜视频在线观看| 欧美视频在线观看视频| 国产在线视频福利| 国产精选一区二区三区| 91精品国产乱码久久久久久蜜臀| 国产精成人品免费观看| 国产视频一区二区在线播放| 婷婷夜色潮精品综合在线| 亚洲国产欧美一区二区三区不卡| 精品国产亚洲av麻豆| 老鸭窝毛片一区二区三区| 日韩中文字幕在线播放| 中文字幕在线播放一区| 成人看片毛片免费播放器| 亚洲黄色录像片| 日韩av电影免费观看| 高清一区二区三区四区| 日本成人中文字幕| 97免费中文视频在线观看| 992在线观看| 美国十次av导航亚洲入口| 欧美性感一区二区三区| 欧美日韩一道本| 暖暖日本在线观看| 久久久91精品国产一区二区精品| 99热在线播放| 一区二区视频网| 亚洲黄色在线| 久久久999精品视频| 亚洲色成人网站www永久四虎 | 午夜久久久久久久久久一区二区| 色呦呦网站入口| 五月天丁香社区| 免费av网站在线| 亚洲国产精品一区| 久久99热精品| 久久精品亚洲a| 日韩欧美国产精品综合嫩v| 日韩成人av网| 国产成人无码一区二区在线观看| youjizz亚洲| 日韩三级电影网址| 亚洲在线观看网站| 亚洲网站免费| 91精品蜜臀在线一区尤物| 午夜精品中文字幕| 欧美亚洲黄色| 欧美日本韩国一区| 亚洲图色中文字幕| 日韩在线你懂得| 欧美日本视频在线| 亚洲高清av一区二区三区| 免费看一区二区三区| 91精品国产全国免费观看| 日本中文字幕影院| 91精品论坛| 亚洲福利一区二区| 国产精品沙发午睡系列| 黄色污污视频在线观看| 一个色综合av| 日本一级黄视频| 操你啦视频在线| 中文字幕日韩av资源站| 一区二区三区精品国产| av在线电影观看| 91在线视频官网| 久久久婷婷一区二区三区不卡| 丰满熟妇人妻中文字幕| 国产成人av网站| 成人av电影免费| www.天堂av.com| 国产精品99久久久久久久女警| 国产啪精品视频| 中文字幕自拍偷拍| 精品一区二区成人精品| 91精品国产综合久久香蕉最新版 | 日韩国产中文字幕| 捆绑裸体绳奴bdsm亚洲| www.豆豆成人网.com| 精品欧美一区二区久久| 97人妻精品一区二区三区免| 欧美亚视频在线中文字幕免费| 亚洲国产一区自拍| 国产人妻一区二区| 成人国产精品一级毛片视频| 色偷偷噜噜噜亚洲男人| 日本黄色录像视频| 国产专区一区| 欧美在线观看一区二区三区| 一级黄色免费网站| 蜜芽一区二区三区| 成人天堂噜噜噜| 日韩大胆人体| 国产精品久久久久影院色老大| 中文字幕人成一区| 在线观看a级片| 亚洲超丰满肉感bbw| 国产美女三级视频| 欧美a视频在线| 欧美一个色资源| 亚洲熟女一区二区| 国产一区国产二区国产三区| 在线观看免费高清视频97| 强制高潮抽搐sm调教高h| 亚洲青涩在线| 国产精品热视频| 国产三级第一页| 91性感美女视频| 在线免费观看成人网| 91福利在线免费| 欧美亚洲高清一区二区三区不卡| 欧美日韩理论片| 欧美偷窥清纯综合图区| 亚洲天堂色网站| 黄色一级片免费看| 久久精品99国产精品日本| 波多野结衣一区二区三区在线观看 | 三级在线视频观看| 狠狠一区二区三区| 日韩亚洲欧美成人| 久久久久久久久久影院| 秋霞电影网一区二区| 666精品在线| 黄网站在线观看| 亚洲自拍偷拍九九九| 国产精品入口免费软件| 黄色网一区二区| 色婷婷久久av| 欧美特级黄色片| youjizz国产精品| 2021国产视频| 成人国产精品入口免费视频| 日韩欧美在线一区二区三区| 一色道久久88加勒比一| 亚洲午夜精品久久久久久app| 国产成人激情视频| 天堂成人在线视频| 一区二区三区在线视频播放| 亚洲欧美另类动漫| 99国产精品久久一区二区三区| 精品激情国产视频| 波多野结衣绝顶大高潮| 久久久精品免费网站| 免费观看美女裸体网站| 亚洲高清999| 久久久国产91| 一级做a爰片久久毛片16| 久久午夜色播影院免费高清 | 黄色国产在线视频| 午夜精品电影| 91国产在线免费观看| 黄视频网站在线看| 7777精品伊人久久久大香线蕉的 | 精品久久在线| 精品网站999www| 日韩精品一区二区亚洲av观看| 97se亚洲国产综合在线| 国产不卡一区二区视频| 91欧美极品| 久久久久久久久久久久av| 国产高清免费av| 亚洲少妇30p| 手机av在线网| 午夜激情久久| 国产精品日韩一区| 黄色网址视频在线观看| 欧美久久久久久久久久| 国产wwwwxxxx| 黄网站免费久久| 精品一区二区成人免费视频| 伊人久久一区| 欧美美女15p| 亚洲高清在线观看视频| 亚洲成人av一区二区| 女同毛片一区二区三区| 噜噜噜91成人网| 日本一区不卡| 色999韩欧美国产综合俺来也| 精品国模在线视频| 亚洲男人第一天堂| 偷拍亚洲欧洲综合| 欧美18—19性高清hd4k| 奇米影视一区二区三区小说| 在线不卡日本| 日韩欧美中文字幕一区二区三区| 欧美激情精品久久久久久蜜臀| 黄色片一区二区| 疯狂做受xxxx欧美肥白少妇| 毛茸茸free性熟hd| 蜜乳av一区二区三区| 异国色恋浪漫潭| 久久97久久97精品免视看秋霞| 欧美亚洲第一页| 搞黄视频免费在线观看| 欧美一区二区三区四区五区 | 色哟哟在线观看| 精品视频999| 国产性一乱一性一伧一色| 久久亚洲免费视频| xxxx在线免费观看| 99re国产精品| 日韩久久久久久久| 欧美顶级毛片在线播放| 国产精品免费久久久| 污污片在线免费视频| 日韩第一页在线| 中文字幕网址在线| 亚洲伊人伊色伊影伊综合网| 波多野结衣先锋影音| 久久国产精品色| 艳母动漫在线免费观看| 欧洲乱码伦视频免费| 99re视频在线| 中文字幕系列一区| 久久久久久国产精品久久| 国产精品一区二区婷婷| 日韩欧美你懂的| 中国精品一区二区| 午夜视频在线观看一区二区| 91中文字幕永久在线| av电影在线观看完整版一区二区| 日本人视频jizz页码69| 亚洲九九精品| 制服国产精品| 小嫩嫩12欧美| 丁香婷婷久久久综合精品国产| 韩国成人在线| 91国内精品久久| 国产精品久久麻豆| 亚洲欧洲国产伦综合| 性欧美18一19性猛交| 欧美色手机在线观看| 91视频免费网址| 亚洲蜜桃精久久久久久久| 91视频在线网站| 99久久久免费精品国产一区二区| xxxx在线免费观看| 蜜桃视频一区二区三区| 美女日批免费视频| 亚洲大胆在线| 伊人再见免费在线观看高清版| 日韩av在线中文字幕| 免费不卡亚洲欧美| 麻豆一区二区| 国产一区在线免费| 在线精品视频一区| 成人欧美一区二区三区黑人孕妇| 亚洲成人1区| 国产精品免费视频久久久| www.成人影院| 欧美在线观看日本一区| 九色porny丨首页入口在线| 欧美精品久久久久久久久| 国产成人午夜| 日韩一区二区三区在线播放| 91香蕉在线观看| 久久久黄色av| 超碰公开在线| 九九热这里只有精品6| 成人av福利| 欧美理论电影在线观看| 午夜在线激情影院| 欧美疯狂xxxx大交乱88av| free性欧美hd另类精品| 久久影院中文字幕| 亚洲夜夜综合| 欧美激情一区二区三区高清视频| 麻豆av在线免费观看| 欧美激情久久久| 性欧美xxx69hd高清| 欧洲亚洲在线视频| 色香欲www7777综合网| 国产色婷婷国产综合在线理论片a| 天堂综合在线播放| 91亚洲国产成人精品性色| 国产日本亚洲| 国产一区二区在线观看免费播放| 色婷婷久久久| 日本精品一区二区| 亚洲v在线看| 一本大道东京热无码aⅴ| 激情欧美国产欧美| 成人在线免费在线观看| 日韩国产精品大片| 亚洲成人福利在线| 国产在线播精品第三| 女人扒开双腿让男人捅| 久久精品在线免费观看| 登山的目的在线| 亚洲大片一区二区三区| 天堂网中文字幕| 911精品国产一区二区在线| www香蕉视频| 日韩激情在线视频| 成人区精品一区二区不卡| 久久久噜久噜久久综合| 日韩免费福利视频| 亚洲自拍偷拍网址| 特黄特色欧美大片| 综合一区中文字幕| 丝袜亚洲精品中文字幕一区| 亚洲理论中文字幕| 99精品视频一区二区三区| 亚洲精品国产精品国自| 亚洲综合男人的天堂| 波多野结衣理论片| 欧美mv和日韩mv国产网站| 欧美精品videos另类| 97视频在线观看视频免费视频 | 久久久免费观看| 日韩在线短视频| 高清一区二区三区视频| 日韩久久综合| 免费一级特黄毛片| 国产一区中文字幕| 欧美激情 一区| 无码av免费一区二区三区试看| 91精品国自产| 亚洲欧洲高清在线| 77thz桃花论族在线观看| 成人免费福利在线| 欧美日韩激情| 1024av视频| 国产福利一区在线观看| gv天堂gv无码男同在线观看| 亚洲成人www| 国产绿帽刺激高潮对白| 中文字幕欧美专区| 伊人久久综合一区二区| 国产精品久久久对白| 99久久99久久精品国产片果冰| 成年人免费在线播放| 国产mv日韩mv欧美| 少妇视频一区二区| 色先锋aa成人| 青青草观看免费视频在线| 久久久久久久久久久成人| 秋霞一区二区| 男人的天堂视频在线| 国产真实乱偷精品视频免| 影音先锋男人在线| 色综合天天综合色综合av | 国产精品色午夜在线观看| 日韩有码av| 久久综合久久色| 久久人人超碰精品| 亚洲第一在线播放| 亚洲国产小视频在线观看| 24小时免费看片在线观看| 国产成人女人毛片视频在线| 日韩午夜激情| 亚洲国产精品无码久久久久高潮| 亚洲一区免费观看| www.五月激情| 欧美精品中文字幕一区| 日韩精品一区二区三区中文在线| 国内外成人激情免费视频| 九九久久精品视频| 欧美卡一卡二卡三| 欧美大片在线观看一区| 欧美aaaxxxx做受视频| 成人免费看片网址| 国产综合激情| 中文字幕国产专区| 欧美中文字幕不卡| 91在线视频免费看| 成人有码在线播放| 黄色成人91| 日韩av手机在线播放| 欧美日韩在线免费| 国产最新视频在线观看| 国产精品电影网| 天天做天天爱天天综合网2021| 国产精品久久久久久久av福利| 一区二区三区在线视频观看 | 91精品国产99久久久久久红楼| 亚洲欧洲日韩| 黑丝av在线播放| 91黄视频在线观看| av网站在线看| 国产一区二区三区免费不卡| 国产精品久久国产愉拍| www久久久久久久| 日韩欧美中文字幕制服| 91精品国产黑色瑜伽裤| 夜夜爽99久久国产综合精品女不卡 |