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

Vue 3.0 進階之依賴注入探秘

開發 前端
為了讓大家能夠更深入地理解 provide/inject 特性,阿寶哥從源碼角度分析了 provide 和 inject 函數的具體實現。

 [[384053]]

本文轉載自微信公眾號「全棧修仙之路」,作者阿寶哥。轉載本文請聯系全棧修仙之路公眾號。  

本文是 Vue 3.0 進階系列 的第六篇文章,在這篇文章中,阿寶哥將帶大家一起探索 Vue 3 中的依賴注入功能。

使用過 Angular 的小伙伴對 依賴注入 應該不會陌生,依賴注入簡稱為 DI(Dependency Injection)。組件之間的依賴關系由容器在運行期決定,形象的說,即由容器動態的將某個依賴關系注入到組件之中。依賴注入的目的并非為軟件系統帶來更多功能,而是為了提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。

在 Vue 3.0 中,為我們提供了簡單的依賴注入功能 —— provide/inject。它們解決了以下問題:有一些深度嵌套的組件,而深層的子組件只需要父組件的部分內容。在這種情況下,如果仍然將 prop 沿著組件鏈逐級傳遞下去,這樣使用起來會很麻煩。

為了解決上述問題,Vue 提供了 provide 和 inject。使用 provide/inject 之后,無論組件層次結構有多深,父組件都可以作為其所有子組件的依賴提供者。

(圖片來源 —— https://v3.cn.vuejs.org/guide/component-provide-inject.html)

由上圖可知,在父組件上通過 provide 提供數據,子組件通過 inject 注入數據。介紹完 provide/inject 的作用之后,我們來看一下具體的示例。

一、Provide/Inject 使用示例

在使用 provide/inject 特性時,你可以通過 provide 和 inject 選項的方式來使用它。這種方式官方文檔已經有介紹了,這里阿寶哥將介紹另一種使用方式,即在組合式 API 的 setup 組件選項中,通過 provide 和 inject 函數的方式來實現依賴注入。

  1. <div id="app"></div> 
  2. <script> 
  3.    const { createApp, h, provide, inject } = Vue 
  4.    const app = createApp({ 
  5.      render: () => h(Provider) 
  6.    }) 
  7.     
  8.    const Provider = { 
  9.      setup() { 
  10.        provide('name''阿寶哥'
  11.        return () => h(Middle) 
  12.      } 
  13.    } 
  14.  
  15.    const Middle = { 
  16.      render: () => h(Consumer) 
  17.    } 
  18.  
  19.    const Consumer = { 
  20.      setup() { 
  21.        const name = inject('name'
  22.        return () => `大家好,我是${name}!` 
  23.      } 
  24.    } 
  25.    app.mount('#app')  
  26. </script> 

在以上示例中,在 Provider 組件內通過 provide 函數配置了數據,而在 Consumer 組件中通過 inject 函數獲取 Provider 組件中已配置的數據。需要注意的是,示例中的 Consumer 組件是作為 Provider 組件的孫組件。因此,通過使用 provide/inject 提供的依賴注入功能,我們實現了數據的跨層級傳遞。

介紹完 provide 和 inject 函數的基本使用之后,接下來阿寶哥將帶大家一起來揭開它們背后的秘密。

二、Provide 函數

在分析 provide 函數之前,我們先來回顧一下它的用法:

  1. const Provider = { 
  2.   setup() { 
  3.     provide('name''阿寶哥'
  4.     return () => h(Middle) 
  5.   } 

該函數被定義在 runtime-core/src/apiInject.ts 文件中:

  1. // packages/runtime-core/src/apiInject.ts 
  2. export interface InjectionKey<T> extends Symbol {} 
  3.  
  4. export function provide<T>(key: InjectionKey<T> | string | number, value: T) { 
  5.   if (!currentInstance) { 
  6.     if (__DEV__) { 
  7.       warn(`provide() can only be used inside setup().`) 
  8.     } 
  9.   } else { 
  10.     let provides = currentInstance.provides 
  11.     // 默認情況下,組件實例會繼承于它父組件實例的 provides 對象,當它需要為本身提供 
  12.     // 值是,它將使用父組件的 provides 對象作為原型對象來創建屬于它自己的 provides 
  13.     // 對象。這樣的話,`inject` 函數就可以簡單地從直接父對象中查找需注入的值,并讓原型鏈 
  14.     // 來完成這個工作。 
  15.     const parentProvides = 
  16.       currentInstance.parent && currentInstance.parent.provides 
  17.     if (parentProvides === provides) { 
  18.       provides = currentInstance.provides = Object.create(parentProvides) 
  19.     } 
  20.     // TS 不允許使用 symbol 作為索引類型 
  21.     provides[key as string] = value 
  22.   } 

通過觀察以上的代碼,我們可以得出以下結論:

  • provide 函數只能使用在組合式 API 的 setup 函數中。
  • 組件實例上會有一個 provides 屬性,通過 provide 配置的數據,最終會被保存到組件的 provides 屬性中。
  • provide 函數支持 3 種類型作為 key,即 InjectionKey | string | number,其中 InjectionKey 類型是 Symbol 類型的子類型。

在以上代碼中,我們見到了 currentInstance 對象,那么這個對象內部的結構是怎樣的呢?為了一探究竟,我們在 provide 函數內部加個斷點:

由上圖可知, currentInstance 是一個含有多種屬性的普通對象。其中 bc(BEFORE_CREATE)、bm(BEFORE_MOUNT) 和 bu(BEFORE_UPDATE) 是與生命周期相關的鉤子。那么問題又來了,currentInstance 對象是怎么創建的?看過之前 Vue 3.0 進階系列文章的小伙伴,可能對 createComponentInstance 函數有點印象,該函數的作用就是創建組件實例,具體代碼如下所示:

  1. // packages/runtime-core/src/component.ts 
  2. export function createComponentInstance( 
  3.   vnode: VNode, 
  4.   parent: ComponentInternalInstance | null
  5.   suspense: SuspenseBoundary | null 
  6. ) { 
  7.   const type = vnode.type as ConcreteComponent 
  8.   // inherit parent app context - or - if root, adopt from root vnode 
  9.   const appContext = 
  10.     (parent ? parent.appContext : vnode.appContext) || emptyAppContext 
  11.  
  12.   const instance: ComponentInternalInstance = { 
  13.     uid: uid++, vnode, type, 
  14.     parent, appContext, 
  15.     root: null!, // to be immediately set 
  16.     subTree: null!, // will be set synchronously right after creation 
  17.     updatenull!, // will be set synchronously right after creation 
  18.     render: null, effects: null
  19.     provides: parent ? parent.provides : Object.create(appContext.provides), 
  20.     bc, bm, bu 
  21.     // 省略大部分屬性 
  22.   } 
  23.   // 省略部分代碼 
  24.   instance.root = parent ? parent.root : instance 
  25.   instance.emit = emit.bind(null, instance) 
  26.   return instance 

需要注意的是,如果當前組件 parent 屬性的值不為 null 時,則將使用 parent.provides 的值作為組件實例 provides 屬性的屬性值。介紹完 provide 和 createComponentInstance 函數,為了讓大家能夠更好地理解前面的示例,阿寶哥用一張圖來總結一下示例中組件之間的關系:

對于根組件來說,它的 parent 屬性值為 null。好的,provide 函數就先介紹到這里,下面我們來開始介紹 inject 函數。

三、Inject 函數

同樣,在分析 inject 函數之前,我們也先來回顧一下它的用法:

  1. const Consumer = { 
  2.   setup() { 
  3.     const name = inject('name'
  4.     return () => `大家好,我是${name}!` 
  5.   } 

inject 函數與 provide 函數是互相配合的,它們都被定義在 runtime-core/src/apiInject.ts 文件中:

  1. // packages/runtime-core/src/apiInject.ts 
  2. export function inject( 
  3.   key: InjectionKey<any> | string, 
  4.   defaultValue?: unknown, 
  5.   treatDefaultAsFactory = false 
  6. ) { 
  7.   const instance = currentInstance || currentRenderingInstance // 獲取當前實例 
  8.   if (instance) { 
  9.     // to support `app.use` plugins, 
  10.     // fallback to appContext's `provides` if the intance is at root 
  11.     const provides = 
  12.       instance.parent == null 
  13.         ? instance.vnode.appContext && instance.vnode.appContext.provides 
  14.         : instance.parent.provides 
  15.  
  16.     if (provides && (key as string | symbol) in provides) { 
  17.       // TS doesn't allow symbol as index type 
  18.       return provides[key as string] 
  19.     } else if (arguments.length > 1) { 
  20.       return treatDefaultAsFactory && isFunction(defaultValue) 
  21.         ? defaultValue() 
  22.         : defaultValue 
  23.     } else if (__DEV__) { 
  24.       warn(`injection "${String(key)}" not found.`) 
  25.     } 
  26.   } else if (__DEV__) { 
  27.     warn(`inject() can only be used inside setup() or functional components.`) 
  28.   } 

在 inject 函數中,我們可以清楚地看到如果當前實例的 parent 屬性為 null 時,則會從 appContext 上下文中獲取 provides 對象,否則將從當前實例的父組件實例中獲取 provides 對象。

對于我們的示例來說,在獲取到 provides 對象后,就會判斷 name 屬性是否存在于當前的 provides 對象中,此時該對象是 { name: "阿寶哥"},所以會直接返回 "阿寶哥"。

此外,通過觀察 inject 函數,我們還可以得出以下結論:

  • inject 函數的第二個參數是一個可選參數 —— defaultValue?: unknown,用于設置默認值或默認值工廠。即在 provides 對象上找不到 key 對應值的時候,可以使用默認值或默認值工廠的返回值來代替。
  • inject 函數只能在 setup() 或函數組件中使用。

四、App 對象中的 provide API

在創建完 Vue 3 應用對象之后,我們可以使用該對象提供的 provide 方法。該方法設置一個可以被注入到應用范圍內所有組件中的值。之后,組件就可以使用 inject 來接收 provide 的值。

  1. import { createApp } from 'vue' 
  2.  
  3. const app = createApp({ 
  4.   inject: ['name'], 
  5.   template: ` 
  6.     <div> 
  7.       {{ name }} 
  8.     </div> 
  9.   ` 
  10. }) 
  11.  
  12. app.provide('name''阿寶哥'

需要注意的是,app.provide 方法不應該與 provide 組件選項或組合式 API 中的 provide 方法混淆。雖然它們也是相同的 provide/inject 機制的一部分,但是是用來配置組件 provide 的值而不是應用 provide 的值。

介紹完 app.provide 方法之后,我們來了解一下它的實現。看過 ”Vue 3.0 進階“ 系列教程的小伙伴,對 app 對象應該不會陌生。因為在前面的文章中,阿寶哥已經介紹過 component、directive 和 mount 等方法。接下來,我們來看一下 provide 方法的具體實現:

  1. // packages/runtime-core/src/apiCreateApp.ts 
  2. export function createAppAPI<HostElement>( 
  3.   render: RootRenderFunction, 
  4.   hydrate?: RootHydrateFunction 
  5. ): CreateAppFunction<HostElement> { 
  6.   return function createApp(rootComponent, rootProps = null) { 
  7.     const context = createAppContext() 
  8.  
  9.     // 省略大部分內容 
  10.     const app: App = (context.app = { 
  11.       _uid: uid++, 
  12.       _context: context, 
  13.  
  14.       provide(key, value) { 
  15.         // TypeScript doesn't allow symbols as index type 
  16.         // https://github.com/Microsoft/TypeScript/issues/24587 
  17.         context.provides[key as string] = value 
  18.         return app 
  19.       } 
  20.     }) 
  21.  
  22.     return app 
  23.   } 

由以上代碼可知,在 provide 方法內部會把 key 和 value 以鍵值對的形式保存在應用上下文 context 對象的 provides 屬性中。

  1. // packages/runtime-core/src/apiCreateApp.ts 
  2. export function createAppContext(): AppContext { 
  3.   return { 
  4.     app: null as any
  5.     config: { ... }, 
  6.     mixins: [], 
  7.     components: {}, 
  8.     directives: {}, 
  9.     provides: Object.create(null
  10.   } 

五、阿寶哥有話說

5.1 在嵌套的 providers 場景下,存在同名的 key 會怎么樣?

  1. <div id="app"></div> 
  2. <script> 
  3.    const { createApp, h, provide, inject } = Vue 
  4.    const app = createApp({ 
  5.      render: () => h(ProviderOne) 
  6.    }) 
  7.     
  8.    const ProviderOne = { 
  9.      setup() { 
  10.        provide('foo''foo'
  11.        provide('bar''bar'
  12.        return () => h(ProviderTwo) 
  13.      } 
  14.    } 
  15.  
  16.    const ProviderTwo = { 
  17.      setup() { 
  18.        provide('foo''fooOverride'
  19.        provide('baz''baz'
  20.        return () => h(Consumer) 
  21.       } 
  22.    } 
  23.  
  24.    const Consumer = { 
  25.      setup() { 
  26.        const foo = inject('foo'
  27.        const bar = inject('bar'
  28.        const baz = inject('baz'
  29.        return () => [foo, bar, baz].join(','
  30.      } 
  31.    } 
  32.    app.mount('#app')  
  33. </script> 

在以上代碼中,ProviderOne 和 ProviderTwo 組件中使用同樣的 foo 屬性名配置了 Provider。然后,我們在底層的 Consumer 組件中使用 inject API 分別注入了 ProviderOne 和 ProviderTwo 中配置的值。接下來,我們先來看一下結果:

  1. fooOverride,bar,baz 

由以上結果可知,在嵌套 providers 的場景中,會就近從父組件實例中獲取對應的值,找不到的話,會往上一層層進行查找。

5.2 通過 inject 獲取響應式的值,能否正常工作?

在某些場景下,我們希望往深層的子組件傳遞通過響應式 API 創建的響應式的值,那么通過 inject 函數獲取的響應式的值可以正常工作么?要弄清楚這個問題,我們來看一個具體的示例:

  1. <div id="app"></div> 
  2. <script> 
  3.    const { createApp, h, provide, inject, ref, onMounted } = Vue 
  4.    const nameRef = ref("阿寶哥"); 
  5.    const app = createApp({ 
  6.      setup() { 
  7.        provide("name", nameRef); 
  8.        return () => h(Middle) 
  9.      } 
  10.     }) 
  11.  
  12.    const Middle = { 
  13.      render: () => h(Consumer) 
  14.    } 
  15.  
  16.    const Consumer = { 
  17.      setup() { 
  18.        const name = inject('name'
  19.        onMounted(() => { 
  20.          setTimeout(() => nameRef.value = "kakuqo", 2000); 
  21.        }) 
  22.        return () => `大家好,我是${name.value}!` 
  23.      } 
  24.   } 
  25.   app.mount('#app')  
  26. </script> 

在以上代碼中,我們通過 ref API 創建了一個 nameRef 對象,然后在根組件中通過 provide 函數配置相應的 Provider。而在 Consumer 組件的 setup 方法內,我們通過 inject 函數注入了 nameRef 對象,并通過 name.value 訪問了該對象內保存的值。

此外,在 setup 方法內部,我們還使用了 onMounted 生命周期鉤子,在鉤子對應的回調函數中,我們延遲 2S 修改 nameRef 對象的值。

以上示例成功運行后,首先會先顯示 大家好,我是阿寶哥!,差不多 2S 后頁面會刷新為 大家好,我是kakuqo!。

5.3 是否支持 self-inject?

什么是 self-inject 呢?這里阿寶哥不做過多解釋,我們直接來看個具體的例子:

  1. <div id="app"></div> 
  2. <script> 
  3.    const { createApp, h, provide, inject } = Vue 
  4.    const app = createApp({ 
  5.      render: () => h(Provider) 
  6.    }) 
  7.     
  8.    const Provider = { 
  9.      setup() { 
  10.        provide('name''阿寶哥'
  11.        const injectedName = inject('name'
  12.        return () => h(injectedName) 
  13.      } 
  14.    } 
  15.    app.mount('#app')  
  16. </script> 

在以上代碼中,我們在 Provider 組件的 setup 方法內部先使用 provide 函數配置了相應的 Provider,然后使用 inject 函數來獲取對應的值。很明顯這個操作并沒有實際的意義,那么可以這樣使用么?答案是可以的,以上示例成功運行之后,Provider 組件會被轉換為 注釋節點。

  1. <div id="app" data-v-app=""><!----></div> 

那么為什么會轉為注釋節點呢?因為 injectedName 的值為 undefined,在通過 h 函數創建 VNode 對象的時候,會繼續調用 createVNode 函數,在該函數內部如果發現是 type 類型為 falsy 值時,會把 VNode 對象的類型統一轉換為 Comment 類型。

  1. // packages/runtime-core/src/vnode.ts 
  2. function _createVNode( 
  3.   type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT, 
  4.   props: (Data & VNodeProps) | null = null
  5.   children: unknown = null
  6.   patchFlag: number = 0, 
  7.   dynamicProps: string[] | null = null
  8.   isBlockNode = false 
  9. ): VNode { 
  10.   if (!type || type === NULL_DYNAMIC_COMPONENT) { 
  11.     if (__DEV__ && !type) { 
  12.       warn(`Invalid vnode type when creating vnode: ${type}.`) 
  13.     } 
  14.     type = Comment 
  15.   } 
  16.   // 省略大部分代碼 

本文阿寶哥主要介紹了依賴注入的概念及作用、如何使用 Vue 3 提供的 provide/inject 特性。為了讓大家能夠更深入地理解 provide/inject 特性,阿寶哥從源碼角度分析了 provide 和 inject 函數的具體實現。在后續的文章中,阿寶哥將會介紹在插件中如何應用 provide/inject 特性,感興趣的小伙伴不要錯過喲。

六、參考資源

Vue 3 官網 - Provide/Inject

Vue 3 官網 - 組合式 API

 

責任編輯:武曉燕 來源: 全棧修仙之路
相關推薦

2021-02-26 05:19:20

Vue 3.0 VNode虛擬

2021-02-16 16:41:45

Vue項目指令

2021-02-19 23:07:02

Vue綁定組件

2021-02-22 21:49:33

Vue動態組件

2021-02-18 08:19:21

Vue自定義Vue 3.0

2021-03-04 22:31:02

Vue進階函數

2021-03-09 22:29:46

Vue 響應式API

2021-03-08 00:08:29

Vue應用掛載

2011-03-29 09:51:58

GuiceIOC

2014-01-07 14:53:37

Android開發依賴注入Roboguice

2011-04-15 09:44:45

Spring

2010-05-11 16:22:40

2011-05-31 10:00:21

Android Spring 依賴注入

2023-07-11 09:14:12

Beanquarkus

2017-08-16 16:00:05

PHPcontainer依賴注入

2022-12-29 08:54:53

依賴注入JavaScript

2021-12-15 09:17:12

Spring依賴注入面試題

2020-10-13 08:24:31

Vue3.0系列

2020-04-22 14:15:32

Vue 3.0語法前端

2015-09-02 11:22:36

JavaScript實現思路
點贊
收藏

51CTO技術棧公眾號

在线观看欧美日韩国产| 香蕉加勒比综合久久| 91精品国产综合久久香蕉922| 亚洲二区在线播放| 加勒比久久高清| 日韩欧美在线视频| 在线成人性视频| 亚洲精品一区二区三区蜜桃 | 精品国产乱码久久久久久图片 | 欧美 变态 另类 人妖| 成人国产一区| 亚洲va国产天堂va久久en| 日韩欧美在线电影| 亚洲男人天堂久久| 日韩电影在线免费观看| 九九热r在线视频精品| 欧美熟妇一区二区| 涩涩屋成人免费视频软件| 欧美性xxxx极品高清hd直播| 8x8x华人在线| 国产精品影院在线| 丁香婷婷深情五月亚洲| 国产精品视频一| 国产污片在线观看| 91超碰国产精品| 亚洲女人天堂视频| 国产香蕉精品视频| 另类一区二区三区| 欧美午夜无遮挡| 亚洲乱码日产精品bd在线观看| 蜜桃成人在线视频| 成人免费电影视频| 91香蕉嫩草影院入口| 国产又粗又猛又爽又| 亚洲午夜精品久久久久久app| 精品国产一区二区三区久久狼5月| 在线精品一区二区三区| 91成人午夜| 欧美美女喷水视频| 欧美丰满熟妇xxxxx| aa视频在线观看| 亚洲日本在线天堂| 中文字幕在线亚洲三区| 国产区在线视频| 91丨porny丨在线| 国产乱码精品一区二区三区日韩精品| 国产又黄又猛又爽| 日本欧美韩国一区三区| 日本久久久久久| 欧美一区二区三区四| 激情自拍一区| 欧美激情一区二区三区在线视频观看| 日韩成人毛片视频| 中文字幕一区二区三区乱码图片| 日韩在线观看免费高清| 成人黄色短视频| 日韩综合在线| 日韩在线高清视频| 成人免费视频国产免费观看| 91精品综合久久久久久久久久久 | 在线精品观看国产| 国产一级不卡毛片| 外国电影一区二区| 欧美日韩亚洲综合在线| 中文字幕第38页| 欧美一级做一级爱a做片性| 欧美三级电影在线观看| 中文字幕线观看| 成人污版视频| 日韩精品一区二区三区三区免费| 巨乳女教师的诱惑| 99国产精品免费网站| 欧美精品一区二区久久婷婷| 国产原创剧情av| 奇米777国产一区国产二区| 精品偷拍一区二区三区在线看| 欧美亚一区二区三区| 欧美精品一二| 久久久国产一区二区三区| 久久r这里只有精品| 精品1区2区3区4区| 日本sm极度另类视频| 91丨九色丨海角社区| 九九精品视频在线看| dy888夜精品国产专区| 手机在线精品视频| 国产欧美日韩精品一区| 制服诱惑一区| av资源在线播放| 色婷婷亚洲婷婷| 999这里有精品| av不卡一区| 亚洲欧洲在线播放| 综合五月激情网| 亚洲伦理一区| 国产欧美va欧美va香蕉在| www.久久伊人| 国产亚洲成年网址在线观看| 二级片在线观看| 瑟瑟视频在线看| 欧美日本一区二区三区| 国产伦精品一区二区三区88av| 最新亚洲精品| 久久国产精品久久国产精品| 国产91精品一区| 韩国av一区二区三区四区| 精品国产一区二区三| 最新国产在线观看| 婷婷丁香久久五月婷婷| 加勒比av中文字幕| 岳的好大精品一区二区三区| 久久亚洲国产精品| 四虎影院在线免费播放| 国产成人亚洲综合色影视| 日本10禁啪啪无遮挡免费一区二区 | 日韩激情视频| 国产亚av手机在线观看| 欧美三区在线观看| 日b视频在线观看| 亚洲午夜精品一区二区国产| 热99精品里视频精品| 国产日韩欧美视频在线观看| 国产亚洲欧洲一区高清在线观看| 日韩精品在线观看av| 亚洲影视资源| 亚洲天堂网站在线观看视频| 成年人午夜视频| 国产在线一区观看| 日本一区二区三区四区在线观看| 国产丝袜精品丝袜| 欧美一区二区免费| 开心激情五月网| 日韩主播视频在线| 久久久久成人精品免费播放动漫| 女子免费在线观看视频www| 欧美日韩三级视频| 亚欧精品视频一区二区三区| 老司机精品福利视频| 免费精品视频一区| 僵尸再翻生在线观看| 精品国产污污免费网站入口| 国产精品老熟女一区二区| 激情成人综合网| 五月天综合网| 国产精品一区二区av影院萌芽| 亚洲国产成人精品久久久国产成人一区| 日韩欧美综合视频| 国产精品亚洲专一区二区三区| 亚洲啪啪av| 成人亚洲网站| 色哟哟网站入口亚洲精品| 国内av在线播放| 久久久久国产免费免费| 午夜肉伦伦影院| 私拍精品福利视频在线一区| 97在线观看免费| 亚洲色图21p| 欧美日韩中文字幕在线| 精品人妻互换一区二区三区| 日韩和欧美一区二区| 日韩av电影免费观看| 日本欧美一区| 日韩在线视频免费观看| 91禁在线观看| 亚洲精品伦理在线| 成人做爰www看视频软件| 99热这里只有精品8| 久久久影院一区二区三区 | 婷婷精品进入| 999视频在线观看| 9999在线视频| 亚洲欧美日韩天堂一区二区| 亚洲天堂视频在线播放| 国产精品久久久久永久免费观看| 男生操女生视频在线观看| 一区二区三区四区在线观看国产日韩| 999久久久| 中文字幕在线官网| 视频在线观看99| 精品欧美一区二区精品少妇| 午夜精品国产更新| 日本美女xxx| 国产精品中文字幕日韩精品| 日本一本中文字幕| 精品九九在线| 亚洲最大激情中文字幕| 成人动漫一区| 日日噜噜噜夜夜爽亚洲精品| 性一交一乱一精一晶| 色综合一区二区| 欧美日韩午夜视频| 91玉足脚交白嫩脚丫在线播放| 天天操天天爽天天射| 欧美va天堂| 欧美一区免费视频| 精品国产亚洲日本| 日本欧美黄网站| 黄a在线观看| 日韩精品亚洲视频| 国产欧美一级片| 色哟哟一区二区在线观看| 亚洲视频重口味| 26uuu亚洲| 天堂网成人在线| 视频一区中文字幕| 欧美大黑帍在线播放| 精品视频久久| 国产在线一区二| 国产精品视频一区二区三区| 欧美在线激情视频| 四虎影视成人| 在线日韩av观看| 五月婷婷在线播放| 欧美一区二区视频网站| 91丨九色丨海角社区| 亚洲r级在线视频| 婷婷在线精品视频| 国产欧美日韩亚州综合| 国产白嫩美女无套久久| 国产精品一区二区久久不卡| www亚洲成人| 裸体素人女欧美日韩| 免费观看亚洲视频| 图片区亚洲欧美小说区| 欧美中文娱乐网| 好吊妞视频这里有精品| 91精品视频一区| www.国产精品| 日韩av电影国产| heyzo在线欧美播放| 精品自拍视频在线观看| 九七电影韩国女主播在线观看| 国产午夜精品全部视频在线播放 | 亚洲日本aⅴ片在线观看香蕉| 亚洲精品无遮挡| 日韩欧美色电影| 国产精品国产一区二区三区四区 | 国产白丝袜美女久久久久| 久久久久久久久久久久久久久久久久 | 久久久久久久综合狠狠综合| 尤物网站在线观看| 福利一区福利二区| 亚洲av午夜精品一区二区三区| 国产一区二区视频在线播放| 又色又爽又黄视频| 久久99国内精品| 一个色综合久久| 久久精品国产77777蜜臀| 成人性生生活性生交12| 日本特黄久久久高潮| 国产成人精品无码播放| 香蕉久久久久久久av网站| koreanbj精品视频一区| 亚洲免费影院| 99蜜桃臀久久久欧美精品网站| 久久成人免费| 成人免费xxxxx在线视频| 日韩在线播放一区二区| 黑森林精品导航| 蜜桃视频在线观看一区二区| 激情 小说 亚洲 图片: 伦| 美国av一区二区| 久久久久久久高清| 国产不卡在线视频| 中文字幕一区三区久久女搜查官| 91美女在线视频| 女人十八毛片嫩草av| 中文字幕在线观看一区二区| 欧美特黄一级片| 一区二区三区中文字幕| 日韩和一区二区| 日韩欧美在线看| 在线视频你懂得| 欧美一区二区精品在线| 亚洲精品97久久中文字幕无码| 亚洲国产精品99| 欧美视频综合| 精品国产一区二区三区久久久 | 在线观看免费视频高清游戏推荐| 精品一区二区三区久久久| 久久黄色一级视频| 99视频一区二区| 免费看黄色三级| 亚洲视频一区二区在线| 久久精品性爱视频| 欧洲一区在线电影| 午夜久久久久久久久久| 亚洲美女性视频| 激情影院在线观看| 久久久久久久久91| 粉嫩91精品久久久久久久99蜜桃| 99re国产在线播放| 国产成人3p视频免费观看| 97超碰免费观看| 噜噜噜躁狠狠躁狠狠精品视频 | 高清成人在线| 91丝袜脚交足在线播放| 蜜桃精品噜噜噜成人av| 中文字幕第50页| 久久久久久亚洲精品杨幂换脸| 污污视频网站在线| 26uuu亚洲婷婷狠狠天堂| 欧美黑人一级片| 欧美性生交片4| 热久久免费视频精品| 草草在线观看| 国产日韩视频在线观看| 久久综合社区| 在线精品亚洲一区二区| 亚洲看片一区| 国产资源中文字幕| 日本一区二区三区视频视频| 国产无码精品久久久| 欧美浪妇xxxx高跟鞋交| 牛牛影视精品影视| 午夜精品久久久99热福利| 久久久免费人体| 欧美精品一区二区三区四区五区| 欧美成人中文| 亚洲精品永久视频| 国产亚洲综合av| 日本熟妇色xxxxx日本免费看| 欧美日高清视频| 男人天堂亚洲二区| 97视频在线播放| www.豆豆成人网.com| 亚洲第一综合网站| 麻豆精品一区二区| 白白色免费视频| 色综合天天综合网国产成人综合天| 亚洲精品第五页| 久久国产精品免费视频| 欧美男男gaygay1069| 欧美一区少妇| 六月婷婷一区| www.中文字幕av| 日韩欧美成人网| 三级做a全过程在线观看| 国内精品伊人久久| 极品一区美女高清| 分分操这里只有精品| 国产成人精品亚洲777人妖| 成人免费视频网站入口::| 欧美精品欧美精品系列| 蜜芽在线免费观看| 国产日韩欧美视频| 婷婷综合激情| 91香蕉视频免费看| 一区二区三区日韩| 亚洲国产精品久久久久久6q| 欧美国产日韩中文字幕在线| 日韩免费一级| 国产freexxxx性播放麻豆| 成人一区二区三区在线观看| 国产性生活网站| 欧美日韩岛国| 国产区一区二区| 欧美久久九九| 波多野结衣一二三区| 成人动漫视频| 熟女视频一区二区三区| av一级亚洲| 青青青青在线视频| 成人午夜大片免费观看| 天堂网av手机版| 国产亚洲精品美女久久久| 成人自拍视频网| 日本一级淫片演员| 国产成人在线电影| 欧美日韩精品区| 伊人久久久久久久久久久| 亚洲精品66| 激情五月六月婷婷| 91丨九色丨尤物| 成人黄色片在线观看 | 成人动漫在线免费观看| 国产精品视频一| 欧美日韩亚洲国产精品| 午夜av免费看| 欧美色国产精品| 羞羞视频在线观看不卡| 激情视频一区二区| 日韩av一二三| 九九热精品免费视频| 日韩成人在线观看| 欧美日韩免费电影| 日本欧美精品在线| www香蕉视频| 久久不射热爱视频精品| 老汉色老汉首页av亚洲| 欧美三级理论片| 亚洲综合在线五月| 国产精品久久一区二区三区不卡 | 亚洲成人第一网站| 久久韩国免费视频| 精品人人人人| 中文字幕 91| 五月激情丁香一区二区三区| 自拍视频在线网| 国产精品久久久久久久小唯西川|