久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網
最全最豐富的資訊網站

詳解vue3中reactive和ref的區別(源碼解析)

vue中reactive和ref的區別是什么?下面本篇文章帶大家深入源碼徹底搞清vue3中reactive和ref的區別,希望對大家有所幫助!

詳解vue3中reactive和ref的區別(源碼解析)

如何快速入門VUE3.0:進入學習

在vue3的日常開發中,我發現很多人都是基于自己的習慣reactiveref一把梭,雖然這樣都可以實現需求,既然這樣那為什么已經有了reactive還需要再去設計一個ref呢?這兩者的實際運用場景以及區別是什么呢?

并且關于ref的底層邏輯,有的人說ref的底層邏輯還是reactive。有的人說ref的底層是classvalue只是這個class的一個屬性,那這兩種說法哪種正確呢?都有沒有依據呢?

抱著這樣的疑問我們本次就深入源碼,徹底搞清vue3中reactiveref的區別。(學習視頻分享:vue視頻教程)

不想看源碼的童鞋,可以直接拉到后面看總結

reactive

源碼地址:packages/reactivity/reactive.ts

首先我們看一下vue3中用來標記目標對象target類型的ReactiveFlags

// 標記目標對象 target 類型的 ReactiveFlags export const enum ReactiveFlags {   SKIP = '__v_skip',   IS_REACTIVE = '__v_isReactive',   IS_READONLY = '__v_isReadonly',   RAW = '__v_raw' }  export interface Target {   [ReactiveFlags.SKIP]?: boolean          // 不做響應式處理的數據   [ReactiveFlags.IS_REACTIVE]?: boolean   // target 是否是響應式   [ReactiveFlags.IS_READONLY]?: boolean   // target 是否是只讀   [ReactiveFlags.RAW]?: any               // 表示proxy 對應的源數據, target 已經是 proxy 對象時會有該屬性 }

reactive

export function reactive<T extends object>(target: T): UnwrapNestedRefs<T> export function reactive(target: object) {   // if trying to observe a readonly proxy, return the readonly version.   // 如果目標對象是一個只讀的響應數據,則直接返回目標對象   if (target && (target as Target)[ReactiveFlags.IS_READONLY]) {     return target   }   // 創建 observe   return createReactiveObject(     target,     false,     mutableHandlers,     mutableCollectionHandlers,     reactiveMap   ) }

reactive函數接收一個target對象,如果target對象只讀則直接返回該對象

若非只讀則直接通過createReactiveObject創建observe對象

createReactiveObject

看著長不要怕,先貼createReactiveObject完整代碼,我們分段閱讀

/**  *   * @param target 目標對象  * @param isReadonly 是否只讀  * @param baseHandlers 基本類型的 handlers  * @param collectionHandlers 主要針對(set、map、weakSet、weakMap)的 handlers  * @param proxyMap  WeakMap數據結構  * @returns   */  function createReactiveObject(   target: Target,   isReadonly: boolean,   baseHandlers: ProxyHandler<any>,   collectionHandlers: ProxyHandler<any>,   proxyMap: WeakMap<Target, any> ) {    // typeof 不是 object 類型的,在開發模式拋出警告,生產環境直接返回目標對象   if (!isObject(target)) {     if (__DEV__) {       console.warn(`value cannot be made reactive: ${String(target)}`)     }     return target   }   // target is already a Proxy, return it.   // exception: calling readonly() on a reactive object   // 已經是響應式的就直接返回(取ReactiveFlags.RAW 屬性會返回true,因為進行reactive的過程中會用weakMap進行保存,   // 通過target能判斷出是否有ReactiveFlags.RAW屬性)   // 例外:對reactive對象進行readonly()   if (     target[ReactiveFlags.RAW] &&     !(isReadonly && target[ReactiveFlags.IS_REACTIVE])   ) {     return target   }   // target already has corresponding Proxy   // 對已經Proxy的,則直接從WeakMap數據結構中取出這個Proxy對象   const existingProxy = proxyMap.get(target)   if (existingProxy) {     return existingProxy   }   // only a whitelist of value types can be observed.   // 只對targetTypeMap類型白名單中的類型進行響應式處理   const targetType = getTargetType(target)   if (targetType === TargetType.INVALID) {     return target   }   // proxy 代理 target   // (set、map、weakSet、weakMap) collectionHandlers   // (Object、Array) baseHandlers   const proxy = new Proxy(     target,     targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers   )   proxyMap.set(target, proxy)   return proxy }

首先我們看到createReactiveObject接收了五個參數

  target: Target,   isReadonly: boolean,   baseHandlers: ProxyHandler<any>,   collectionHandlers: ProxyHandler<any>,   proxyMap: WeakMap<Target, any>

target 目標對象

isReadonly 是否只讀

baseHandlers 基本類型的 handlers 處理數組,對象

collectionHandlers 處理 set、map、weakSet、weakMap

proxyMap WeakMap數據結構存儲副作用函數


這里主要是通過ReactiveFlags.RAWReactiveFlags.IS_REACTIVE判斷是否是響應式數據,若是則直接返回該對象

 if (     target[ReactiveFlags.RAW] &&     !(isReadonly && target[ReactiveFlags.IS_REACTIVE])   ) {     return target   }

對于已經是Proxy的,則直接從WeakMap數據結構中取出這個Proxy對象并返回

  const existingProxy = proxyMap.get(target)   if (existingProxy) {     return existingProxy   }

這里則是校驗了一下當前target的類型是不是ObjectArrayMapSetWeakMapWeakSet,如果都不是則直接返回該對象,不做響應式處理

 // 只對targetTypeMap類型白名單中的類型進行響應式處理   const targetType = getTargetType(target)   if (targetType === TargetType.INVALID) {     return target   }

校驗類型的邏輯

function getTargetType(value: Target) {   return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)     ? TargetType.INVALID     : targetTypeMap(toRawType(value)) }  function targetTypeMap(rawType: string) {   switch (rawType) {     case 'Object':     case 'Array':       return TargetType.COMMON     case 'Map':     case 'Set':     case 'WeakMap':     case 'WeakSet':       return TargetType.COLLECTION     default:       return TargetType.INVALID   } }

所有的前置校驗完后,就可以使用proxy 代理target對象了

這里使用了一個三目運算符通過TargetType.COLLECTION來執行不同的處理邏輯

  • (set、map、weakSet、weakMap) 使用 collectionHandlers
  • (Object、Array) 使用 baseHandlers
// proxy 代理 target   // (set、map、weakSet、weakMap) collectionHandlers   // (Object、Array) baseHandlers   const proxy = new Proxy(     target,     targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers   )   proxyMap.set(target, proxy)   return proxy

現在對createReactiveObject的執行邏輯是不是就很清晰了

到這里還沒有結束,createReactiveObject中最后proxy是如何去代理target的呢?這里我們用baseHandlers舉例,深入baseHandlers的內部去看看

baseHandlers

源碼地址:packages/reactivity/baseHandlers.ts

reactive.ts中我們可以看到一共引入了四種 handler

import {   mutableHandlers,   readonlyHandlers,   shallowReactiveHandlers,   shallowReadonlyHandlers } from './baseHandlers'
  • mutableHandlers 可變處理
  • readonlyHandlers 只讀處理
  • shallowReactiveHandlers 淺觀察處理(只觀察目標對象的第一層屬性)
  • shallowReadonlyHandlers 淺觀察 && 只讀

我們以mutableHandlers為例

// 可變處理 // const get = /*#__PURE__*/ createGetter() // const set = /*#__PURE__*/ createSetter() // get、has、ownKeys 會觸發依賴收集 track() // set、deleteProperty 會觸發更新 trigger() export const mutableHandlers: ProxyHandler<object> = {   get,                  // 用于攔截對象的讀取屬性操作   set,                  // 用于攔截對象的設置屬性操作   deleteProperty,       // 用于攔截對象的刪除屬性操作   has,                  // 檢查一個對象是否擁有某個屬性   ownKeys               // 針對 getOwnPropertyNames,  getOwnPropertySymbols, keys 的代理方法 }

這里的getset分別對應著createGetter()createSetter()

  • createGetter()

先上完整版代碼

/**  * 用于攔截對象的讀取屬性操作  * @param isReadonly 是否只讀  * @param shallow 是否淺觀察  * @returns   */ function createGetter(isReadonly = false, shallow = false) {   /**    * @param target 目標對象    * @param key 需要獲取的值的鍵值    * @param receiver 如果遇到 setter,receiver 則為setter調用時的this值    */   return function get(target: Target, key: string | symbol, receiver: object) {     // ReactiveFlags 是在reactive中聲明的枚舉值,如果key是枚舉值則直接返回對應的布爾值     if (key === ReactiveFlags.IS_REACTIVE) {       return !isReadonly     } else if (key === ReactiveFlags.IS_READONLY) {       return isReadonly     } else if (       // 如果key是raw  receiver 指向調用者,則直接返回目標對象。       // 這里判斷是為了保證觸發攔截 handle 的是 proxy 本身而不是 proxy 的繼承者       // 觸發攔的兩種方式:一是訪問 proxy 對象本身的屬性,二是訪問對象原型鏈上有 proxy 對象的對象的屬性,因為查詢會沿著原型鏈向下找       key === ReactiveFlags.RAW &&       receiver ===         (isReadonly           ? shallow             ? shallowReadonlyMap             : readonlyMap           : shallow           ? shallowReactiveMap           : reactiveMap         ).get(target)     ) {       return target     }      const targetIsArray = isArray(target)     // 如果目標對象 不為只讀、是數組、key屬于arrayInstrumentations:['includes', 'indexOf', 'lastIndexOf']方法之一,即觸發了這三個方法之一     if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {       // 通過 proxy 調用,arrayInstrumentations[key]的this一定指向 proxy       return Reflect.get(arrayInstrumentations, key, receiver)     }      const res = Reflect.get(target, key, receiver)      // 如果 key 是 symbol 內置方法,或者訪問的是原型對象__proto__,直接返回結果,不收集依賴     if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {       return res     }      // 不是只讀類型的 target 就收集依賴。因為只讀類型不會變化,無法觸發 setter,也就會觸發更新     if (!isReadonly) {       track(target, TrackOpTypes.GET, key)     }      // 如果是淺觀察,不做遞歸轉化,就是說對象有屬性值還是對象的話不遞歸調用 reactive()     if (shallow) {       return res     }      // 如果get的結果是ref     if (isRef(res)) {       // ref unwrapping - does not apply for Array + integer key.       // 返回 ref.value,數組除外       const shouldUnwrap = !targetIsArray || !isIntegerKey(key)       return shouldUnwrap ? res.value : res     }      // 由于 proxy 只能代理一層,如果子元素是對象,需要遞歸繼續代理     if (isObject(res)) {       // Convert returned value into a proxy as well. we do the isObject check       // here to avoid invalid value warning. Also need to lazy access readonly       // and reactive here to avoid circular dependency.       return isReadonly ? readonly(res) : reactive(res)     }      return res   } }

看著長,最終就是track()依賴收集

track()依賴收集內容過多,和trigger()觸發更新一起,單開一篇文章

  • createSetter()

/**  * 攔截對象的設置屬性操作  * @param shallow 是否是淺觀察  * @returns   */ function createSetter(shallow = false) {   /**    * @param target 目標對象    * @param key 設置的屬性名稱    * @param value 要改變的屬性值    * @param receiver 如果遇到setter,receiver則為setter調用時的this值    */   return function set(     target: object,     key: string | symbol,     value: unknown,     receiver: object   ): boolean {     let oldValue = (target as any)[key]     // 如果模式不是淺觀察模式     if (!shallow) {       // 拿新值和老值的原始值,因為新傳入的值可能是響應式數據,如果直接和 target 上原始值比較是沒有意義的       value = toRaw(value)       oldValue = toRaw(oldValue)       // 目標對象不是數組,舊值是ref,新值不是ref,則直接賦值,這里提到ref       if (!isArray(target) && isRef(oldValue) && !isRef(value)) {         oldValue.value = value         return true       }     } else {       // in shallow mode, objects are set as-is regardless of reactive or not     }     // 檢查對象是否有這個屬性     const hadKey =       isArray(target) && isIntegerKey(key)         ? Number(key) < target.length         : hasOwn(target, key)     // 賦值         const result = Reflect.set(target, key, value, receiver)     // don't trigger if target is something up in the prototype chain of original     // reactive是proxy實例才觸發更新,防止通過原型鏈觸發攔截器觸發更新     if (target === toRaw(receiver)) {       if (!hadKey) {         // 如果不存在則trigger ADD         trigger(target, TriggerOpTypes.ADD, key, value)       } else if (hasChanged(value, oldValue)) {         // 如果新舊值不相等則trigger SET         trigger(target, TriggerOpTypes.SET, key, value, oldValue)       }     }     return result   } }

trigger()觸發更新

ref

源碼地址:packages/reactivity/src/ref.ts

接收一個可選unknown,接著直接調用createRef()

export function ref(value?: unknown) {   return createRef(value, false) }

詳解vue3中reactive和ref的區別(源碼解析)

ref的區別就是在調用createRef()時第二個值傳的是true

export function shallowRef(value?: unknown) {   return createRef(value, true) }

看一下官方文檔上對shallowRef的解釋

詳解vue3中reactive和ref的區別(源碼解析)

createRef

通過isRef()判斷是否是ref數據,是則直接返回該數據,不是則通過new RefImpl創建ref數據

在創建時會傳兩個值一個是rawValue(原始值),一個是shallow(是否是淺觀察),具體使用場景可看上面refshallowRef的介紹

function createRef(rawValue: unknown, shallow: boolean) {   // 是否是 ref 數據   if (isRef(rawValue)) {     return rawValue   }   return new RefImpl(rawValue, shallow) }
  • isRef()

通過__v_isRef只讀屬性判斷是否是ref數據,此屬性會在RefImpl創建ref數據時添加

export function isRef(r: any): r is Ref {   return Boolean(r && r.__v_isRef === true) }

RefImpl

class RefImpl<T> {   private _value: T   private _rawValue: T    public dep?: Dep = undefined   // 只讀屬性 __v_isRef 判斷是否是ref數據的靜態標識   public readonly __v_isRef = true    constructor(value: T, public readonly _shallow: boolean) {     this._rawValue = _shallow ? value : toRaw(value)  // 非淺觀察用toRaw()包裹原始值     this._value = _shallow ? value : toReactive(value) // 非淺觀察用toReactive()處理數據   }    get value() {   // 依賴收集     trackRefValue(this)     return this._value   }    set value(newVal) {     newVal = this._shallow ? newVal : toRaw(newVal) // 非淺觀察用toRaw()包裹值     // 兩個值不相等     if (hasChanged(newVal, this._rawValue)) {       this._rawValue = newVal       this._value = this._shallow ? newVal : toReactive(newVal)       triggerRefValue(this, newVal) // 觸發依賴,派發更新     }   } }

根據RefImpl我們可以看到ref的底層邏輯,如果是對象確實會使用reactive進行處理,并且ref的創建使用的也是RefImpl class實例,value只是RefImpl的屬性

在我們訪問設置 ref的value值時,也分別是通過getset攔截進行依賴收集派發更新

  • toReactive

我們來看一下toReactive()這個方法,在RefImpl中創建ref數據時會調用toReactive()方法,這里會先判斷傳進來的值是不是對象,如果是就用reactive()包裹,否則就返回其本身

export const toReactive = <T extends unknown>(value: T): T =>   isObject(value) ? reactive(value) : value
  • trackRefValue

ref的依賴收集方法

export function trackRefValue(ref: RefBase<any>) {   if (isTracking()) {     ref = toRaw(ref)     if (!ref.dep) {       ref.dep = createDep()     }     if (__DEV__) {       trackEffects(ref.dep, {         target: ref,         type: TrackOpTypes.GET,         key: 'value'       })     } else {       trackEffects(ref.dep)     }   } }
  • triggerRefValue

ref的派發更新方法

export function triggerRefValue(ref: RefBase<any>, newVal?: any) {   ref = toRaw(ref)   if (ref.dep) {     if (__DEV__) {       triggerEffects(ref.dep, {         target: ref,         type: TriggerOpTypes.SET,         key: 'value',         newValue: newVal       })     } else {       triggerEffects(ref.dep)     }   } }

總結

看完reactiveref源碼,相信對本文一開始的幾個問題也都有了答案,這里也總結了幾個問題:

  • 問:ref的底層邏輯是什么,具體是如何實現的

答:ref底層會通過 new RefImpl()來創造ref數據,在new RefImpl()會首先給數據添加__v_isRef只讀屬性用來標識ref數據。而后判斷傳入的值是否是對象,如果是對象則使用toReactive()處理成reactive,并將值賦給RefImpl()value屬性上。在訪問設置ref數據的value時會分別觸發依賴收集派發更新流程。


  • 問:ref底層是否會使用reactive處理數據

答:RefImpl中非淺觀察會調用toReactive()方法處理數據,toReactive()中會先判斷傳入的值是不是一個對象,如果是對象則使用reactive進行處理,不是則直接返回值本身。


  • 問:為什么已經有了reactive還需要在設計一個ref呢?

答: 因為vue3響應式方案使用的是proxy,而proxy的代理目標必須是非原始值,沒有任何方式能去攔截對原始值的操作,所以就需要一層對象作為包裹,間接實現原始值的響應式方案。


  • 問:為什么ref數據必須要有個value屬性,訪問ref數據必須要通過.value的方式呢?

答:這是因為要解決響應式丟失的問題,舉個例子:

// obj是響應式數據 const obj = reactive({ foo: 1, bar: 2 })  // newObj 對象下具有與 obj對象同名的屬性,并且每個屬性值都是一個對象 // 該對象具有一個訪問器屬性 value,當讀取 value的值時,其實讀取的是 obj 對象下相應的屬性值  const newObj = {     foo: {         get value() {             return obj.foo         }     },     bar: {         get value() {             return obj.bar         }     } }  effect(() => {     // 在副作用函數內通過新對象 newObj 讀取 foo 的屬性值     console.log(newObj.foo) }) // 正常觸發響應 obj.foo = 100

可以看到,在現在的newObj對象下,具有與obj對象同名的屬性,而且每個屬性的值都是一個對象,例如foo 屬性的值是:

{     get value() {         return obj.foo     } }

該對象有一個訪問器屬性value,當讀取value的值時,最終讀取的是響應式數據obj下的同名屬性值。也就是說,當在副作用函數內讀取newObj.foo時,等價于間接讀取了obj.foo的值。這樣響應式數據就能夠與副作用函數建立響應聯系

(學習視頻分享:web前端開發、編程基礎視頻)

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
在线亚洲免费| 国产精品宾馆| 日韩国产一区二区| 日本蜜桃在线观看视频| 久久久久久免费视频| 久久国产欧美| 五月婷婷六月综合| 亚洲综合福利| 欧美在线不卡| 精品国产欧美| 中文字幕在线看片| 欧美搞黄网站| 蜜桃tv一区二区三区| 亚洲欧美日韩国产| 国产日韩中文在线中文字幕| 精品国产欧美日韩| 99久久久国产精品美女| 黄色亚洲在线| 欧美一区=区三区| 成人美女视频| 丝袜美腿成人在线| 国产美女撒尿一区二区| 日韩国产欧美| 亚洲有吗中文字幕| 精品美女视频| 国产精品日韩欧美一区| 国产精品一二| 日韩亚洲一区在线| 一本综合精品| 成人福利视频| 日韩中文字幕一区二区高清99| 欧美aa在线视频| 亚洲成人精品| 91成人精品在线| 蜜桃精品在线| 91精品丝袜国产高跟在线| bbw在线视频| 亚洲深深色噜噜狠狠爱网站| 美女精品视频在线| 黄色亚洲免费| 久久精品国产免费| 日韩在线观看一区二区| 国产精品久av福利在线观看| 国产99久久| 国产精品中文字幕制服诱惑| jiujiure精品视频播放| 国产精品毛片aⅴ一区二区三区| 久久亚洲专区| 国产日本精品| 午夜在线精品| 中文字幕在线官网| 国产欧美久久一区二区三区| 亚洲精品一区二区在线看| 老司机精品在线| 亚洲精品在线二区| 狠狠干成人综合网| 成人精品视频| 三级久久三级久久久| 欧美日韩一二三四| 久久一区精品| 日韩 欧美一区二区三区| 精品一区免费| 日本不卡免费高清视频在线| 免费看久久久| 日韩av在线播放中文字幕| 午夜精品网站| 日韩中文在线电影| 久久精品免视看国产成人| 亚洲精品自拍| 亚洲视频www| 国产精品99一区二区| 色婷婷综合网| 麻豆传媒一区二区三区| 日韩精品中文字幕吗一区二区 | 偷拍欧美精品| 久久精品免费一区二区三区| 久久伊人国产| 国产精品视频一区二区三区| 亚洲综合婷婷| 中文字幕一区二区精品区| 欧美日韩国产免费观看视频| 日韩欧美一区二区三区在线视频 | 美女av在线免费看| 国产欧美三级| 欧美精品国产白浆久久久久| 一区二区国产在线观看| 水蜜桃久久夜色精品一区的特点| 欧美肉体xxxx裸体137大胆| 日韩欧美看国产| 国产一区二区三区免费在线| 欧美视频久久| 日韩av中文在线观看| 青青草精品视频| 久久激情av| 国产精品羞羞答答在线观看| 四虎在线精品| 欧美日韩一区自拍| 国产精品视频一区二区三区四蜜臂 | 日韩国产欧美| 99久久久久久中文字幕一区| 久久精品国产99久久| 久久中文亚洲字幕| 一本色道久久精品| 久久一二三区| 日韩二区三区在线观看| 欧美日韩一区二区三区在线电影| 国产一精品一av一免费爽爽| 国产精品黄色| 精品国产亚洲一区二区三区大结局| 国产黄色精品| 国产中文字幕一区二区三区| 日韩欧美看国产| 国产精品丝袜xxxxxxx| 蜜臀a∨国产成人精品| 欧美综合社区国产| 国产成人精品一区二区三区视频 | 欧美成人综合| 中文字幕一区二区三区四区久久| 日韩av不卡在线观看| 欧美a在线观看| 色网在线免费观看| 亚洲高清二区| 日韩精品一级中文字幕精品视频免费观看 | 最近高清中文在线字幕在线观看1| 欧美少妇精品| 亚洲一区日韩| 男人的天堂久久精品| 国产日韩中文在线中文字幕| 丰满少妇一区| 国产精品88久久久久久| 日本亚洲欧美天堂免费| 久久精品三级| 在线视频精品| 国产精品一区二区三区av| 日韩三区免费| 中文字幕日韩亚洲| 麻豆视频一区二区| 欧美日韩激情| 欧美日韩一区自拍| 99久精品视频在线观看视频| 亚洲人成高清| 成人在线视频中文字幕| 黑丝一区二区| 精品一级视频| 视频一区二区三区入口| 国产成人精品三级高清久久91| 99综合视频| 欧美aaaaaa午夜精品| 一区二区自拍| 国产精品成人3p一区二区三区| 肉色欧美久久久久久久免费看| 一区二区三区国产在线| a日韩av网址| 亚洲性视频在线| 国产一二在线播放| 日本精品一区二区三区在线观看视频| 国产乱码午夜在线视频| 婷婷成人av| 久久一区二区三区喷水| 欧美极品中文字幕| 蜜桃久久精品一区二区| 亚洲最新无码中文字幕久久 | 波多野结衣一区| 免费在线亚洲欧美| 日韩午夜精品| 久久这里只有| 亚洲视频国产精品| 欧美影院三区| 另类综合日韩欧美亚洲| 蜜桃久久精品一区二区| 蜜桃精品在线| 精品午夜视频| 日本国产一区| 性一交一乱一区二区洋洋av| 97欧美在线视频| 欧美日韩一区二区三区在线电影| 99riav国产精品| 日韩av福利| 久久影院资源站| 日本不卡中文字幕| 欧美日韩第一| 色偷偷色偷偷色偷偷在线视频| 国产免费av一区二区三区| 亚洲青青久久| 美女日韩在线中文字幕| 欧美性感美女一区二区| 波多野结衣久久精品| 精品国产亚洲日本| 国产伦精品一区二区三区千人斩 | 日韩欧美久久| 亚洲日本久久| 欧美日韩国产高清| 精品精品99| 久久福利在线| 国产精品久久久久久久久久久久久久久 | 日韩高清不卡一区| 亚洲精品看片| 无码日韩精品一区二区免费| 蜜桃视频在线观看一区| 在线综合亚洲|