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

使用Vue3的CompositionAPI來優化代碼量

開發 前端
在我的開源項目中有一個組件是用來發送消息和展示消息的,這個組件的邏輯很復雜也是我整個項目的靈魂所在,單文件代碼有1100多行。我每次用webstorm編輯這個文件時,電腦cpu溫度都會飆升并伴隨著卡頓。

[[376028]]

本文轉載自微信公眾號「神奇的程序員k」,作者神奇的程序員k 。轉載本文請聯系神奇的程序員k公眾號。

前言

在我的開源項目中有一個組件是用來發送消息和展示消息的,這個組件的邏輯很復雜也是我整個項目的靈魂所在,單文件代碼有1100多行。我每次用webstorm編輯這個文件時,電腦cpu溫度都會飆升并伴隨著卡頓。

就在前幾天我終于忍不住了,意識到了Vue2的optionsAPI的缺陷,決定用Vue3的CompositionAPI來解決這個問題,本文就跟大家分享下我在優化過程中踩到的坑以及我所采用的解決方案,歡迎各位感興趣的開發者閱讀本文。

問題分析

我們先來看看組件的整體代碼結構,如下圖所示:

image-20210114095802363

  • template部分占用267行
  • script部分占用889行
  • style部分為外部引用占用1行

罪魁禍首就是script部分,本文要優化的就是這一部分的代碼,我們再來細看下script中的代碼結構:

  • props部分占用6行
  • data部分占用52行
  • created部分占用8行
  • mounted部分占用98行
  • methods部分占用672行
  • emits部分占用6行
  • computed部分占用8行
  • watch部分占用26行

現在罪魁禍首是methods部分,那么我們只需要把methods部分的代碼拆分出去,單文件代碼量就大大減少了。

優化方案

經過上述分析后,我們已經知道了問題所在,接下來就跟大家分享下我一開始想到的方案以及最終所采用的方案。

直接拆分成文件

一開始我覺得既然methods方法占用的行數太多,那么我在src下創建一個methods文件夾,把每個組件中的methods的方法按照組件名進行劃分,創建對應的文件夾,在對應的組件文件夾內部,將methods中的方法拆分成獨立的ts文件,最后創建index.ts文件,將其進行統一導出,在組件中使用時按需導入index.ts中暴露出來的模塊,如下圖所示:

image-20210114103824562

  • 創建methods文件夾
  • 把每個組件中的methods的方法按照組件名進行劃分,創建對應的文件夾,即:message-display
  • 將methods中的方法拆分成獨立的ts文件,即:message-display文件夾下的ts文件
  • 創建index.ts文件,即:methods下的index.ts文件

index.ts代碼

如下所示,我們將拆分的模塊方法進行導入,然后統一export出去

  1. import compressPic from "@/methods/message-display/CompressPic"
  2. import pasteHandle from "@/methods/message-display/PasteHandle"
  3.  
  4. export { compressPic, pasteHandle }; 

在組件中使用

最后,我們在組件中按需導入即可,如下所示:

  1. import { compressPic, pasteHandle } from "@/methods/index"
  2.  
  3. export default defineComponent({ 
  4.     mounted() { 
  5.       compressPic(); 
  6.       pasteHandle(); 
  7.     } 
  8. }) 

運行結果

當我自信滿滿的開始跑項目時,發現瀏覽器的控制臺報錯了,提示我this未定義,突然間我意識到將代碼拆分成文件后,this是指向那個文件的,并沒有指向當前組件實例,當然可以將this作為參數傳進去,但我覺得這樣并不妥,用到一個方法就傳一個this進去,會產生很多冗余代碼,因此這個方案被我pass了。

使用mixins

前一個方案因為this的問題以失敗告終,在Vue2.x的時候官方提供了mixins來解決this問題,我們使用mixin來定義我們的函數,最后使用mixins進行混入,這樣就可以在任意地方使用了。

由于mixins是全局混入的,一旦有重名的mixin原來的就會被覆蓋,所以這個方案也不合適,pass。

image-20210114111746208

使用CompositionAPI

上述兩個方案都不合適,那 么CompositionAPI就剛好彌補上述方案的短處,成功的實現了我們想要實現的需求。

我們先來看看什么是CompositionAPI,正如文檔所述,我們可以將原先optionsAPI中定義的函數以及這個函數需要用到的data變量,全部歸類到一起,放到setup函數里,功能開發完成后,將組件需要的函數和data在setup進行return。

setup函數在創建組件之前執行,因此它是沒有this的,這個函數可以接收2個參數: props和context,他們的類型定義如下:

  1. interface Data { 
  2.   [key: string]: unknown 
  3.  
  4. interface SetupContext { 
  5.   attrs: Data 
  6.   slots: Slots 
  7.   emit: (event: string, ...args: unknown[]) => void 
  8. function setup(props: Data, context: SetupContext): Data 

我的組件需要拿到父組件傳過來的props中的值,需要通過emit來向父組件傳遞數據,props和context這兩個參數正好解決了我這個問題。

setup又是個函數,也就意味著我們可以將所有的函數拆分成獨立的ts文件,然后在組件中導入,在setup中將其return給組件即可,這樣就很完美的實現了一開始我們一開始所說的的拆分。

實現思路

接下來的內容會涉及到響應性API,如果對響應式API不了解的開發者請先移步官方文檔。

我們分析出方案后,接下來我們就來看看具體的實現路:

  • 在組件的導出對象中添加setup屬性,傳入props和context
  • 在src下創建module文件夾,將拆分出來的功能代碼按組件進行劃分
  • 將每一個組件中的函數進一步按功能進行細分,此處我分了四個文件夾出來
    • common-methods 公共方法,存放不需要依賴組件實例的方法
    • components-methods 組件方法,存放當前組件模版需要使用的方法
    • main-entrance 主入口,存放setup中使用的函數
    • split-method 拆分出來的方法,存放需要依賴組件實例的方法,setup中函數拆分出來的文件也放在此處
  • 在主入口文件夾中創建InitData.ts文件,該文件用于保存、共享當前組件需要用到的響應式data變量
  • 所有函數拆分完成后,我們在組件中將其導入,在setup中進行return即可

實現過程

接下來我們將上述思路進行實現。

添加setup選項

我們在vue組件的導出部分,在其對象內部添加setup選項,如下所示:

  1. <template> 
  2.   <!---其他內容省略--> 
  3. </template> 
  4. <script lang="ts"
  5. export default defineComponent({ 
  6.   name"message-display"
  7.   props: { 
  8.     listId: String, // 消息id 
  9.     messageStatus: Number, // 消息類型 
  10.     buddyId: String, // 好友id 
  11.     buddyName: String, // 好友昵稱 
  12.     serverTime: String // 服務器時間 
  13.   }, 
  14.   setup(props, context) { 
  15.     // 在此處即可寫響應性API提供的方法,注意⚠️此處不能用this 
  16.   } 
  17. </script> 

創建module模塊

我們在src下創建module文件夾,用于存放我們拆分出來的功能代碼文件。

如下所示,為我創建好的目錄,我的劃分依據是將相同類別的文件放到一起,每個文件夾的所代表的含義已在實現思路進行說明,此處不作過多解釋。

創建InitData.ts文件

我們將組件中用到的響應式數據,統一在這里進行定義,然后在setup中進行return,該文件的部分代碼定義如下,完整代碼請移步:InitData.ts

  1. import { 
  2.   reactive, 
  3.   Ref, 
  4.   ref, 
  5.   getCurrentInstance, 
  6.   ComponentInternalInstance 
  7. from "vue"
  8. import { 
  9.   emojiObj, 
  10.   messageDisplayDataType, 
  11.   msgListType, 
  12.   toolbarObj 
  13. from "@/type/ComponentDataType"
  14. import { Store, useStore } from "vuex"
  15.  
  16. // DOM操作,必須return否則不會生效 
  17. const messagesContainer = ref<HTMLDivElement | null>(null); 
  18. const msgInputContainer = ref<HTMLDivElement | null>(null); 
  19. const selectImg = ref<HTMLImageElement | null>(null); 
  20. // 響應式Data變量 
  21. const messageContent = ref<string>(""); 
  22. const emoticonShowStatus = ref<string>("none"); 
  23. const senderMessageList = reactive([]); 
  24. const isBottomOut = ref<boolean>(true); 
  25. let listId = ref<string>(""); 
  26. let messageStatus = ref<number>(0); 
  27. let buddyId = ref<string>(""); 
  28. let buddyName = ref<string>(""); 
  29. let serverTime = ref<string>(""); 
  30. let emit: (event: string, ...args: any[]) => void = () => { 
  31.   return 0; 
  32. }; 
  33. // store與當前實例 
  34. let $store = useStore(); 
  35. let currentInstance = getCurrentInstance(); 
  36.  
  37. export default function initData(): messageDisplayDataType { 
  38.   // 定義set方法,將props中的數據寫入當前實例 
  39.   const setData = ( 
  40.     listIdParam: Ref<string>, 
  41.     messageStatusParam: Ref<number>, 
  42.     buddyIdParam: Ref<string>, 
  43.     buddyNameParam: Ref<string>, 
  44.     serverTimeParam: Ref<string>, 
  45.     emitParam: (event: string, ...args: any[]) => void 
  46.   ) => { 
  47.     listId = listIdParam; 
  48.     messageStatus = messageStatusParam; 
  49.     buddyId = buddyIdParam; 
  50.     buddyName = buddyNameParam; 
  51.     serverTime = serverTimeParam; 
  52.     emit = emitParam; 
  53.   }; 
  54.   const setProperty = ( 
  55.     storeParam: Store<any>, 
  56.     instanceParam: ComponentInternalInstance | null 
  57.   ) => { 
  58.     $store = storeParam; 
  59.     currentInstance = instanceParam; 
  60.   }; 
  61.    
  62.   // 返回組件需要的Data 
  63.   return { 
  64.     messagesContainer, 
  65.     msgInputContainer, 
  66.     selectImg, 
  67.     $store, 
  68.     emoticonShowStatus, 
  69.     currentInstance, 
  70.     // .... 其他部分省略.... 
  71.     emit 
  72.   } 

??細心的開發者可能已經發現,我把響應式變量定義在導出的函數外面了,之所以這么做是因為setup的一些特殊原因,在下面的踩坑章節我將會詳解我為什么要這樣做。

在組件中使用

定義完相應死變量后,我們就可以在組件中導入使用了,部分代碼如下所示,完整代碼請移步:message-display.vue

  1. import initData from "@/module/message-display/main-entrance/InitData"
  2.  
  3. export default defineComponent({ 
  4.    setup(props, context) { 
  5.     // 初始化組件需要的data數據 
  6.     const { 
  7.       createDisSrc, 
  8.       resourceObj, 
  9.       messageContent, 
  10.       emoticonShowStatus, 
  11.       emojiList, 
  12.       toolbarList, 
  13.       senderMessageList, 
  14.       isBottomOut, 
  15.       audioCtx, 
  16.       arrFrequency, 
  17.       pageStart, 
  18.       pageEnd, 
  19.       pageNo, 
  20.       pageSize, 
  21.       sessionMessageData, 
  22.       msgListPanelHeight, 
  23.       isLoading, 
  24.       isLastPage, 
  25.       msgTotals, 
  26.       isFirstLoading, 
  27.       messagesContainer, 
  28.       msgInputContainer, 
  29.       selectImg 
  30.     } = initData(); 
  31.       
  32.     // 返回組件需要用到的方法 
  33.     return { 
  34.       createDisSrc, 
  35.       resourceObj, 
  36.       messageContent, 
  37.       emoticonShowStatus, 
  38.       emojiList, 
  39.       toolbarList, 
  40.       senderMessageList, 
  41.       isBottomOut, 
  42.       audioCtx, 
  43.       arrFrequency, 
  44.       pageStart, 
  45.       pageEnd, 
  46.       pageNo, 
  47.       pageSize, 
  48.       sessionMessageData, 
  49.       msgListPanelHeight, 
  50.       isLoading, 
  51.       isLastPage, 
  52.       msgTotals, 
  53.       isFirstLoading, 
  54.       messagesContainer, 
  55.       msgInputContainer, 
  56.       selectImg 
  57.     }; 
  58.    } 
  59. }) 

我們定義后響應式變量后,就可以在拆分出來的文件中導入initData函數,訪問里面存儲的變量了。

在文件中訪問initData

我將頁面內所有的事件監聽也拆分成了文件,放在了EventMonitoring.ts中,在事件監聽的處理函數是需要訪問initData里存儲的變量的,接下來我們就來看下如何訪問,部分代碼如下所示,完整代碼請移步EventMonitoring.ts)

  1. import { 
  2.   computed, 
  3.   Ref, 
  4.   ComputedRef, 
  5.   watch, 
  6.   getCurrentInstance, 
  7.   toRefs 
  8. from "vue"
  9. import { useStore } from "vuex"
  10. import initData from "@/module/message-display/main-entrance/InitData"
  11. import { SetupContext } from "@vue/runtime-core"
  12. import _ from "lodash"
  13.  
  14.  
  15. export default function eventMonitoring( 
  16.   props: messageDisplayPropsType, 
  17.   context: SetupContext<any
  18. ): { 
  19.   userID: ComputedRef<string>; 
  20.   onlineUsers: ComputedRef<number>; 
  21. } | void { 
  22.   const $store = useStore(); 
  23.   const currentInstance = getCurrentInstance(); 
  24.   // 獲取傳遞的參數 
  25.   const data = initData(); 
  26.   // 將props改為響應式 
  27.   const prop = toRefs(props); 
  28.   // 獲取data中的數據 
  29.   const senderMessageList = data.senderMessageList; 
  30.   const sessionMessageData = data.sessionMessageData; 
  31.   const pageStart = data.pageStart; 
  32.   const pageEnd = data.pageEnd; 
  33.   const pageNo = data.pageNo; 
  34.   const isLastPage = data.isLastPage; 
  35.   const msgTotals = data.msgTotals; 
  36.   const msgListPanelHeight = data.msgListPanelHeight; 
  37.   const isLoading = data.isLoading; 
  38.   const isFirstLoading = data.isFirstLoading; 
  39.   const listId = data.listId; 
  40.   const messageStatus = data.messageStatus; 
  41.   const buddyId = data.buddyId; 
  42.   const buddyName = data.buddyName; 
  43.   const serverTime = data.serverTime; 
  44.   const messagesContainer = data.messagesContainer as Ref<HTMLDivElement>; 
  45.    
  46.   // 監聽listID改變 
  47.   watch(prop.listId, (newMsgId: string) => { 
  48.     listId.value = newMsgId; 
  49.     messageStatus.value = prop.messageStatus.value; 
  50.     buddyId.value = prop.buddyId.value; 
  51.     buddyName.value = prop.buddyName.value; 
  52.     serverTime.value = prop.serverTime.value; 
  53.     // 消息id發生改變,清空消息列表數據 
  54.     senderMessageList.length = 0; 
  55.     // 初始化分頁數據 
  56.     sessionMessageData.length = 0; 
  57.     pageStart.value = 0; 
  58.     pageEnd.value = 0; 
  59.     pageNo.value = 1; 
  60.     isLastPage.value = false
  61.     msgTotals.value = 0; 
  62.     msgListPanelHeight.value = 0; 
  63.     isLoading.value = false
  64.     isFirstLoading.value = true
  65.   }); 

正如代碼中那樣,在文件中使用時,拿出initData中對應的變量,需要修改其值時,只需要修改他的value即可。

至此,有關compositionAPI的基本使用就跟大家講解完了,下面將跟大家分享下我在實現過程中所踩的坑,以及我的解決方案。

踩坑分享

今天是周四,我周一開始決定使用CompositionAPI來重構我這個組件的,一直搞到昨天晚上才重構完成,前前后后踩了很多坑,正所謂踩坑越多你越強,這句話還是很有道理的??。

接下來就跟大家分享下我踩到的一些坑以及我的解決方案。

dom操作

我的組件需要對dom進行操作,在optionsAPI中可以使用this.$refs.xxx來訪問組件dom,在setup中是沒有this的,翻了下官方文檔后,發現需要通過ref來定義,如下所示:

  1. <template> 
  2. <div ref="msgInputContainer"></div> 
  3. <ul v-for="(item, i) in list" :ref="el => { ulContainer[i] = el }"></ul> 
  4. </template> 
  5.  
  6. <script lang="ts"
  7.   import { ref, reactive, onBeforeUpdate } from "vue"
  8.   setup(){ 
  9.     export default defineComponent({ 
  10.     // DOM操作,必須return否則不會生效 
  11.     // 獲取單一dom 
  12.     const messagesContainer = ref<HTMLDivElement | null>(null); 
  13.     // 獲取列表dom 
  14.     const ulContainer = ref<HTMLUListElement>([]); 
  15.     const list = reactive([1, 2, 3]); 
  16.     // 列表dom在組件更新前必須初始化 
  17.     onBeforeUpdate(() => { 
  18.        ulContainer.value = []; 
  19.     }); 
  20.     return { 
  21.       messagesContainer, 
  22.       list, 
  23.       ulContainer 
  24.     } 
  25.   }) 
  26.   } 
  27. </script> 

訪問vuex

在setup中訪問vuex需要通過useStore()來訪問,代碼如下所示:

  1. import { useStore } from "vuex"
  2.  
  3. const $store = useStore(); 
  4. console.log($store.state.token); 

訪問當前實例

在組件中需要訪問掛載在globalProperties上的東西,在setup中就需要通過getCurrentInstance()來訪問了,代碼如下所示:

  1. import { getCurrentInstance } from "vue"
  2.  
  3. const currentInstance = getCurrentInstance(); 
  4. currentInstance?.appContext.config.globalProperties.$socket.sendObj({ 
  5.   code: 200, 
  6.   token: $store.state.token, 
  7.   userID: $store.state.userID, 
  8.   msg: $store.state.userID + "上線" 
  9. }); 

無法訪問$options

我重構的websocket插件是將監聽消息接收方法放在options上的,需要通過this.$options.xxx來訪問,文檔翻了一圈沒找到有關在setup中使用的內容,那看來是不能訪問了,那么我只能選擇妥協,把插件掛載在options上的方法放到globalProperties上,這樣問題就解決了。

內置方法只能在setup中訪問

如上所述,我們使用到了getCurrentInstance和useStore,這兩個內置方法還有initData中定義的那些響應式數據,只有在setup中使用時才能拿到數據,否則就是null。

我的文件是拆分出去的,有些函數是運行在某個拆分出來的文件中的,不可能都在setup中執行一遍的,響應式變量也不可能全當作參數進行傳遞的,為了解決這個問題,我有試過使用provide注入然后通過inject訪問,結果運行后發現不好使,控制臺報黃色警告說provide和inject只能運行在setup中,我直接裂開,當時發了一條沸點求助了下,到了晚上也沒得到解決方案??。

經過一番求助后,我的好友@前端印象給我提供了一個思路,成功的解決了這個問題,也就是我上面initData的做法,將響應式變量定義在導出函數的外面,這樣我們在拆分出來的文件中導入initData方法時,里面的變量都是指向同一個地址,可以直接訪問存儲在里面的變量且不會將其進行初始化。

至于getCurrentInstance和useStore訪問出現null的情景,還有props、emit的使用問題,我們可以在initData的導出函數內部定義set方法,在setup里的方法中獲取到實例后,通過set方法將其設置進我們定義的變量中。

至此,問題就完美解決了,最后跟大家看下優化后的組件代碼,393行??

圖片

image-20210114201837539

項目地址

項目地址:chat-system-github

在線體驗地址:chat-system

 

責任編輯:武曉燕 來源: 神奇的程序員k
相關推薦

2020-11-12 08:32:14

Vue3模板優化

2025-06-23 11:35:29

VormsVue 3代碼

2021-12-01 08:11:44

Vue3 插件Vue應用

2025-07-07 03:00:00

2024-11-06 10:16:22

2021-12-29 07:51:21

Vue3 插件Vue應用

2021-11-30 08:19:43

Vue3 插件Vue應用

2023-11-28 09:03:59

Vue.jsJavaScript

2022-11-01 11:55:27

ReactVue3

2022-02-18 09:39:51

Vue3.0Vue2.0Script Set

2021-12-02 05:50:35

Vue3 插件Vue應用

2020-09-19 21:15:26

Composition

2021-06-26 06:29:14

Vue 2Vue 3開發

2022-09-06 12:20:30

Vue3CVCRUD

2022-07-15 08:45:07

slotVue3

2025-08-22 13:14:54

2021-11-17 08:24:47

Vue3 插件Vue應用

2021-05-20 07:26:21

工具Vuex Vue.js

2022-07-08 08:52:25

Vue3組合動態返回

2021-12-08 09:09:33

Vue 3 Computed Vue2
點贊
收藏

51CTO技術棧公眾號

粉嫩蜜臀av国产精品网站| japanese在线观看| 我想看黄色大片| 黄网站视频在线观看| 欧美日韩直播| 亚洲日本va在线观看| 51视频国产精品一区二区| 最近免费观看高清韩国日本大全| 三级黄色在线视频| 欧美日本三级| 中文字幕+乱码+中文字幕一区| 久久久久久成人| 日韩视频在线观看一区二区三区| 免费在线黄色影片| 999在线观看精品免费不卡网站| 欧美日韩国产高清一区二区| 美日韩精品免费| 激情综合五月网| 亚洲高清影院| 国产精品欧美一区喷水| 欧美亚洲另类制服自拍| 摸摸摸bbb毛毛毛片| 成人影院大全| 91丨porny丨户外露出| 欧美精品久久久久久久久久| 久操视频免费看| 自由日本语热亚洲人| 国产精品福利电影一区二区三区四区| 国产精品白嫩初高中害羞小美女| 疯狂揉花蒂控制高潮h| av中文字幕电影在线看| 国产成人av电影在线| 日本精品视频在线播放| 三级黄色片网站| 国产精久久久| 亚洲素人一区二区| 久久99精品久久久久久青青日本| 久久久久成人精品无码| 中文字幕亚洲在线观看| 一区二区三区在线播放| 91免费看蜜桃| 久久久久99精品| 精品午夜电影| 精品久久中文字幕| 久久99蜜桃综合影院免费观看| 97在线公开视频| 亚洲字幕久久| 欧美成人一区二区三区在线观看| 国产精品视频网站在线观看| 成人毛片在线精品国产| 伊人狠狠色j香婷婷综合| 精品国产第一区二区三区观看体验| 日韩成人手机在线| 日本高清中文字幕在线| 国产伦精品一区二区三区免费 | 国产视频一区二区三区在线播放| 天天影院图片亚洲| 丝袜a∨在线一区二区三区不卡| 在线日韩精品视频| 色18美女社区| 黄毛片在线观看| 国产清纯美女被跳蛋高潮一区二区久久w| 国产精品视频99| 免费视频一二三区| 在线精品国产| 久久99亚洲精品| 久久精品一区二区免费播放| 国产亚洲精彩久久| 一区二区三区资源| 超碰97在线看| 精品av中文字幕在线毛片| 极品少妇xxxx精品少妇| 久久久久久国产精品美女| avtt天堂在线| 最近国产精品视频| 欧美一区二区三区视频免费播放 | 亚洲欧洲成视频免费观看| 婷婷五月综合缴情在线视频| 免费一级毛片在线观看| 久久伊人中文字幕| 成人免费视频网| 日本少妇毛茸茸高潮| 欧美日韩国产一区二区三区不卡| 69堂亚洲精品首页| 欧美国产激情视频| 欧美精品电影| 久久先锋影音av| 欧日韩一区二区三区| 亚洲高清精品视频| 日本 国产 欧美色综合| 97视频在线观看播放| 97在线观看视频免费| 亚洲日产av中文字幕| 欧美裸体一区二区三区| 免费黄色福利视频| 成人午夜视屏| 欧美美女bb生活片| 亚洲欧美日韩偷拍| 国产色99精品9i| 精品国产一区二区三区久久久蜜月| 怡红院一区二区| 深夜福利久久| yw.139尤物在线精品视频| 亚洲精品视频大全| 日韩理论电影| 国产一区二区三区在线免费观看| 女人18毛片毛片毛片毛片区二| 天天综合精品| 一本一道久久a久久精品逆3p| 欧美自拍偷拍网| 免费短视频成人日韩| 日韩中文字幕在线播放| 免费毛片一区二区三区| 日本特黄久久久高潮| 丁香婷婷久久久综合精品国产 | 中文字幕一区二区三区人妻电影| 色综合久久一区二区三区| 久久久久国产精品免费网站| 91麻豆精品在线| 香蕉精品999视频一区二区| 久久久久国产一区二区三区| 国产精品免费精品一区| 中日韩男男gay无套| 国产综合视频在线观看| 97人妻精品一区二区三区动漫| 粉嫩aⅴ一区二区三区四区| 日本免费高清一区二区| 国产三线在线| 精品久久久久久中文字幕一区奶水 | 国产精品午夜一区二区欲梦| 福利网址在线观看| 久久aⅴ乱码一区二区三区| 91精品国产色综合| 五月天综合激情| 国产精品日本| 日韩av电影国产| 性猛交富婆╳xxx乱大交天津| 国产伦精一区二区三区| 欧美日韩一区二区三区在线视频| 艳母动漫在线看| 久久天天做天天爱综合色| 国产资源第一页| 亚洲精品tv| 国产性色av一区二区| 麻豆视频免费在线播放| 国产一区二区精品| 国产精品三区四区| 日韩av高清在线| 国产欧美精品一区aⅴ影院| 国产av人人夜夜澡人人爽麻豆| 99精品国产九九国产精品| 日韩欧美亚洲国产精品字幕久久久| 亚洲精品成人无码| 色婷婷色综合| 国产精品v片在线观看不卡| 婷婷丁香一区二区三区| 国产女同互慰高潮91漫画| 国产精品自拍片| yy6080久久伦理一区二区| 欧美精品少妇一区二区三区| 成人免费网站黄| 亚洲一区二区三区免费在线观看| 含羞草久久爱69一区| 国产免费视频在线| 亚洲精选免费视频| 国产特级淫片高清视频| 国语一区二区三区| 在线视频亚洲欧美| 国产亚洲色婷婷久久99精品| 国产精品1区2区3区| 欧美日韩在线精品| 国产精品专区免费| 国产亚洲人成网站在线观看| 久久精品五月天| 中文字幕国产一区| 九九热精品在线播放| 国产精东传媒成人av电影| 久久久噜噜噜久久| 亚洲在线精品视频| 99久久er热在这里只有精品66| 亚洲精品在线视频观看| 999av小视频在线| 精品视频偷偷看在线观看 | 国产精品二区一区二区aⅴ污介绍| 美女黄色片视频| 成人线上播放| 日韩亚洲在线观看| 亚洲中文字幕在线观看| 亚洲欧美区自拍先锋| aaa黄色大片| 无码一区二区三区视频| 97视频热人人精品| 蜜桃av.网站在线观看| 日韩午夜小视频| 久久久久亚洲AV成人无在| 奇米色一区二区| 欧美大片免费播放| 日本妇女一区| 国产欧美日韩中文| 成年网站在线视频网站| 亚洲欧美日韩直播| 国产精品视频久久久久久久| 久久午夜色播影院免费高清 | 日韩精品一区二区av| 国产亚洲精品中文字幕| 91专区在线观看| jlzzjlzz亚洲女人| 成人做爰66片免费看网站| 欧亚一区二区| 亚洲天堂成人在线| 99久久精品国产一区二区成人| 欧美激情在线看| 男男受被啪到高潮自述| 五月天久久网站| 国产在线一区二| 久久男人天堂| xvideos亚洲人网站| 亚洲色图欧美视频| 日韩精品中午字幕| 中文字幕一级片| 国产精品视频看| 精品国产一区在线| 国产综合色产在线精品| 女同性恋一区二区| 欧美特黄一级大片| 国产精品网址在线| 五月天av在线| 亚洲视频自拍偷拍| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的 | 激情综合亚洲精品| 免费在线观看日韩视频| 国产精品欧美日韩一区| 国产成人精品av| 在线观看黄色av| 欧美人xxxx| 国产剧情在线视频| 亚洲成a人片在线观看中文| 日韩在线一区视频| 久久久久国产精品一区三寸| 999在线观看视频| 欧美va天堂| 激情小说综合网| 日韩一区二区三区高清在线观看| 欧美激情成人在线视频| 六月婷婷综合网| 6080午夜不卡| 亚洲一区中文字幕永久在线| 日本高清不卡视频| 伊人久久久久久久久久久久久久| 久久精品视频在线看| 狠狠干狠狠操视频| 国产精品v一区二区三区 | 欧美久久精品| 国产精品夜夜夜一区二区三区尤| 美女久久精品| 3d动漫啪啪精品一区二区免费 | 国产一区二区三区成人欧美日韩在线观看| 欧美 国产 精品| 中文字幕午夜精品一区二区三区| 亚洲精品一区国产精品| 菠萝蜜一区二区| 亚洲欧美日本国产有色| 成人同人动漫免费观看 | 成人福利在线| 日韩一级免费观看| 国产手机视频在线| 日韩一区二区三区视频在线 | 日韩成人中文字幕在线观看| 波多野结衣视频在线观看| 亚洲色图都市小说| 一起操在线播放| 久久综合给合久久狠狠狠97色69| 捆绑裸体绳奴bdsm亚洲| 久久av老司机精品网站导航| 久久综合九色综合88i| 久久福利综合| 在线观看日本一区| 亚洲69av| 日本一区视频在线观看| 大奶在线精品| 乱一区二区三区在线播放| 国产成人av| 综合一区中文字幕| 国产综合精品一区| 欧美老熟妇喷水| 蜜桃在线一区二区三区| 欧美牲交a欧美牲交| 久久久久久久波多野高潮日日| 妓院一钑片免看黄大片| 久久 天天综合| zjzjzjzjzj亚洲女人| 久久麻豆一区二区| 欧美xxxooo| 日本一区二区三区高清不卡| 我要看一级黄色录像| 一区二区三区四区不卡视频| 91av在线免费视频| 欧美色网站导航| 成人免费视频国产免费| 欧美日本一区二区在线观看| 性一交一乱一精一晶| 亚洲欧美国产制服动漫| 成人高清免费在线| 自拍偷拍免费精品| 日本无删减在线| 欧美精品做受xxx性少妇| 日本免费在线视频| 国内精品久久久久伊人av| 精品欧美日韩精品| 国产精品91免费在线| 成人午夜888| 欧美日韩电影一区二区三区| 综合久久久久| 欧美成人免费高清视频| 老司机午夜免费精品视频| 天天综合成人网| 久久综合九色综合欧美就去吻| 精品人妻伦九区久久aaa片| 欧美午夜精品在线| 国产精品国产三级国产专区52| 欧美日韩中文字幕一区| 午夜成人鲁丝片午夜精品| 久久精品国产亚洲7777| bestiality新另类大全| 日本成熟性欧美| 欧洲av一区二区| 国产福利一区二区三区在线观看| 色爱综合网欧美| 亚洲乱码国产一区三区| 成人黄色小视频在线观看| 久久久久9999| 亚洲精品精品亚洲| 在线亚洲欧美日韩| 亚洲性夜色噜噜噜7777| 国产资源在线观看入口av| 成人黄动漫网站免费| 啪啪国产精品| 成人av在线播放观看| 精品动漫3d一区二区三区免费| 国产3p在线播放| 国产日产亚洲精品系列| av网站中文字幕| 欧美亚洲高清一区| 国产又黄又大又爽| 在线a欧美视频| 国产精品扒开腿做爽爽爽视频软件| 国语精品中文字幕| 亚洲精选91| 国产喷水theporn| 久久久国产精品麻豆| 可以在线观看av的网站| 欧美精品一区二区三区四区| 一二三四区在线观看| 欧美在线视频网| 欧美国产不卡| 国产精品宾馆在线精品酒店| av电影在线观看一区| 夫妇露脸对白88av| 欧洲一区二区av| 亚洲成人精品女人久久久| 久久婷婷国产麻豆91天堂| 国产夫妻在线播放| 国产精品推荐精品| 日韩午夜激情| 中文字幕一区二区久久人妻网站| 欧美午夜激情视频| 欧洲免费在线视频| 国产精品精品一区二区三区午夜版| 国产成人一区| 亚洲综合欧美在线| 日韩毛片在线免费观看| 少妇太紧太爽又黄又硬又爽| 日韩精品黄色网| 韩国成人在线| 亚洲最新免费视频| 国产精品亚洲专一区二区三区 | 狠狠久久亚洲欧美专区| 在线观看毛片av| 日韩中文字幕在线播放| 蜜桃精品一区二区三区| 五月丁香综合缴情六月小说| 久久夜色精品国产噜噜av| 美女黄页在线观看| 久久精品在线播放| 国产一级成人av| 国产成人手机视频| 亚洲激情综合网| 亚洲aⅴ乱码精品成人区| 国产成人福利网站| 91精品国产福利在线观看麻豆| a在线视频观看| 国产欧美综合色| 99国产揄拍国产精品| 97久久超碰福利国产精品…| 精品国产一区探花在线观看 | 可以免费在线观看的av| 亚洲美女在线观看| 国产一区二区三区免费在线 | segui88久久综合| 色婷婷精品国产一区二区三区|