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

Vue 3 的組合 API 如何請求數據?

開發 前端
Vue 3 已經發布一段時間了,其組合 API 多少有點 React Hooks 的影子在里面,今天我也打算通過這種方式來學習下組合 API。

 [[347295]]

前言

之前在學習 React Hooks 的過程中,看到一篇外網文章,通過 Hooks 來請求數據,并將這段邏輯抽象成一個新的 Hooks 給其他組件復用,我也在我的博客里翻譯了一下:《在 React Hooks 中如何請求數據?》,感興趣可以看看。雖然是去年的文章,在閱讀之后一下子就掌握了 Hooks 的使用方式,而且數據請求是在業務代碼中很常用的邏輯。

Vue 3 已經發布一段時間了,其組合 API 多少有點 React Hooks 的影子在里面,今天我也打算通過這種方式來學習下組合 API。

項目初始化

為了快速啟動一個 Vue 3 項目,我們直接使用當下最熱門的工具 Vite 來初始化項目。整個過程一氣呵成,行云流水。

  1. npm init vite-app vue3-app 
  1. # 打開生成的項目文件夾 
  2. cd vue3-app 
  3. # 安裝依賴 
  4. npm install 
  5. # 啟動項目 
  6. npm run dev 

我們打開 App.vue 將生成的代碼先刪掉。

組合 API 的入口

接下來我們將通過 Hacker News API 來獲取一些熱門文章,Hacker News API返回的數據結構如下:

  1.   "hits": [ 
  2.     { 
  3.       "objectID""24518295"
  4.       "title""Vue.js 3"
  5.       "url""https://github.com/vuejs/vue-next/releases/tag/v3.0.0"
  6.     }, 
  7.     {...}, 
  8.     {...}, 
  9.   ] 

我們通過 ui > li 將新聞列表展示到界面上,新聞數據從 hits 遍歷中獲取。

  1. <template> 
  2.   <ul> 
  3.     <li 
  4.       v-for="item of hits" 
  5.       :key="item.objectID" 
  6.     > 
  7.       <a :href="item.url">{{item.title}}</a> 
  8.     </li> 
  9.   </ul> 
  10. </template> 
  11.  
  12. <script> 
  13. import { reactive } from 'vue' 
  14.  
  15. export default { 
  16.   setup() { 
  17.     const state = reactive({ 
  18.       hits: [] 
  19.     }) 
  20.     return state 
  21.   } 
  22. </script> 

 

在講解數據請求前,我看先看看 setup() 方法,組合 API 需要通過 setup() 方法來啟動,setup() 返回的數據可以在模板內使用,可以簡單理解為 Vue 2 里面 data() 方法返回的數據,不同的是,返回的數據需要先經過 reactive() 方法進行包裹,將數據變成響應式。

組合 API 中請求數據

在 Vue 2 中,我們請求數據時,通常需要將發起請求的代碼放到某個生命周期中(created或 mounted)。在 setup() 方法內,我們可以使用 Vue 3 提供的生命周期鉤子將請求放到特定生命周期內,關于生命周期鉤子方法與之前生命周期的對比如下:

 

 


生命周期

 

 

可以看到,基本上就是在之前的方法名前加上了一個 on,且并沒有提供 onCreated 的鉤子,因為在 setup() 內執行就相當于在 created 階段執行。下面我們在 mounted 階段來請求數據:

  1. import { reactive, onMounted } from 'vue' 
  2.  
  3. export default { 
  4.   setup() { 
  5.     const state = reactive({ 
  6.       hits: [] 
  7.     }) 
  8.     onMounted(async () => { 
  9.       const data = await fetch
  10.         'https://hn.algolia.com/api/v1/search?query=vue' 
  11.       ).then(rsp => rsp.json()) 
  12.       state.hits = data.hits 
  13.     }) 
  14.     return state 
  15.   } 

最后效果如下:

Demo

 

監聽數據變動

Hacker News 的查詢接口有一個 query 參數,前面的案例中,我們將這個參數固定了,現在我們通過響應式的數據來定義這個變量。

  1. <template> 
  2.   <input type="text" v-model="query" /> 
  3.   <ul> 
  4.     <li 
  5.       v-for="item of hits" 
  6.       :key="item.objectID" 
  7.     > 
  8.       <a :href="item.url">{{item.title}}</a> 
  9.     </li> 
  10.   </ul> 
  11. </template> 
  12.  
  13. <script> 
  14. import { reactive, onMounted } from 'vue' 
  15.  
  16. export default { 
  17.   setup() { 
  18.     const state = reactive({ 
  19.       query: 'vue'
  20.       hits: [] 
  21.     }) 
  22.     onMounted((async () => { 
  23.       const data = await fetch
  24.         `https://hn.algolia.com/api/v1/search?query=${state.query}` 
  25.       ).then(rsp => rsp.json()) 
  26.       state.hits = data.hits 
  27.     }) 
  28.     return state 
  29.   } 
  30. </script> 

現在我們在輸入框修改,就能觸發 state.query 同步更新,但是并不會觸發 fetch 重新調用,所以我們需要通過 watchEffect() 來監聽響應數據的變化。

  1. import { reactive, onMounted, watchEffect } from 'vue' 
  2.  
  3. export default { 
  4.   setup() { 
  5.     const state = reactive({ 
  6.       query: 'vue'
  7.       hits: [] 
  8.     }) 
  9.     const fetchData = async (query) => { 
  10.       const data = await fetch
  11.         `https://hn.algolia.com/api/v1/search?query=${query}` 
  12.       ).then(rsp => rsp.json()) 
  13.       state.hits = data.hits 
  14.     } 
  15.     onMounted(() => { 
  16.       fetchData(state.query) 
  17.       watchEffect(() => { 
  18.         fetchData(state.query) 
  19.       }) 
  20.     }) 
  21.     return state 
  22.   } 

由于 watchEffect() 首次調用的時候,其回調就會執行一次,造成初始化時會請求兩次接口,所以我們需要把 onMounted 中的 fetchData 刪掉。

  1. onMounted(() => { 
  2. - fetchData(state.query) 
  3.   watchEffect(() => { 
  4.     fetchData(state.query) 
  5.   }) 
  6. }) 

 

 


Demo

 

 

watchEffect() 會監聽傳入函數內所有的響應式數據,一旦其中的某個數據發生變化,函數就會重新執行。如果要取消監聽,可以調用 watchEffect() 的返回值,它的返回值為一個函數。下面舉個例子:

  1. const stop = watchEffect(() => { 
  2.   if (state.query === 'vue3') { 
  3.     // 當 query 為 vue3 時,停止監聽 
  4.     stop() 
  5.   } 
  6.   fetchData(state.query) 
  7. }) 

當我們在輸入框輸入 "vue3" 后,就不會再發起請求了。

 

 


Demo

 

 

返回事件方法

現在有個問題就是 input 內的值每次修改都會觸發一次請求,我們可以增加一個按鈕,點擊按鈕后再觸發 state.query 的更新。

  1. <template> 
  2.   <input type="text" v-model="input" /> 
  3.   <button @click="setQuery">搜索</button> 
  4.   <ul> 
  5.     <li 
  6.       v-for="item of hits" 
  7.       :key="item.objectID" 
  8.     > 
  9.       <a :href="item.url">{{item.title}}</a> 
  10.     </li> 
  11.   </ul> 
  12. </template> 
  13.  
  14. <script> 
  15. import { reactive, onMounted, watchEffect } from 'vue' 
  16.  
  17. export default { 
  18.   setup() { 
  19.     const state = reactive({ 
  20.       input: 'vue'
  21.       query: 'vue'
  22.       hits: [] 
  23.     }) 
  24.     const fetchData = async (query) => { 
  25.       const data = await fetch
  26.         `https://hn.algolia.com/api/v1/search?query=${query}` 
  27.       ).then(rsp => rsp.json()) 
  28.       state.hits = data.hits 
  29.     } 
  30.     onMounted(() => { 
  31.       watchEffect(() => { 
  32.         fetchData(state.query) 
  33.       }) 
  34.     }) 
  35.      
  36.     const setQuery = () => { 
  37.       state.query = state.input 
  38.     } 
  39.     return { setQuery, state } 
  40.   } 
  41. </script> 

 

可以注意到 button 綁定的 click 事件的方法,也是通過 setup() 方法返回的,我們可以將 setup() 方法返回值理解為 Vue2 中 data() 方法和 methods 對象的合并。

原先的返回值 state 變成了現在返回值的一個屬性,所以我們在模板層取數據的時候,需要進行一些修改,在前面加上 state.。

  1. <template> 
  2.   <input type="text" v-model="state.input" /> 
  3.   <button @click="setQuery">搜索</button> 
  4.   <ul> 
  5.     <li 
  6.       v-for="item of state.hits" 
  7.       :key="item.objectID" 
  8.     > 
  9.       <a :href="item.url">{{item.title}}</a> 
  10.     </li> 
  11.   </ul> 
  12. </template> 

 

 

 


Demo

 

 

返回數據

修改作為強迫癥患者,在模板層通過 state.xxx 的方式獲取數據實在是難受,那我們是不是可以通過對象解構的方式將 state 的數據返回呢?

  1. <template> 
  2.   <input type="text" v-model="input" /> 
  3.   <button class="search-btn" @click="setQuery">搜索</button> 
  4.   <ul class="results"
  5.     <li 
  6.       v-for="item of hits" 
  7.       :key="item.objectID" 
  8.     > 
  9.       <a :href="item.url">{{item.title}}</a> 
  10.     </li> 
  11.   </ul> 
  12. </template> 
  13.  
  14. <script> 
  15. import { reactive, onMounted, watchEffect } from 'vue' 
  16.  
  17. export default { 
  18.   setup(props, ctx) { 
  19.     const state = reactive({ 
  20.       input: 'vue'
  21.       query: 'vue'
  22.       hits: [] 
  23.     }) 
  24.     // 省略部分代碼... 
  25.     return { 
  26.       ...state, 
  27.       setQuery, 
  28.     } 
  29.   } 
  30. </script> 

 

答案是『不可以』。修改代碼后,可以看到頁面雖然發起了請求,但是頁面并沒有展示數據。

state 在解構后,數據就變成了靜態數據,不能再被跟蹤,返回值類似于:

  1. export default { 
  2.   setup(props, ctx) { 
  3.     // 省略部分代碼... 
  4.     return { 
  5.       input: 'vue'
  6.       query: 'vue'
  7.       hits: [], 
  8.       setQuery, 
  9.     } 
  10.   } 

 

Demo

 

為了跟蹤基礎類型的數據(即非對象數據),Vue3 也提出了解決方案:ref() 。

  1. import { ref } from 'vue' 
  2.  
  3. const count = ref(0) 
  4. console.log(count.value) // 0 
  5.  
  6. count.value++ 
  7. console.log(count.value) // 1 

上面為 Vue 3 的官方案例,ref() 方法返回的是一個對象,無論是修改還是獲取,都需要取返回對象的 value 屬性。

我們將 state 從響應對象改為一個普通對象,然后所有屬性都使用 ref 包裹,這樣修改后,后續的解構才做才能生效。這樣的弊端就是,state 的每個屬性在修改時,都必須取其value 屬性。但是在模板中不需要追加 .value,Vue 3 內部有對其進行處理。

  1. import { ref, onMounted, watchEffect } from 'vue' 
  2. export default { 
  3.   setup() { 
  4.     const state = { 
  5.       input: ref('vue'), 
  6.       query: ref('vue'), 
  7.       hits: ref([]) 
  8.     } 
  9.     const fetchData = async (query) => { 
  10.       const data = await fetch
  11.         `https://hn.algolia.com/api/v1/search?query=${query}` 
  12.       ).then(rsp => rsp.json()) 
  13.       state.hits.value = data.hits 
  14.     } 
  15.     onMounted(() => { 
  16.       watchEffect(() => { 
  17.         fetchData(state.query.value) 
  18.       }) 
  19.     }) 
  20.     const setQuery = () => { 
  21.       state.query.value = state.input.value 
  22.     } 
  23.     return { 
  24.       ...state, 
  25.       setQuery, 
  26.     } 
  27.   } 

有沒有辦法保持 state 為響應對象,同時又支持其對象解構的呢?當然是有的,Vue 3 也提供了解決方案:toRefs() 。toRefs() 方法可以將一個響應對象變為普通對象,并且給每個屬性加上 ref()。

  1. import { toRefs, reactive, onMounted, watchEffect } from 'vue' 
  2.  
  3. export default { 
  4.   setup() { 
  5.     const state = reactive({ 
  6.       input: 'vue'
  7.       query: 'vue'
  8.       hits: [] 
  9.     }) 
  10.     const fetchData = async (query) => { 
  11.       const data = await fetch
  12.         `https://hn.algolia.com/api/v1/search?query=${query}` 
  13.       ).then(rsp => rsp.json()) 
  14.       state.hits = data.hits 
  15.     } 
  16.     onMounted(() => { 
  17.       watchEffect(() => { 
  18.         fetchData(state.query) 
  19.       }) 
  20.     }) 
  21.     const setQuery = () => { 
  22.       state.query = state.input 
  23.     } 
  24.     return { 
  25.       ...toRefs(state), 
  26.       setQuery, 
  27.     } 
  28.   } 

Loading 與 Error 狀態

通常,我們發起請求的時候,需要為請求添加 Loading 和 Error 狀態,我們只需要在 state中添加兩個變量來控制這兩種狀態即可。

  1. export default { 
  2.   setup() { 
  3.     const state = reactive({ 
  4.       input: 'vue'
  5.       query: 'vue'
  6.       hits: [], 
  7.       error: false
  8.       loading: false
  9.     }) 
  10.     const fetchData = async (query) => { 
  11.       state.error = false 
  12.       state.loading = true 
  13.       try { 
  14.         const data = await fetch
  15.           `https://hn.algolia.com/api/v1/search?query=${query}` 
  16.         ).then(rsp => rsp.json()) 
  17.         state.hits = data.hits 
  18.       } catch { 
  19.         state.error = true 
  20.       } 
  21.       state.loading = false 
  22.     } 
  23.     onMounted(() => { 
  24.       watchEffect(() => { 
  25.         fetchData(state.query) 
  26.       }) 
  27.     }) 
  28.     const setQuery = () => { 
  29.       state.query = state.input 
  30.     } 
  31.     return { 
  32.       ...toRefs(state), 
  33.       setQuery, 
  34.     } 
  35.   } 

同時在模板使用這兩個變量:

  1. <template> 
  2.   <input type="text" v-model="input" /> 
  3.   <button @click="setQuery">搜索</button> 
  4.   <div v-if="loading">Loading ...</div> 
  5.   <div v-else-if="error">Something went wrong ...</div> 
  6.   <ul v-else
  7.     <li 
  8.       v-for="item of hits" 
  9.       :key="item.objectID" 
  10.     > 
  11.       <a :href="item.url">{{item.title}}</a> 
  12.     </li> 
  13.   </ul> 
  14. </template> 

 

展示 Loading、Error 狀態:

 

 


Demo

 

 

將數據請求邏輯抽象

用過 umi 的同學肯定知道 umi 提供了一個叫做 useRequest 的 Hooks,用于請求數據非常的方便,那么我們通過 Vue 的組合 API 也可以抽象出一個類似于 useRequest 的公共方法。

接下來我們新建一個文件 useRequest.js :

  1. import { 
  2.   toRefs, 
  3.   reactive, 
  4. from 'vue' 
  5.  
  6. export default (options) => { 
  7.   const { url } = options 
  8.   const state = reactive({ 
  9.     data: {}, 
  10.     error: false
  11.     loading: false
  12.   }) 
  13.  
  14.   const run = async () => { 
  15.     state.error = false 
  16.     state.loading = true 
  17.     try { 
  18.       const result = await fetch(url).then(res => res.json()) 
  19.       state.data = result 
  20.     } catch(e) { 
  21.       state.error = true 
  22.     } 
  23.     state.loading = false 
  24.   } 
  25.  
  26.   return { 
  27.     run, 
  28.     ...toRefs(state) 
  29.   } 

然后在 App.vue 中引入:

  1. <template> 
  2.   <input type="text" v-model="query" /> 
  3.   <button @click="search">搜索</button> 
  4.   <div v-if="loading">Loading ...</div> 
  5.   <div v-else-if="error">Something went wrong ...</div> 
  6.   <ul v-else
  7.     <li 
  8.       v-for="item of data.hits" 
  9.       :key="item.objectID" 
  10.     > 
  11.       <a :href="item.url">{{item.title}}</a> 
  12.     </li> 
  13.   </ul> 
  14. </template> 
  15.  
  16. <script> 
  17. import { ref, onMounted } from 'vue' 
  18. import useRequest from './useRequest' 
  19.  
  20. export default { 
  21.   setup() { 
  22.     const query = ref('vue'
  23.     const { data, loading, error, run } = useRequest({ 
  24.       url: 'https://hn.algolia.com/api/v1/search' 
  25.     }) 
  26.     onMounted(() => { 
  27.       run() 
  28.     }) 
  29.     return { 
  30.       data, 
  31.       query, 
  32.       error, 
  33.       loading, 
  34.       search: run, 
  35.     } 
  36.   } 
  37. </script> 

 

當前的 useRequest 還有兩個缺陷:

1.傳入的 url 是固定的,query 修改后,不能及時的反應到 url 上;

2.不能自動請求,需要手動調用一下 run 方法;

  1. import { 
  2.   isRef, 
  3.   toRefs, 
  4.   reactive, 
  5.   onMounted, 
  6. from 'vue' 
  7.  
  8. export default (options) => { 
  9.   const { url, manual = false, params = {} } = options 
  10.  
  11.   const state = reactive({ 
  12.     data: {}, 
  13.     error: false
  14.     loading: false
  15.   }) 
  16.  
  17.   const run = async () => { 
  18.     // 拼接查詢參數 
  19.     let query = '' 
  20.     Object.keys(params).forEach(key => { 
  21.       const val = params[key
  22.       // 如果去 ref 對象,需要取 .value 屬性 
  23.       const value = isRef(val) ? val.value : val 
  24.       query += `${key}=${value}&` 
  25.     }) 
  26.     state.error = false 
  27.     state.loading = true 
  28.     try { 
  29.       const result = await fetch(`${url}?${query}`) 
  30.        .then(res => res.json()) 
  31.       state.data = result 
  32.     } catch(e) { 
  33.       state.error = true 
  34.     } 
  35.     state.loading = false 
  36.   } 
  37.  
  38.   onMounted(() => { 
  39.     // 第一次是否需要手動調用 
  40.     !manual && run() 
  41.   }) 
  42.  
  43.   return { 
  44.     run, 
  45.     ...toRefs(state) 
  46.   } 

經過修改后,我們的邏輯就變得異常簡單了。

  1. import useRequest from './useRequest' 
  2.  
  3. export default { 
  4.   setup() { 
  5.     const query = ref('vue'
  6.     const { data, loading, error, run } = useRequest( 
  7.       { 
  8.         url: 'https://hn.algolia.com/api/v1/search'
  9.         params: { 
  10.           query 
  11.         } 
  12.       } 
  13.     ) 
  14.     return { 
  15.       data, 
  16.       query, 
  17.       error, 
  18.       loading, 
  19.       search: run, 
  20.     } 
  21.   } 

當然,這個 useRequest 還有很多可以完善的地方,例如:不支持 http 方法修改、不支持節流防抖、不支持超時時間等等。最后,希望大家看完文章后能有所收獲。

本文轉載自微信公眾號「更了不起的前端」,可以通過以下二維碼關注。轉載本文請聯系更了不起的前端公眾號。

 

責任編輯:武曉燕 來源: 更了不起的前端
相關推薦

2020-10-20 09:51:51

Vue 3 的組合

2021-04-12 05:55:29

緩存數據Axios

2022-06-13 08:39:21

Vue3API

2024-06-20 13:50:53

Vue 3API開發

2022-07-13 10:07:31

vue3組件監聽器

2024-01-12 07:22:49

Vue組合式props

2020-09-19 21:15:26

Composition

2021-03-27 22:21:48

HTTPPython數據

2021-05-19 09:29:52

VueAxios異步請求

2011-04-21 09:59:48

WEBjavascript

2022-03-24 15:28:43

Vue開發框架

2025-03-14 08:01:19

2020-07-22 18:04:00

VueAPI共享

2022-07-08 08:52:25

Vue3組合動態返回

2021-11-30 11:04:52

API網絡技術應用程序

2013-08-20 13:22:35

PythonGo編程語言

2024-12-05 10:53:02

JSON數據服務器

2021-03-30 08:05:39

Vue 3 生命周期Vue2

2019-07-30 11:17:18

系統數據安全

2021-07-29 12:05:18

Vue3Api前端
點贊
收藏

51CTO技術棧公眾號

久久亚洲欧美国产精品乐播| 你懂的视频一区二区| 欧美性猛交丰臀xxxxx网站| 精品乱子伦一区二区三区| 日本黄色一级视频| 亚洲91精品| 日韩精品日韩在线观看| 99热这里只有精品在线播放| 国产传媒在线播放| 99麻豆久久久国产精品免费| 国产精品入口免费视频一| 欧美激情国产精品免费| 午夜精品久久久久久久99老熟妇 | 亚洲精品一区二区久| 蜜桃免费在线视频| 福利影院在线看| 中文字幕一区二区三区在线播放| 欧美激情综合亚洲一二区| 中文字幕一区二区久久人妻网站 | www.亚洲男人天堂| 999这里有精品| 校园春色亚洲| 亚洲免费在线播放| 视频在线99re| 国产精品国产高清国产| 国产一区91精品张津瑜| 国产成人97精品免费看片| 久久婷婷一区二区| 国产成人免费视频网站视频社区| 亚洲国产wwwccc36天堂| 亚洲自拍av在线| 成人a v视频| 伊人精品在线| 欧美大码xxxx| 久久精品色妇熟妇丰满人妻| 日韩欧美美女在线观看| 欧美一区二区三区的| 国产97色在线 | 日韩| 免费污视频在线| 亚洲人成在线播放网站岛国| 91久久久久久久一区二区| 呻吟揉丰满对白91乃国产区| 日韩成人午夜| 精品粉嫩超白一线天av| 国产极品在线视频| 国产理论电影在线| 一区二区三区中文字幕| 人人妻人人澡人人爽精品欧美一区| 伊人成人开心激情综合网| 男的插女的下面视频| av中文字幕在线播放| 中文字幕五月欧美| 51成人做爰www免费看网站| 亚洲一区中文字幕永久在线| 老司机亚洲精品| 日韩美女中文字幕| 狠狠人妻久久久久久综合| 亚洲综合国产激情另类一区| 91chinesevideo永久地址| 欧美不卡视频在线观看| 一本一本久久| 1769国内精品视频在线播放| 国产成人无码精品亚洲| 国产精品美女| 国产精品1234| 一道本无吗一区| 国产乱子伦视频一区二区三区| 国产美女精品免费电影| 国产亲伦免费视频播放| 国产成人av影院| 国产原创精品| 久久精品99北条麻妃| 天堂资源在线中文精品| 国产精品一区二区性色av| 一区二区三区黄| 国产99久久久久| 久久精品magnetxturnbtih| 伦理片一区二区三区| 国产精品人成在线观看免费| 黄色网址在线免费看| 91丝袜在线| 在线免费观看一区| 日本少妇一区二区三区| 亚洲成a人片77777在线播放| 在线不卡国产精品| 欧美精品xxxxx| 午夜亚洲影视| 成人精品网站在线观看| 午夜激情在线视频| 国产日韩欧美综合在线| 九九久久九九久久| 美女一区网站| 欧美日韩精品在线| 8x8x最新地址| youjizz亚洲| 欧美日韩国产乱码电影| 奇米777在线| 亚洲肉体裸体xxxx137| 色老头一区二区三区在线观看| 久久久精品视频免费观看| 国产精品一级| 91日本在线观看| 色在线免费视频| 亚洲欧美欧美一区二区三区| 欧美日韩二三区| 精品一区二区三区四区五区 | 成人一区二区三区仙踪林| gogo亚洲高清大胆美女人体| 91.麻豆视频| 中文字幕丰满乱子伦无码专区| 亚州av乱码久久精品蜜桃| 欧美一区二区三区……| www.黄色国产| 国产精品国产三级国产aⅴ入口 | 成年人午夜视频| 久久精品72免费观看| 国内精品久久久久久久果冻传媒| 欧美三级黄网| 色综合久久久久综合99| 亚洲一级Av无码毛片久久精品| 日韩理论在线| 国产成人激情小视频| 成人免费视频国产免费麻豆| 亚洲欧洲另类国产综合| 成年人小视频网站| 久久亚洲黄色| 欧美福利小视频| 国产影视一区二区| 欧美激情在线看| 精品99在线视频| 女仆av观看一区| 欧美激情精品久久久久久| 国产又粗又黄又爽的视频| 日本一区二区综合亚洲| 99精品在线免费视频| 91麻豆精品国产91久久久久推荐资源| 日韩中文第一页| 亚洲综合成人av| 国产女同互慰高潮91漫画| 无码人妻精品一区二区三区在线| 99精品中文字幕在线不卡| 色婷婷久久av| 在线免费a视频| 国产精品伦一区| 亚洲欧美国产中文| 久久国产电影| 91九色国产社区在线观看| 尤物网在线观看| 欧美日韩亚洲综合一区| 欧美性猛交xxxx乱大交少妇| 色综合天天综合网中文字幕| 国产精品第二页| 国产三级在线看| 欧亚洲嫩模精品一区三区| a级片在线观看| 91精品综合| 91欧美精品午夜性色福利在线| 国产三级在线播放| 欧美一三区三区四区免费在线看 | 97精品一区二区| 亚洲色图18p| 日本欧美一区二区| 精品中文字幕视频| 亚洲国产福利视频| 亚洲高清一区二区三区| 日韩精品一区二区三区高清免费| a91a精品视频在线观看| 蜜桃91精品入口| h1515四虎成人| 成人444kkkk在线观看| 可以免费看av的网址| 美女国产一区二区三区| 亚洲精品偷拍视频| 国产成人精品福利| 欧美专区日韩视频| 国产av一区二区三区精品| 一区二区三区免费观看| 三级a在线观看| 午夜欧美在线| 极品日韩久久| 嫩草伊人久久精品少妇av杨幂| 日韩中文在线不卡| 黄色美女一级片| 色一区在线观看| 黄色香蕉视频在线观看| 成人免费视频视频在线观看免费| 无码人妻丰满熟妇区五十路百度| 这里视频有精品| 日本久久精品视频| 男女啪啪在线观看| 亚洲国产精品高清久久久| 狠狠色综合一区二区| 久久久久久久黄色片| 国产蜜臀av在线一区二区三区| 香蕉视频xxx| 男人的天堂成人在线| 成人精品一二区| 偷拍精品精品一区二区三区| 亚洲国产成人久久综合| 日韩一级片中文字幕| 一区二区三区不卡视频 | 亚洲视频一区在线播放| 亚洲一级电影视频| 东方伊人免费在线观看| 丁香婷婷综合激情五月色| 亚洲一二三区av| 亚洲黄网站黄| 美女在线免费视频| 欧洲杯什么时候开赛| 国产精品麻豆免费版| 精品176极品一区| 欧美中文字幕在线| 欧美性受ⅹ╳╳╳黑人a性爽| 国产性色av一区二区| 国产成人手机在线| 日韩一区二区三区在线视频| 无码人妻丰满熟妇区五十路| 亚洲电影一级黄| 免费成年人视频在线观看| 中文字幕+乱码+中文字幕一区| 四季av综合网站| 国产成人综合在线播放| 亚洲 国产 图片| 丝袜国产日韩另类美女| av之家在线观看| 国内久久精品| xxxxxx在线观看| 小小影院久久| 亚洲一区三区视频在线观看| 精品成av人一区二区三区| 久久er99热精品一区二区三区| 精品欧美午夜寂寞影院| 亚洲综合视频1区| 亚洲三级在线| 成人免费观看a| 偷拍自拍亚洲| 国产又爽又黄的激情精品视频| 午夜不卡视频| 亚洲天堂网站在线观看视频| 亚洲区小说区图片区| 亚洲国产精品久久91精品| 肥臀熟女一区二区三区| 日韩精品一区二区三区在线播放 | 日韩视频免费观看高清在线视频| 亚洲熟妇av乱码在线观看| 欧美亚日韩国产aⅴ精品中极品| 黄瓜视频在线免费观看| 色偷偷成人一区二区三区91 | 天美传媒免费在线观看| 国产免费成人在线视频| 精品成人a区在线观看| 久久久久久国产精品视频| 亚洲九九爱视频| 麻豆一区产品精品蜜桃的特点| 亚洲精品视频在线看| 懂色av懂色av粉嫩av| 一区二区三区免费看视频| 国产在线视频二区| 欧美日韩亚洲91| 91久久国产综合久久91| 欧美日韩亚洲高清一区二区| 91国内精品视频| 日韩免费视频线观看| 色婷婷av一区二区三区之红樱桃 | 国产欧美日韩在线播放| 欧美电影免费网站| 热re99久久精品国产99热| 不卡在线一区| 路边理发店露脸熟妇泻火| 国产综合自拍| 丝袜老师办公室里做好紧好爽| 久久人人97超碰国产公开结果| 国产一级特黄a大片免费| 极品尤物av久久免费看| 老熟女高潮一区二区三区| 久久综合国产精品| 特级西西人体高清大胆| 亚洲女同女同女同女同女同69| 日韩激情一区二区三区| 色综合久久88色综合天天 | 国产精一区二区三区| 天天躁日日躁狠狠躁av麻豆男男| 久久综合久久综合久久| 成人欧美一区二区三区黑人一| 亚洲一区二区三区在线看| 久久精品无码av| 欧美一区二区精美| 日本a一级在线免费播放| 色妞欧美日韩在线| 免费毛片b在线观看| 亚洲一线二线三线视频| 国产精品对白一区二区三区| 欧美aaa级| 国产高清自拍一区| 欧美中文一区二区| 男人添女人荫蒂免费视频| 日韩精品一卡二卡三卡四卡无卡| 午夜免费福利网站| 久久精品人人做人人综合 | 香蕉av福利精品导航| 欧美色视频一区二区三区在线观看| 亚洲精品一二三| 少妇久久久久久久| 精品国产一区二区三区忘忧草| 精品99又大又爽又硬少妇毛片| 美女精品视频一区| 日韩国产网站| 精品国产91亚洲一区二区三区www| 日韩免费一区| 99精品人妻少妇一区二区| 国产精品18久久久久久久久久久久| 精品无人区无码乱码毛片国产 | 国产伦精品一区二区三区视频网站 | 成人高清dvd| 日本欧美在线观看| 无码人妻aⅴ一区二区三区 | 日韩三级一区二区| 精品区一区二区| 久久精品视频观看| 国产成人亚洲综合| 三级精品视频| 天堂8在线天堂资源bt| 精品亚洲成av人在线观看| 欧美多人猛交狂配| 懂色aⅴ精品一区二区三区蜜月| av中文字幕第一页| 日韩在线观看免费av| 成人看片网站| 欧美精品七区| 99国产精品99久久久久久粉嫩| 国产免费无码一区二区| 国产精品国产a| 中文字幕欧美色图| 亚洲日本中文字幕| 日韩电影免费观看高清完整版| 国产美女精品在线观看| 好吊视频一区二区三区四区| 6080国产精品| 亚洲欧美日韩久久精品| 一二三区中文字幕| 日韩在线视频二区| 久久久久黄色| 欧美亚洲视频一区| 久久97超碰色| 日本免费网站视频| 欧美欧美欧美欧美| 国产精品久久麻豆| 91情侣偷在线精品国产| 91精品天堂福利在线观看| 婷婷激情综合五月天| 亚洲日本va在线观看| 国产三级按摩推拿按摩| 久久成人亚洲精品| 99精品国产高清一区二区麻豆| 久久亚洲国产成人精品无码区 | 欧美日韩日日夜夜| sese一区| 欧美黑人巨大xxx极品| 天堂精品久久久久| 国内精品视频一区二区三区| 成年人网站91| 久久精品视频1| 日韩一区二区高清| 蜜乳av一区| 国产日本一区二区三区| 久久国产福利| 一本色道久久88| 日韩一级二级三级精品视频| 精灵使的剑舞无删减版在线观看| 国产在线精品一区二区三区| 久久大逼视频| 娇小11一12╳yⅹ╳毛片| 精品免费日韩av| 忘忧草在线影院两性视频| 亚洲国产午夜伦理片大全在线观看网站| 久久99热国产| 激情视频在线播放| 亚洲乱码一区av黑人高潮| 日本亚洲欧洲无免费码在线| 国产成人亚洲综合无码| 91丨porny丨首页| 久久久久久久久久久久久久免费看| 欧美刺激午夜性久久久久久久| 日韩小视频网站| 紧缚捆绑精品一区二区| 精品小视频在线观看| 亚洲天天在线日亚洲洲精| 国产美女视频一区二区| 国产乱子伦农村叉叉叉| 国产精品久久午夜| 黄色a在线观看| 国产精品网站视频| 亚洲黄色精品| 午夜激情视频在线播放| 亚洲电影第1页| 在线免费成人| www.xxx亚洲| 亚洲成人综合视频| av在线电影播放| 韩国一区二区三区美女美女秀 |