久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術文章
文章詳情頁

詳解Vue中的watch和computed

瀏覽:77日期:2022-11-03 15:30:30

前言

對于使用Vue的前端而言,watch、computed和methods三個屬性相信是不陌生的,是日常開發中經常使用的屬性。但是對于它們的區別及使用場景,又是否清楚,本文我將跟大家一起通過源碼來分析這三者的背后實現原理,更進一步地理解它們所代表的含義。 在繼續閱讀本文之前,希望你已經具備了一定的Vue使用經驗,如果想學習Vue相關知識,請移步至官網。

Watch

我們先來找到watch的初始化的代碼,/src/core/instance/state.js

export function initState (vm: Component) { vm._watchers = [] const opts = vm.$options if (opts.props) initProps(vm, opts.props) // 初始化props if (opts.methods) initMethods(vm, opts.methods) // 初始化方法 if (opts.data) { initData(vm) // 先初始化data 重點 } else { observe(vm._data = {}, true /* asRootData */) } if (opts.computed) initComputed(vm, opts.computed) // 初始化computed if (opts.watch && opts.watch !== nativeWatch) { initWatch(vm, opts.watch) // 初始化watch }}

接下來我們深入分析一下initWatch的作用,不過在接下去之前,這里有一點是data的初始化是在computed和watch初始化之前,這是為什么呢?大家可以停在這里想一下這個問題。想不通也沒關系,繼續接下來的源碼分析,這個問題也會迎刃而解。

initWatch

function initWatch (vm: Component, watch: Object) { for (const key in watch) { const handler = watch[key] if (Array.isArray(handler)) { // 如果handler是一個數組 for (let i = 0; i < handler.length; i++) { // 遍歷watch的每一項,執行createWatcher createWatcher(vm, key, handler[i]) } } else { createWatcher(vm, key, handler) } }}

createWatcher

function createWatcher ( vm: Component, expOrFn: string | Function, handler: any, options?: Object) { if (isPlainObject(handler)) { // 判斷handler是否是純對象,對options和handler重新賦值 options = handler handler = handler.handler } if (typeof handler === ’string’) { // handler用的是methods上面的方法,具體用法請查看官網文檔 handler = vm[handler] } // expOrnFn: watch的key值, handler: 回調函數 options: 可選配置 return vm.$watch(expOrFn, handler, options) // 調用原型上的$watch}

Vue.prototype.$watch

Vue.prototype.$watch = function ( expOrFn: string | Function, cb: any, options?: Object ): Function { const vm: Component = this if (isPlainObject(cb)) { // 判斷cb是否是對象,如果是則繼續調用createWatcher return createWatcher(vm, expOrFn, cb, options) } options = options || {} options.user = true // user Watcher的標示 options = { user: true, ...options } const watcher = new Watcher(vm, expOrFn, cb, options) // new Watcher 生成一個user Watcher if (options.immediate) { // 如果傳入了immediate 則直接執行回調cb try { cb.call(vm, watcher.value) } catch (error) { handleError(error, vm, `callback for immediate watcher '${watcher.expression}'`) } } return function unwatchFn () { watcher.teardown() } }}

上面幾個函數調用的邏輯都比較簡單,所以就在代碼上寫了注釋。我們重點關注一下這個userWatcher生成的時候做了什么。

Watcher

又來到了我們比較常見的Watcher類的階段了,這次我們重點關注生成userWatch的過程。

export default class Watcher { vm: Component; expression: string; cb: Function; id: number; deep: boolean; user: boolean; lazy: boolean; sync: boolean; dirty: boolean; active: boolean; deps: Array<Dep>; newDeps: Array<Dep>; depIds: SimpleSet; newDepIds: SimpleSet; before: ?Function; getter: Function; value: any; constructor ( vm: Component, expOrFn: string | Function, cb: Function, options?: ?Object, isRenderWatcher?: boolean ) { this.vm = vm if (isRenderWatcher) { vm._watcher = this } vm._watchers.push(this) // options if (options) { // 在 new UserWatcher的時候傳入了options,并且options.user = true this.deep = !!options.deep this.user = !!options.user this.lazy = !!options.lazy this.sync = !!options.sync this.before = options.before } else { this.deep = this.user = this.lazy = this.sync = false } this.cb = cb this.id = ++uid // uid for batching this.active = true this.dirty = this.lazy // for lazy watchers this.deps = [] this.newDeps = [] this.depIds = new Set() this.newDepIds = new Set() this.expression = process.env.NODE_ENV !== ’production’ // 一個函數表達式 ? expOrFn.toString() : ’’ // parse expression for getter if (typeof expOrFn === ’function’) { this.getter = expOrFn } else { this.getter = parsePath(expOrFn) // 進入這個邏輯,調用parsePath方法,對getter進行賦值 if (!this.getter) { this.getter = noop process.env.NODE_ENV !== ’production’ && warn( `Failed watching path: '${expOrFn}' ` + ’Watcher only accepts simple dot-delimited paths. ’ + ’For full control, use a function instead.’, vm ) } } this.value = this.lazy ? undefined : this.get() }}

首先會對這個watcher的屬性進行一系列的初始化配置,接著判斷expOrFn這個值,對于我們watch的key而言,不是函數所以會執行parsePath函數,該函數定義如下:

/** * Parse simple path. */const bailRE = new RegExp(`[^${unicodeRegExp.source}.$_d]`)export function parsePath (path: string): any { if (bailRE.test(path)) { return } const segments = path.split(’.’) return function (obj) { for (let i = 0; i < segments.length; i++) { // 遍歷數組 if (!obj) return obj = obj[segments[i]] // 每次把當前的key值對應的值重新賦值obj } return obj }}

首先會判斷傳入的path是否符合預期,如果不符合則直接return,接著講path根據’.’字符串進行拆分,因為我們傳入的watch可能有如下幾種形式:

watch: {a: () {} ’formData.a’: () {}}

所以需要對path進行拆分,接下來遍歷拆分后的數組,這里返回的函數的參數obj其實就是vm實例,通過vm[segments[i]],就可以最終找到這個watch所對應的屬性,最后將obj返回。

constructor () { // 初始化的最后一段邏輯this.value = this.lazy // 因為this.lazy為false,所以會執行this.get方法 ? undefined : this.get()} get () { pushTarget(this) // 將當前的watcher實例賦值給 Dep.target let value const vm = this.vm try { value = this.getter.call(vm, vm) // 這里的getter就是上文所講parsePath放回的函數,并將vm實例當做第一個參數傳入 } catch (e) { if (this.user) { handleError(e, vm, `getter for watcher '${this.expression}'`) // 如果報錯了會這這一塊邏輯 } else { throw e } } finally { // 'touch' every property so they are all tracked as // dependencies for deep watching if (this.deep) { // 如果deep為true,則執行深遞歸 traverse(value) } popTarget() // 將當前watch出棧 this.cleanupDeps() // 清空依賴收集 這個過程也是尤為重要的,后續我會單獨寫一篇文章分析。 } return value }

對于UserWatcher的初始化過程,我們基本上就分析完了,traverse函數本質就是一個遞歸函數,邏輯并不復雜,大家可以自行查看。 初始化過程已經分析完,但現在我們好像并不知道watch到底是如何監聽data的數據變化的。其實對于UserWatcher的依賴收集,就發生在watcher.get方法中,通過this.getter(parsePath)函數,我們就訪問了vm實例上的屬性。因為這個時候已經initData,所以會觸發對應屬性的getter函數,這也是為什么initData會放在initWatch和initComputed函數前面。所以當前的UserWatcher就會被存放進對應屬性Dep實例下的subs數組中,如下:

Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value },}

前幾個篇章我們都提到renderWatcher,就是視圖的初始化渲染及更新所用。這個renderWathcer初始化的時機是在我們執行$mount方法的時候,這個時候又會對data上的數據進行了一遍依賴收集,每一個data的key的Dep實例都會將renderWathcer放到自己的subs數組中。如圖:

詳解Vue中的watch和computed

, 當我們對data上的數據進行修改時,就會觸發對應屬性的setter函數,進而觸發dep.notify(),遍歷subs中的每一個watcher,執行watcher.update()函數->watcher.run,renderWathcer的update方法我們就不深究了,不清楚的同學可以參考下我寫的Vue數據驅動。 對于我們分析的UserWatcher而言,相關代碼如下:

class Watcher { constructor () {} //.. run () { if (this.active) { // 用于標示watcher實例有沒有注銷 const value = this.get() // 執行get方法 if ( // 比較新舊值是否相同 value !== this.value || // Deep watchers and watchers on Object/Arrays should fire even // when the value is the same, because the value may // have mutated. isObject(value) || this.deep ) { // set new value const oldValue = this.value this.value = value if (this.user) { // UserWatcher try { this.cb.call(this.vm, value, oldValue) // 執行回調cb,并傳入新值和舊值作為參數 } catch (e) { handleError(e, this.vm, `callback for watcher '${this.expression}'`) } } else { this.cb.call(this.vm, value, oldValue) } } } }}

首先會判斷這個watcher是否已經注銷,如果沒有則執行this.get方法,重新獲取一次新值,接著比較新值和舊值,如果相同則不繼續執行,若不同則執行在初始化時傳入的cb回調函數,這里其實就是handler函數。至此,UserWatcher的工作原理就分析完了。接下來我們來繼續分析ComputedWatcher,同樣的我們找到初始代碼

Computed

initComputed

const computedWatcherOptions = { lazy: true }function initComputed (vm: Component, computed: Object) { // $flow-disable-line const watchers = vm._computedWatchers = Object.create(null) // 用來存放computedWatcher的map // computed properties are just getters during SSR const isSSR = isServerRendering() for (const key in computed) { const userDef = computed[key] const getter = typeof userDef === ’function’ ? userDef : userDef.get if (process.env.NODE_ENV !== ’production’ && getter == null) { warn( `Getter is missing for computed property '${key}'.`, vm ) } if (!isSSR) { // 不是服務端渲染 // create internal watcher for the computed property. watchers[key] = new Watcher( // 執行new Watcher vm, getter || noop, noop, computedWatcherOptions { lazy: true } ) } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. if (!(key in vm)) { // 會在vm的原型上去查找computed對應的key值存不存在,如果不存在則執行defineComputed,存在的話則退出, // 這個地方其實是Vue精心設計的 // 比如說一個組件在好幾個文件中都引用了,如果不將computed defineComputed(vm, key, userDef) } else if (process.env.NODE_ENV !== ’production’) { if (key in vm.$data) { warn(`The computed property '${key}' is already defined in data.`, vm) } else if (vm.$options.props && key in vm.$options.props) { warn(`The computed property '${key}' is already defined as a prop.`, vm) } } }}

defineComputed

new Watcher的邏輯我們先放一邊,我們先關注一下defineComputed這個函數到底做了什么

export function defineComputed ( target: any, key: string, userDef: Object | Function) { const shouldCache = !isServerRendering() if (typeof userDef === ’function’) { // 分支1 sharedPropertyDefinition.get = shouldCache ? createComputedGetter(key) : createGetterInvoker(userDef) sharedPropertyDefinition.set = noop } else { sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : createGetterInvoker(userDef.get) : noop sharedPropertyDefinition.set = userDef.set || noop } if (process.env.NODE_ENV !== ’production’ && sharedPropertyDefinition.set === noop) { sharedPropertyDefinition.set = function () { warn( `Computed property '${key}' was assigned to but it has no setter.`, this ) } } Object.defineProperty(target, key, sharedPropertyDefinition)}

這個函數本質也是調用Object.defineProperty來改寫computed的key值對應的getter函數和setter函數,當訪問到key的時候,就會觸發其對應的getter函數,對于大部分情況下,我們會走到分支1,對于不是服務端渲染而言,sharedPropertyDefinition.get會被createComputedGetter(key)賦值,set會被賦值為一個空函數。

createComputedGetter

function createComputedGetter (key) { return function computedGetter () { const watcher = this._computedWatchers && this._computedWatchers[key] // 就是上文中new Watcher() if (watcher) { if (watcher.dirty) { watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } }}

可以看到createComputedGetter(key)其實會返回一個computedGetter函數,也就是說在執行render函數時,訪問到這個vm[key]對應的computed的時候會觸發getter函數,而這個getter函數就是computedGetter。

<template><div>{{ message }}</div></template>export default {data () { return { a: 1, b: 2 } }, computed: { message () { // 這里的函數名message就是所謂的key return this.a + this.b } }}

以上代碼為例子,來一步步解析computedGetter函數。 首先我們需要先獲取到key對應的watcher.

const watcher = this._computedWatchers && this._computedWatchers[key]

而這里的watcher就是在initComputed函數中所生成的。

if (!isSSR) { // 不是服務端渲染 // create internal watcher for the computed property. watchers[key] = new Watcher( // 執行new Watcher vm, getter || noop, noop, computedWatcherOptions { lazy: true } ) }

我們來看看computedWatcher的初始化過程,我們還是接著來繼續回顧一下Watcher類相關代碼

export default class Watcher { vm: Component; expression: string; cb: Function; id: number; deep: boolean; user: boolean; lazy: boolean; sync: boolean; dirty: boolean; active: boolean; deps: Array<Dep>; newDeps: Array<Dep>; depIds: SimpleSet; newDepIds: SimpleSet; before: ?Function; getter: Function; value: any; constructor ( vm: Component, expOrFn: string | Function, cb: Function, options?: ?Object, isRenderWatcher?: boolean ) { this.vm = vm if (isRenderWatcher) { vm._watcher = this } vm._watchers.push(this) // options if (options) { this.deep = !!options.deep this.user = !!options.user this.lazy = !!options.lazy // lazy = true this.sync = !!options.sync this.before = options.before } else { this.deep = this.user = this.lazy = this.sync = false } this.cb = cb this.id = ++uid // uid for batching this.active = true this.dirty = this.lazy // for lazy watchers this.dirty = true 這里把this.dirty設置為true this.deps = [] this.newDeps = [] this.depIds = new Set() this.newDepIds = new Set() this.expression = process.env.NODE_ENV !== ’production’ ? expOrFn.toString() : ’’ // parse expression for getter if (typeof expOrFn === ’function’) { // 走到這一步 this.getter = expOrFn } else { // .. } this.value = this.lazy // 一開始不執行this.get()函數 直接返回undefined ? undefined : this.get() }

緊接著回到computedGetter函數中,執行剩下的邏輯

if (watcher) { if (watcher.dirty) { watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value}

首先判斷watcher是否存在,如果存在則執行以下操作

判斷watcher.dirty是否為true,如果為true,則執行watcher.evaluate 判斷當前Dep.target是否存在,存在則執行watcher.depend 最后返回watcher.value

在computedWatcher初始化的時候,由于傳入的options.lazy為true,所以相應的watcher.diry也為true,當我們在執行render函數的時候,訪問到message,觸發了computedGetter,所以會執行watcher.evaluate。

evaluate () { this.value = this.get() // 這里的get() 就是vm[’message’] 返回就是this.a + this.b的和 this.dirty = false // 將dirty置為false}

同時這個時候由于訪問vm上的a屬性和b屬性,所以會觸發a和b的getter函數,這樣就會把當前這個computedWatcher加入到了a和b對應的Dpe實例下的subs數組中了。如圖:

詳解Vue中的watch和computed

接著當前的Dep.target毫無疑問就是renderWatcher了,并且也是存在的,所以就執行了watcher.depend()

depend () { let i = this.deps.length while (i--) { this.deps[i].depend() }}

對于當前的message computedWatcher而言,this.deps其實就是a和b兩個屬性對應的Dep實例,接著遍歷整個deps,對每一個dep就進行depend()操作,也就是每一個Dep實例把當前的Dep.target(renderWatcher都加入到各自的subs中,如圖:

詳解Vue中的watch和computed

所以這個時候,一旦你修改了a和b的其中一個值,都會觸發setter函數->dep.notify()->watcher.update,代碼如下:

update () { /* istanbul ignore else */ if (this.lazy) { this.dirty = true } else if (this.sync) { this.run() } else { queueWatcher(this) }}

總結

其實不管是watch還是computed本質上都是通過watcher來實現,只不過它們的依賴收集的時機會有所不同。就使用場景而言,computed多用于一個值依賴于其他響應式數據,而watch主要用于監聽響應式數據,在進行所需的邏輯操作!大家可以通過單步調試的方法,一步步調試,能更好地加深理解。

以上就是詳解Vue中的watch和computed的詳細內容,更多關于Vue watch和computed的資料請關注好吧啦網其它相關文章!

標簽: Vue
相關文章:
主站蜘蛛池模板: 四色成人av永久网址 | 亚洲一区影院 | 免费毛片a线观看 | 亚洲精品国产剧情久久9191 | 国内精品视频一区 | 国产精品成人av | av观看免费| 成人美女免费网站视频 | 久久艹久久 | av超碰| 国产精品视频一区二区三区不卡 | 91久久久久久久久 | 蜜桃视频网站在线观看 | 影视在线观看 | 99精品欧美一区二区三区 | 日韩久久久久久久久久久 | 99看片 | 亚洲欧美中文日韩v在线观看 | 九色网址| 视频一区免费观看 | 国产精品中文字幕在线播放 | 国产精品一区人伦免视频播放 | 亚洲一道本 | 欧美一级全黄 | 国产单男 | 成人片免费看 | 成人免费视频网站在线观看 | 日本一级毛片视频 | 国产v日产∨综合v精品视频 | 中文字幕av一区二区 | 亚洲欧美日韩精品久久奇米色影视 | 九九色九九| 日韩超碰在线观看 | 国产激情在线观看 | 日韩视频在线免费观看 | 一区自拍 | 国产午夜久久 | 亚州中文 | 青青草视频免费观看 | 欧美日韩亚洲国产 | 天天舔天天干天天操 | 羞羞网页| 亚洲一区二区三区四区的 | 日韩国产精品一区二区 | 91视频观看| 国产片淫级awww| 国产日韩欧美精品一区二区三区 | 999久久国产| 91尤物网站网红尤物福利 | www免费网站在线观看 | 98精品国产高清在线xxxx天堂 | 日韩欧美在线一区二区 | 久久麻豆| 91偷拍精品一区二区三区 | 欧美一级做性受免费大片免费 | 欧美成人一区二区三区片免费 | 国产人妖在线 | 在线观看免费黄色 | 成人午夜在线 | 伊人网综合视频 | 久久男人天堂 | 亚洲精品成人免费 | 欧美一级做性受免费大片免费 | 91国产精品入口 | 毛片久久 | 国产一区二区在线免费观看 | 日韩欧美在线一区 | 四虎影院最新地址 | 精品无人乱码一区二区三区 | 日本一区二区精品视频 | 国产小视频在线观看 | 欧美视频网站 | 香蕉大人久久国产成人av | 精品成人av| 日韩精品一91爱爱 | 欧美亚洲国产一区 | 一级黄色片网站 | 国内自拍视频在线观看 | 亚洲精品夜夜夜 | 日本一区二区三区四区 | a∨色狠狠一区二区三区 | 久久久一区二区 | 91亚洲精品乱码久久久久久蜜桃 | 99爱爱视频 | 国产一在线 | 99精品欧美一区二区三区综合在线 | 嫩草研究院在线观看入口 | 视频在线91 | 亚洲精品在线网站 | 欧美成人一区二免费视频软件 | 国产精品成人国产乱一区 | 国产精品福利视频 | 国产精品永久免费自在线观看 | 毛片在线免费 | 国产成人精品综合 | 99免费精品| 99热精品在线 | av一道本| 久久777 | 亚洲一区二区三区高清 | 亚洲一区视频在线播放 | 亚洲狠狠| 在线观看免费黄色小视频 | 色婷婷欧美 | 小情侣高清国产在线播放 | 国产高潮失禁喷水爽网站 | 国产日韩欧美91 | 久久久亚洲一区 | 中文亚洲字幕 | 日韩精品影院 | 欧美精品一区二区三区免费视频 | 国产精品欧美日韩 | 99精品视频免费在线观看 | 国产欧美在线 | 亚洲精品美女久久久 | 91视频免费观看网址 | 久久精品播放 | 亚洲精品字幕 | 亚洲午夜精品a | 日韩快播电影网 | 国产最好的av国产大片 | 欧美视频第一页 | 亚洲三级网站 | 亚洲国产网站 | 精品一区二区三区视频 | 99热首页 | 岛国av一区 | 人人爱超碰 | 日韩成人免费视频 | 麻豆毛片| 天天摸夜夜摸爽爽狠狠婷婷97 | 国产中文字幕一区二区三区 | 亚洲一区中文 | 久久亚洲国产精品日日av夜夜 | 国产精品欧美日韩 | av在线一区二区 | 99国产视频 | 精品国产一区二区三区性色av | 男人亚洲天堂网 | 四虎影院入口 | 天堂一区二区三区 | 久久久久久91亚洲精品中文字幕 | 国产欧美高清在线观看 | 天天操天天插天天干 | 在线日韩欧美 | 91 久久| 曰批免费视频播放免费 | 蜜桃av一区二区三区 | 91精品国产乱码久久久久久久久 | 麻豆乱码国产一区二区三区 | 欧美日韩国产综合视频 | 三级成人在线 | 蜜臀91精品国产高清在线观看 | 欧美日韩在线精品 | 91视频网址 | 日韩视频二区 | 免费观看黄视频 | 欧美成人在线免费视频 | 天堂中文视频在线观看 | 亚洲v日韩v综合v精品v | 亚洲精品一区中文字幕乱码 | 久久久国产一区二区 | 精品视频一区二区 | 日韩极品在线 | 国产精品美女久久久 | 91中文在线 | 亚洲国产精品一区二区三区 | 成人性大片免费观看网站 | 日韩在线精品视频 | 成人av免费观看 | 国产色婷婷精品综合在线播放 | 国产成人午夜精品5599 | 欧洲另类交 | 亚洲成人av在线 | 91成人在线免费视频 | 成人精品国产一区二区4080 | 亚洲精品一区二区 | 欧美日韩午夜 | 亚洲一区二区三区免费在线观看 | 欧美日韩亚洲视频 | 色综合成人 | 欧美日韩精品一区二区 | 99爱在线观看| 99精品视频一区二区三区 | 国产精品久久久久久久久久久久久久 | 日韩午夜电影在线观看 | 久久99国产伦子精品免费 | 国产中文字幕一区 | 亚洲综合色网 | 免费视频久久 | www.涩涩视频| 丁香久久 | 日本一区二区三区中文字幕 | 日韩欧美在线视频 | 在线观看毛片网站 | 米奇成人网 | a一级毛片| 精品永久免费 | 亚洲国产精品一区二区三区 | 欧美日韩成人在线 | 国内精品视频在线观看 | 一区二区精品 | 五月天婷婷丁香 | 久久国内精品 | 欧美精品在线不卡 | 综合久久综合久久 | 亚洲精品一区二区三区中文字幕 | 先锋av资源在线 | 亚洲二区视频 | 色伊人网 | 99热国产在线观看 | 国产精品视频一区二区三区 | 久久青青视频 | 亚洲九九精品 | 中文字幕在线电影观看 | 在线播放91| 久久久极品 | 亚洲毛片在线观看 | 精品少妇一区二区三区 | 精品999| 国产视频一视频二 | a国产在线观看 | 亚洲+变态+欧美+另类+精品 | 国产三区四区 | 二区视频 | 欧美激情精品 | 这里只有精品在线视频观看 | 亚洲永久免费视频 | 色婷婷亚洲 | 五月网婷婷 | 国产乱码精品一区二区三区五月婷 | 特级av| 久久在线播放 | 国产成人av在线播放 | www.麻豆视频 | 日韩三区 | 黄色免费av| 日韩午夜在线 | 91看片在线观看 | 久久国产精品99久久久久久老狼 | 欧美a v在线播放 | 色婷婷综合久久久久中文一区二区 | 欧美精品一区二区三区一线天视频 | 国产三级精品在线 | 欧美二区三区视频 | 九一精品国产 | 天天爽夜夜爽 | 免费国产视频在线观看 | 国产一区二区三区在线 | 成人福利网 | 一区二区三区四区精品 | 久久va| 久久亚洲免费 | 国产精品99| 亚洲xx在线 | 成年人网站免费在线观看 | 一区二区成人 | av最新在线 | 亚洲日本韩国在线观看 | 欧美一级二级三级视频 | 欧美一级网站 | 国产精品久久久久久中文字 | 色久视频 | 久草视频在线观 | 华人黄网站大全 | 久久久久9999国产精品 | 欧美激情精品久久久久久变态 | 黄片毛片一级 | 国产在线网 | 一级视频网站 | 国内久久 | 亚洲欧洲综合av | 黄色毛片在线看 | 免费看的毛片 | 欧美日韩在线观看视频 | 欧美性受 | 亚洲97 | 亚洲一区中文字幕在线观看 | 亚洲人成在线观看 | 亚洲最大av网站 | 婷婷久久综合九色综合绿巨人 | 高清一区二区三区 | 伊人色综合久久天天五月婷 | jlzzjlzz亚洲日本少妇 | 男女啪啪无遮挡 | 欧美午夜精品一区二区三区电影 | 国产一区二区在线播放 | 久久久久国产精品 | 欧美视频精品 | 99精品视频在线免费观看 | 亚洲欧美精品一区 | 国产成人精品免费 | 亚洲视频在线看 | 男人的天堂一级片 | 欧美另类久久 | 国产综合精品一区二区三区 | 91亚洲国产精品 | 91xx在线观看 | 欧美激情在线精品一区二区三区 | 精品国产一区二区三区性色av | 国产欧美精品一区二区 | 国产依人在线 | 欧美中文字幕在线 | 日韩伦理一区二区 | 欧美成人免费网站 | 一区二区三区国产精品 | 狠狠久久伊人中文字幕 | 日本久久精品视频 | 国产欧美一区二区三区在线看 | 日日干日日操 | 欧美一区二区三区 | 精品欧美乱码久久久久久 | av黄色在线 | 在线成人av | 国产精品福利91 | 91精品一区二区三区久久久久久 | 国产日韩欧美在线 | 欧美午夜精品久久久久久浪潮 | www.欧美.com| 97色免费视频 | 天天拍天天草 | 免费在线成人网 | av网战| 国产一级大片 | 91久久国产精品 | 久久这里只有精品首页 | 先锋av资源网 | 国产一区二区三区免费 | 一区二区三区在线免费 | 日日碰碰 | 中文字国产精久久无 | 久久久久高清 | 午夜欧美 | 欧美日韩电影一区二区 | 亚洲成人一区二区三区 | 最新中文字幕在线资源 | 4h影视 | 天天插天天操 | 欧美性www| 日本一区二区不卡 | 国产成人精品午夜 | 亚洲电影一区二区三区 | 亚洲高清视频在线 | 午夜精品久久久久 | 日韩高清国产一区在线 | 久久久国色 | 久久综合久久久 | 亚洲激情在线 | 中文字幕 国产精品 | 亚洲高清视频在线 | 亚洲不卡高清视频 | 自拍一区视频 | 久久国产精品一区二区三区 | 97国产在线视频 | 亚洲视频免费 | 国产在线视频xxx | 性大毛片视频 | 五月激情综合网 | 久久中文网 | 狠狠躁夜夜躁人人爽天天高潮 | 876av国产精品电影 | 亚洲成人精品一区二区三区 | 欧美一区二区三区 | 成人精品在线观看 | 亚洲精品一区在线观看 | 一级片国产 | 欧美自拍视频 | 综合久久国产九一剧情麻豆 | 亚洲综合无码一区二区 | 国产亚洲精品久久久久久青梅 | 99草视频| 91影院在线观看 | 中文字幕乱码一区二区三区 | 成人免费淫片视频观 | 国产精品亚洲欧美日韩一区在线 | 欧美精品在线一区二区三区 | 日韩欧美国产精品综合嫩v 久久久久久国产精品高清 国产目拍亚洲精品99久久精品 | 国产在视频一区二区三区吞精 | 欧美亚洲综合久久 | 一区二区在线视频免费观看 | 欧美视频区 | 91在线最新 | 日韩三区| 国产情侣在线视频 | 99热播在线 | 国产a视频| 久久毛片 | 一区二区不卡视频 | 羞羞视频网站在线看 | 国产精品.xx视频.xxtv | 国产视频一区二区在线观看 | 亚洲一区国产精品 | 91丝袜| 国产最新精品 | 精品久久久久久久久久久久 | 男人的天堂在线视频 | 中文字幕一区二区三 | 精品国产乱码久久久久久久软件 | 欧美在线综合 | 日韩一区在线视频 | 免费av一区二区三区 | 国产视频第一页 | 久久久久久91| 亚洲这里只有精品 | 最新免费av网站 | 狠狠干av | 99久久久国产精品 | 国产亚洲欧美一区二区 | 草久在线观看 | 午夜影视免费观看 | 黄色一级视 | 久久久久久亚洲精品 | 毛片精品| 日韩在线观看中文字幕 | 亚洲一区中文字幕永久在线 | 午夜精品久久久久久久久久久久 | 国产美女自拍视频 | 在线久草 | 成人精品视频99在线观看免费 | 天天干天天搞天天射 | 精品久久ai| 中文字幕一页二页 | 天天澡天天狠天天天做 | 99精品九九 | 伊人久久一区二区三区 | 国产成人免费视频网站高清观看视频 | 日韩成人在线观看 | 黄色高清视频在线观看 | 国产精品一区在线观看 | 91视频网址| 亚洲日本乱码一区两区在线观看 | 在线播放亚洲 | 日韩在线欧美 | 欧美日韩精品一区 | 日韩欧美一区二区三区免费观看 | 在线国产视频 | 欧美高清一区 | 男人的天堂在线视频 | 成人精品福利视频 | 特黄特黄aaaa级毛片免费看 | 久久久久久1 | 精品视频一区二区三区 | 免费成人小视频 | japanhd熟睡侵犯 | 在线视频亚洲 | 国产精品久久久久久二区 | 久久久亚洲精品视频 | 天堂中文在线视频 | 国产一级免费在线 | 午夜精品久久久久久久久久久久久 | 搜索黄色毛片 | 一区二区三区 在线 | 亚洲一区二区三区爽爽爽爽爽 | 欧美激情性国产欧美无遮挡 | 99re国产精品视频 | 日本中文字幕在线播放 | 91在线免费看 | 一级黄色影片在线观看 | 亚洲毛片| 久久天天躁狠狠躁夜夜躁2014 | 国产精品视频播放 | 男人的天堂亚洲 | 国产精品视频不卡 | 超碰在线播| 91精品国产综合久久久久久丝袜 | 国产欧美一区二区 | 精品视频一区二区三区 | 久久免费精品视频 | 伦乱视频 | 综合网日韩 | 亚洲精品久久久久久一区二区 | 一区二区三区精品 | 在线免费观看黄 | 一级片免费在线视频 | 亚洲成人综合在线 | 天天综合天天色 | 国产欧美精品 | 色橹橹欧美在线观看视频高清 | 午夜激情免费看 | 国产色视频网站 | 久久精品日韩 | 亚洲国产成人在线 | 欧美色视频在线观看 | 成年免费观看 | 日韩精品免费视频 | 在线视频久 | 精品国产一区二区三区四区 | 国产高清在线不卡 | 久久综合九色综合欧美狠狠 | 免费视频成人 | 日本不卡高字幕在线2019 | 亚洲aaa在线观看 | 亚洲中午字幕 | 亚洲成人一区二区 | 欧美激情一区二区三区 | 成人一级片| 欧美视频一区 | 国产精品成人在线观看 | 亚洲欧洲精品一区二区三区 | 欧洲毛片 | www.久久精品 | 亚洲欧美视频一区 | 国产日产欧美a级毛片 | 精品一区不卡 | 国产精品成人3p一区二区三区 | 中文字幕久久精品 | 日韩精品一区二区三区在线播放 | 亚洲性爰| 青青草国产成人av片免费 | 国产视频综合在线 | 久草最新 | 亚洲一区二区三区在线播放 | 99草视频 | 国产乱码精品一区二区三区爽爽爽 | 成人三级在线 | 成人在线小视频 | 五月激情综合婷婷 | 日韩欧美二区 | 毛片国产| 有码一区 | 国产成人精品久久二区二区 | 在线观看国产视频 | 91在线电影 | 欧美在线观看一区 | 国产视频精品一区二区三区 | 成年人看的羞羞网站 | 久久porn| 黄瓜av | 一级二级在线观看 | 久久视频一区二区 | a免费在线 | 成视频年人免费看黄网站 | 亚洲一二三区在线观看 | 久久精品无码一区二区日韩av | 日本精a在线观看 | 北条麻妃99精品青青久久 | 在线免费毛片 | av中文字幕在线观看 | 色吊丝2288sds中文字幕 | 国产精品免费看 | 亚洲综合无码一区二区 | 亚洲精品3 | 中文字幕在线免费观看 | 国产高清av在线一区二区三区 | 午夜精品视频在线观看 | 成人在线观看av | 免费精品 | 国产精品成人网 | 亚洲 欧美 另类 综合 偷拍 | 成人免费一区二区三区视频网站 | 欧洲美女7788成人免费视频 | 成人免费视频网站 | 国产精品99久久久久久宅男 | 一区二区三区四区视频 | 互换娇妻呻吟hd中文字幕 | 日本电影www | 美女h视频| 国产一区久久 | 欧美日韩一区二区在线观看 | av 一区二区三区 | 日本三级国产 | 一区二区网站 | 51国产午夜精品免费视频 | 欧美一级艳片视频免费观看 | h片观看 | 欧美二区在线观看 | 欧美日韩中文在线观看 | 成人在线视频免费观看 | 精品成人 | 黄网在线 | 欧美精品一区自拍a毛片在线视频 | 国产亚洲精品精品国产亚洲综合 | 天堂一区 | 亚洲风情在线观看 | 精品亚洲一区二区三区 | 亚洲国产精品t66y | 亚洲精品女人久久 | 精品毛片在线 | 精品国产第一国产综合精品 | 黄色一级毛片在线观看 | 成人欧美在线视频 | 97天堂| 中文字幕在线视频免费播放 | 精品久久久久久久久久久久久久 | 国产传媒毛片精品视频第一次 | 国产成人午夜视频 | 成人亚洲精品 | 国产精品成人在线 | 欧美二区三区 | 99精品久久久久久久免费看蜜月 | 99视频网| 五月香婷婷 | 欧美在线亚洲 | 免费操片 | 97热在线| 99亚洲精品| 国产高清免费视频 | av在线免费观看网站 | 午夜男人免费视频 | 一级黄色影片在线观看 | 亚洲日日操 | 午夜视频大全 | 欧美日本韩国一区二区三区 | 成人 在线| 西西做爰免费视频 | 91久久久久久久久久久久久久久久 | 国产成人精品一区二区在线 | 国产免费av网站 | 免费一级片| 人人爽日日爽 | 日本视频在线 | 免费在线观看毛片网站 | 美女久久 | 国产一区免费视频 | 精品久久一区二区 |