国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

發(fā)布訂閱模式這個面試題該咋答

共 24387字,需瀏覽 49分鐘

 ·

2023-08-16 20:42

本文來自 @simonezhou 小姐姐投稿的第八期筆記。面試官常問發(fā)布訂閱、觀察者模式,我們?nèi)粘i_發(fā)也很常用。文章講述了 mitt、tiny-emitter、Vue eventBus這三個發(fā)布訂閱、觀察者模式相關(guān)的源碼。

源碼地址

  1. mitt:https://github.com/developit/mitt
  2. tiny-emitter:https://github.com/scottcorgan/tiny-emitter

1. mitt 源碼解讀

1.1 package.json 項(xiàng)目 build 打包(運(yùn)用到包暫不深究,保留個印象即可)

執(zhí)行 npm run build:

// 
"scripts": {
    ...
    "bundle""microbundle -f es,cjs,umd",
    "build""npm-run-all --silent clean -p bundle -s docs",
    "clean""rimraf dist",
    "docs""documentation readme src/index.ts --section API -q --parse-extension ts",
   ...
 },
  • 使用 npm-run-all(A CLI tool to run multiple npm-scripts in parallel or sequential:https://www.npmjs.com/package/npm-run-all) 命令執(zhí)行
  • clean 命令,使用 rimraf(The UNIX command rm -rf for node. https://www.npmjs.com/package/rimraf)刪除 dist 文件路徑
  • bundle 命令,使用 microbundle(The zero-configuration bundler for tiny modules, powered by Rollup. https://www.npmjs.com/package/microbundle) 進(jìn)行打包
  • microbundle 命令指定 format: es, cjs, umd,  package.json 指定 soucre 字段為打包入口 js:

{
 "name""mitt",          // package name
  ...
  ...
  "module""dist/mitt.mjs",    // ES Modules output bundle
  "main""dist/mitt.js",      // CommonJS output bundle
  "jsnext:main""dist/mitt.mjs",   // ES Modules output bundle
  "umd:main""dist/mitt.umd.js",  // UMD output bundle
  "source""src/index.ts",     // input
  "typings""index.d.ts",     // TypeScript typings directory
  "exports": {
    "import""./dist/mitt.mjs",    // ES Modules output bundle
    "require""./dist/mitt.js",  // CommonJS output bundle
    "default""./dist/mitt.mjs"  // Modern ES Modules output bundle
  },
  ...
}

1.2 如何調(diào)試查看分析?

使用 microbundle watch 命令,新增 script,執(zhí)行 npm run dev:

"dev""microbundle watch -f es,cjs,umd"

對應(yīng)目錄新增入口,比如 test.js,執(zhí)行 node test.js 測試功能:

const mitt = require('./dist/mitt');

const Emitter = mitt();

Emitter.on('test', (e, t) => console.log(e, t));

Emitter.emit('test', { a12321 });

對應(yīng)源碼 src/index.js 也依然可以加相關(guān)的 log 進(jìn)行查看,代碼變動后會觸發(fā)重新打包

1.3. TS 聲明

使用上可以(官方給的例子),比如定義 foo 事件,回調(diào)函數(shù)里面的參數(shù)要求是 string 類型,可以想象一下源碼 TS 是怎么定義的:

import mitt from 'mitt';

// key 為事件名,key 對應(yīng)屬性為回調(diào)函數(shù)的參數(shù)類型 
type Events = {
  foo: string;
  bar?: number; // 對應(yīng)事件允許不傳參數(shù)
};

const emitter = mitt<Events>(); // inferred as Emitter<Events>

emitter.on('foo', (e) => {}); // 'e' has inferred type 'string'

emitter.emit('foo'42); // Error: Argument of type 'number' is not assignable to parameter of type 'string'. (2345)

emitter.on('*', (type, e) => console.log(type, e) )

源碼內(nèi)關(guān)于 TS 定義(關(guān)鍵幾句):

export type EventType = string | symbol;

// Handler 為事件(除了*事件)回調(diào)函數(shù)定義
export type Handler<T = unknown> = (event: T) => void;

// WildcardHandler 為事件 * 回調(diào)函數(shù)定義
export type WildcardHandler<T = Record<string, unknown>> = (
 type: keyof T,   // keyof T,事件名
 event: T[keyof T]  // T[keyof T], 事件名對應(yīng)的回調(diào)函數(shù)入?yún)㈩愋?/span>
) => void;


export interface Emitter<Events extends Record<EventType, unknown>> {
 // ...

 on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
 on(type: '*'handler: WildcardHandler<Events>): void;

 // ...
 emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
  // 這句主要兼容無參數(shù)類型的事件,如果說事件對應(yīng)回調(diào)必須傳參,使用中如果未傳,那么會命中 never,如下圖
 emit<Key extends keyof Events>(type: undefined extends Events[Key] ? Key : never): void;
}

以下是會報(bào) TS 錯誤:

以下是正確的:

1.4 主邏輯


  1. 整體就是一個 function,輸入為事件 Map,輸出為 all 所有事件 Map,還有 on,emit,off 幾個關(guān)于事件方法:
export default function mitt<Events extends Record<EventTypeunknown>>(
  // 支持 all 初始化
 all?: EventHandlerMap<Events>
): Emitter<Events
{
  // 內(nèi)部維護(hù)了一個 Map(all),Key 為事件名,Value 為 Handler 回調(diào)函數(shù)數(shù)組
  all = all || new Map();
  return {
   all,   // 所有事件 & 事件對應(yīng)方法
   emit,  // 觸發(fā)事件
   on,   // 訂閱事件
   off   // 注銷事件
  }
}
  1. on 為【事件訂閱】,push 對應(yīng) Handler 到對應(yīng)事件 Map 的 Handler 回調(diào)函數(shù)數(shù)組內(nèi)(可熟悉下 Map 相關(guān)API https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map):
on<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {
  // Map get 獲取
 const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
  // 如果已經(jīng)初始化過的話,是個數(shù)組,直接 push 即可
 if (handlers) {
  handlers.push(handler);
 }
  // 如果第一次注冊事件,則 set 新的數(shù)組
 else {
  all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);
 }
}
  1. off 為【事件注銷】,從對應(yīng)事件 Map 的 Handlers 中,splice 掉:
off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {
  // Map get 獲取
 const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
  // 如果有事件列表,則進(jìn)入,沒有則忽略
 if (handlers) {
    // 對 handler 事件進(jìn)行 splice 移出數(shù)組
    // 這里是對找到的第一個 handler 進(jìn)行移出,所以如果訂閱了多次,只會去除第一個
    // handlers.indexOf(handler) >>> 0,>>> 為無符號位移
    // 關(guān)于網(wǎng)上對 >>> 用法說明:It doesn't just convert non-Numbers to Number, it converts them to Numbers that can be expressed as 32-bit unsigned ints.
  if (handler) {
   handlers.splice(handlers.indexOf(handler) >>> 01);
  }
    // 如果不傳對應(yīng)的 Handler,則為清空事件對應(yīng)的所有訂閱
  else {
   all!.set(type, []);
  }
 }
}
  1. emit 為【事件觸發(fā)】,讀取事件 Map 的 Handlers,循環(huán)逐一觸發(fā),如果訂閱了 * 全事件,則讀取 * 的 Handlers 逐一觸發(fā):
emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
  // 獲取對應(yīng) type 的 Handlers
 let handlers = all!.get(type);
 if (handlers) {
  (handlers as EventHandlerList<Events[keyof Events]>)
   .slice()
   .map((handler) => {
    handler(evt!);
   });
 }

  // 獲取 * 對應(yīng)的 Handlers
 handlers = all!.get('*');
 if (handlers) {
  (handlers as WildCardEventHandlerList<Events>)
   .slice()
   .map((handler) => {
    handler(type, evt!);
   });
 }
}

為什么是使用 slice().map() ,而不是直接使用 forEach() 進(jìn)行觸發(fā)?具體可查看:https://github.com/developit/mitt/pull/109,具體可以拷貝相關(guān)代碼進(jìn)行調(diào)試,直接更換成 forEach 的話,針對以下例子所觸發(fā)的 emit 是錯誤的:

import mitt from './mitt'

type Events = {
  test: number
}

const Emitter = mitt<Events>()
Emitter.on('test'function A(num{
  console.log('A', num)
  Emitter.off('test', A)
})
Emitter.on('test'function B({
  console.log('B')
})
Emitter.on('test'function C({
  console.log('C')
})

Emitter.emit('test'32432// 觸發(fā) A,C 事件,B 會被漏掉
Emitter.emit('test'32432// 觸發(fā) B,C,這個是正確的

// 原因解釋:
// forEach 時,在 Handlers 循環(huán)過程中,同時觸發(fā)了 off 操作
// 按這個例子的話,A 是第一個被注冊的,所以第一個會被 slice 掉
// 因?yàn)?nbsp;array 是引用類型,slice 之后,那么 B 函數(shù)就會變成第一個
// 但此時遍歷已經(jīng)到第二個了,所以 B 函數(shù)就會被漏掉執(zhí)行

// 解決方案:
// 所以對數(shù)組進(jìn)行 [].slice() 做一個淺拷貝,off 的 Handlers 與 當(dāng)前循環(huán)中的 Handlers 處理成不同一個
// [].slice.forEach() 效果其實(shí)也是一樣的,用 map 的話個人感覺不是很語義化

1.5 小結(jié)

  • TS keyof 的靈活運(yùn)用
  • undefined extends Events[Key] ? Key : never,為 TS 的條件類型(https://www.typescriptlang.org/docs/handbook/2/conditional-types.html)
  • undefined extends Events[Key] ? Key : never,當(dāng)我們想要編譯器不捕獲當(dāng)前值或者類型時,我們可以返回 never類型。never 表示永遠(yuǎn)不存在的值的類型
// 來自 typescript 中的 lib.es5.d.ts 定義

/**
 * Exclude null and undefined from T
 */

type NonNullable<T> = T extends null | undefined ? never : T;

// 如果 T 的值包含 null 或者 undefined,則會 never 表示不允許走到此邏輯,否則返回 T 本身的類型
  • mitt 的事件回調(diào)函數(shù)參數(shù),只會有一個,而不是多個,如何兼容多個參數(shù)的情況,官方推薦是使用 object 的(object is recommended and powerful),這種設(shè)計(jì)擴(kuò)展性更高,更值得推薦。

2. tiny-emitter 源碼解讀

2.1 主邏輯

  1. 所有方法都是掛載在 E 的 prototype 內(nèi)的,總共暴露了 once,emit,off,on 四個事件的方法:
function E ({
  // Keep this empty so it's easier to inherit from
  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}

// 所有事件都掛載在 this.e 上,是個 object
E.prototype = {
 onfunction (name, callback, ctx{},
  oncefunction (name, callback, ctx{},
 emitfunction (name{},
  offfunction (name, callback{}
}

module.exports = E;
module.exports.TinyEmitter = E;
  1. once 訂閱一次事件,當(dāng)被觸發(fā)一次后,就會被銷毀:
once: function (name, callback, ctx{
  var self = this;
  // 構(gòu)造另一個回調(diào)函數(shù),調(diào)用完之后,銷毀該 callback
  function listener ({
    self.off(name, listener);     // 銷毀
    callback.apply(ctx, arguments);  // 執(zhí)行
  };

  listener._ = callback
  
  // on 函數(shù)返回 this,所以可以鏈?zhǔn)秸{(diào)用
  return this.on(name, listener, ctx); // 訂閱這個構(gòu)造的回調(diào)函數(shù)
}
  1. on 事件訂閱
on: function (name, callback, ctx{
  var e = this.e || (this.e = {});

  // 單純 push 進(jìn)去,這里也沒有做去重,所以同一個回調(diào)函數(shù)可以被訂閱多次
  (e[name] || (e[name] = [])).push({
    fn: callback,
    ctx: ctx
  });

  // 返回 this,可以鏈?zhǔn)秸{(diào)用
  return this;
}
  1. off 事件銷毀
off: function (name, callback{
  var e = this.e || (this.e = {});
  var evts = e[name];
  var liveEvents = []; // 保存還有效的 hanlder

 // 傳遞的 callback,如果命中,就不會被放到 liveEvents 里面
  // 所以這里的銷毀是一次性銷毀全部相同的 callback,與 mitt 不一樣
  if (evts && callback) {
    for (var i = 0, len = evts.length; i < len; i++) {
      if (evts[i].fn !== callback && evts[i].fn._ !== callback)
        liveEvents.push(evts[i]);
    }
  }

  // Remove event from queue to prevent memory leak
  // Suggested by https://github.com/lazd
  // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910

  // 如果沒有任何 handler,對應(yīng)的事件 name 也可以被 delete
  (liveEvents.length)
    ? e[name] = liveEvents
    : delete e[name];

  // 返回 this,可以鏈?zhǔn)秸{(diào)用
  return this;
}
  1. emit 事件觸發(fā)
emit: function (name{
  // 取除了第一位的剩余所有參數(shù)
  var data = [].slice.call(arguments1);
  
  // slice() 淺拷貝
  var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
  var i = 0;
  var len = evtArr.length;

  // 循環(huán)逐個觸發(fā) handler,把 data 傳入其中
  for (i; i < len; i++) {
    evtArr[i].fn.apply(evtArr[i].ctx, data);
  }

  // 返回 this,可以鏈?zhǔn)秸{(diào)用
  return this;
}

2.2 小結(jié)

  • return this,支持鏈?zhǔn)秸{(diào)用
  • emit 事件觸發(fā)時,[].slice.call(arguments, 1) 剔除第一個參數(shù),獲取到剩余的參數(shù)列表,再使用 apply 來調(diào)用
  • on 事件訂閱時,記錄的是 { fn, ctx },fn 為回調(diào)函數(shù),ctx 支持綁定上下文

3. mitt 與 tiny-emitter 對比

  • TS 靜態(tài)類型校驗(yàn)上 mitt > tiny-emitter,開發(fā)更友好,對于回調(diào)函數(shù)參數(shù)的管理,tiny-emitter 支持多參數(shù)調(diào)用的,但是 mitt 提倡使用 object 管理,設(shè)計(jì)上感覺 mitt 更加友好以及規(guī)范
  • 在 off 事件銷毀中,tiny-emitter 與 mitt 處理方式不同,tiny-emitter 會一次性銷毀所有相同的 callback,而 mitt 則只是銷毀第一個
  • mitt 不支持 once 方法,tiny-emitter 支持 once 方法
  • mitt 支持 * 全事件訂閱,tiny-emitter 則不支持

4. Vue eventBus 事件總線(3.x 已廢除,2.x 依然存在)

  • 關(guān)于 events 的處理:https://github.com/vuejs/vue/blob/dev/src/core/instance/events.js
  • 事件相關(guān)初始化:https://github.com/vuejs/vue/blob/dev/src/core/instance/index.js
  1. 初始化過程
// index.js 調(diào)用 initMixin 方法,初始化 _events object
initMixin(Vue)

// event.js 定義 initEvents 方法
// vm._events 保存所有事件 & 事件回調(diào)函數(shù),是個 object
export function initEvents (vm: Component{
  vm._events = Object.create(null)
  // ...
}

// index.js 調(diào)用 eventsMixin,往 Vue.prototype 掛載相關(guān)事件方法
eventsMixin(Vue)

// event.js 定義了 eventsMixin 方法
export function eventsMixin (Vue: Class<Component>{
  // 事件訂閱
 Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {}
  // 事件訂閱執(zhí)行一次
  Vue.prototype.$once = function (event: string, fn: Function): Component {}
  // 事件退訂
  Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {}
  // 事件觸發(fā)
  Vue.prototype.$emit = function (event: string): Component {}
}
  1. $on 事件訂閱
// event 是個 string,也可以是個 string 數(shù)組
// 說明可以一次性對多個事件,訂閱同一個回調(diào)函數(shù)
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
  const vm: Component = this
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      vm.$on(event[i], fn)
    }
  } else {
    // 本質(zhì)是就是對應(yīng) event,push 對應(yīng)的 fn
    (vm._events[event] || (vm._events[event] = [])).push(fn)
    
    // 以下先不展開,關(guān)于 hookEvent 的調(diào)用說明
    // optimize hook:event cost by using a boolean flag marked at registration
    // instead of a hash lookup
    if (hookRE.test(event)) {
      vm._hasHookEvent = true
    }
  }
  return vm
}
  1. $once 事件訂閱&執(zhí)行一次
// 包裝一層 on,內(nèi)包含退訂操作以及調(diào)用操作
// 訂閱的是包裝后的 on 回調(diào)函數(shù)
Vue.prototype.$once = function (event: string, fn: Function): Component {
  const vm: Component = this
  function on ({
    vm.$off(event, on)
    fn.apply(vm, arguments)
  }
  on.fn = fn
  vm.$on(event, on)
  return vm
}
  1. $off 事件退訂
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
  const vm: Component = this
  
  // 沒有傳參數(shù),說明全部事件退訂,直接清空
  if (!arguments.length) {
    vm._events = Object.create(null)
    return vm
  }
  
  // 存在 event 數(shù)組,遍歷逐一調(diào)用自己
  if (Array.isArray(event)) {
    for (let i = 0, l = event.length; i < l; i++) {
      vm.$off(event[i], fn)
    }
    return vm
  }
  
  // 以下情況為非數(shù)組事件名,為單一事件,則獲取該事件對應(yīng)訂閱的 callbacks
  const cbs = vm._events[event]
  // 若 callbacks 為空,什么都不用做
  if (!cbs) {
    return vm
  }
  // 如果傳入的 fn 為空,說明退訂這個事件的所有 callbacks
  if (!fn) {
    vm._events[event] = null
    return vm
  }
  // callbacks 不為空,并且 fn 不為空,則為退訂某個 callback
  let cb
  let i = cbs.length
  while (i--) {
    cb = cbs[i]
    // 訂閱多次的 callback,都會被退訂,一次退訂所有相同的 callback
    if (cb === fn || cb.fn === fn) {
      cbs.splice(i, 1)
      break
    }
  }
  return vm
}
  1. $emit 事件觸發(fā)
Vue.prototype.$emit = function (event: string): Component {
  const vm: Component = this
  if (process.env.NODE_ENV !== 'production') {
    const lowerCaseEvent = event.toLowerCase()
    if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
      tip(
        `Event "${lowerCaseEvent}" is emitted in component ` +
        `${formatComponentName(vm)} but the handler is registered for "${event}". ` +
        `Note that HTML attributes are case-insensitive and you cannot use ` +
        `v-on to listen to camelCase events when using in-DOM templates. ` +
        `You should probably use "${hyphenate(event)}" instead of "${event}".`
      )
    }
  }
  
  // 獲取這個 event 的 callbacks 出來
  let cbs = vm._events[event]
  if (cbs) {
    cbs = cbs.length > 1 ? toArray(cbs) : cbs
    // 獲取除了第一位,剩余的其他所有參數(shù)
    const args = toArray(arguments1)
    const info = `event handler for "${event}"`
    // 遍歷逐一觸發(fā)
    for (let i = 0, l = cbs.length; i < l; i++) {
      // 以下暫不展開,這是 Vue 中對于方法調(diào)用錯誤異常的處理方案
      invokeWithErrorHandling(cbs[i], vm, args, vm, info)
    }
  }
  return vm
}

實(shí)現(xiàn)邏輯大致和 mitt,tiny-emitter 一致,也是 pubsub,整體思路都是維護(hù)一個 object 或者 Map,on 則是放到數(shù)組內(nèi),emit 則是循環(huán)遍歷逐一觸發(fā),off 則是查找到對應(yīng)的 handler 移除數(shù)組
TODO:

  • Vue 中對于方法調(diào)用錯誤異常的處理方案:invokeWithErrorHandling
  • hookEvent 的使用&原理

5. 附錄

  • rimraf:https://www.npmjs.com/package/rimraf
  • microbundle:https://www.npmjs.com/package/microbundle
  • package.json exports 字段:https://nodejs.org/api/packages.html#packages_conditional_exports
  • Map:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map
  • TS 條件類型:https://www.typescriptlang.org/docs/handbook/2/conditional-types.html
  • TS Never:https://www.typescriptlang.org/docs/handbook/basic-types.html#never
  • TS keyof: https://www.typescriptlang.org/docs/handbook/2/keyof-types.html#the-keyof-type-operator
  • What is the JavaScript >>> operator and how do you use it? https://stackoverflow.com/questions/1822350/what-is-the-javascript-operator-and-how-do-you-use-it

瀏覽 691
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)
評論
圖片
表情
推薦
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報(bào)

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 色哟哟无码精品一区二区三区| 一起操在线观看| 亚洲精品偷拍| 在线观看亚洲视频| 五丁香在线观看AV| 欧美一级片免费看| 无码人妻一区二区三一区免费n狂飙| 日本A片在线免费观看| 2021国产视频| ThePorn日本无码| 日本少妇网站| 亚洲欧美日韩电影| EEUSS| 综合伊人| 欧美偷拍一区二区| 亚洲三级在线免费观看| 蜜桃91精品入口| 99在线观看精品视频| 天天操网站| 无码东京热国产| 国产波霸爆乳一区二区| 四川BBB嫩BBBB爽BBBB| AV无码中文| 尤物精品| 福利视频网站| 美女黄色视频永费在线观看网站| 51午夜福利| a片免费观看视频| 91久久精品一区二区三| 亚洲97| 曰本精品综合网在线| 天天日天天噜| 人人看人人爱| 亚洲AV成人精品日韩在线播放| 97资源在线| 日韩免费在线| 91大熟女91大腚女人| 伊大香蕉| AV免费播放| 五月天激情小说| 国产女人18毛片水18精品软件| 黄色视频免费观看国产| 日本综合色| 亚洲精品a| www.爆操| 深夜福利一区二区| 日韩激情无码一区二区| 无码免费观看| 欧美色一级| 韩国一级AV| 久久久久无码国产精品不卡| 一级A片亲子乱| 欧美精品xxx| 东京热久久综合| www国产精品| 亚洲激情视频| 日本中文字幕在线观看视频| 青青草成人电影| 日韩黄色AV| 午夜福利av在线| 午夜福利视频3000| 欧美成人三级在线观看| 午夜做爱福利视频| 黄色A片免费| 伊人久久免费| 国产黄色电影| 操逼网址大全| 51av在线| 操极品美女| 一区二区三区不卡在线| 亚洲无码在线播放| 国产免看一级a一片成人aⅴ| 视频一区二区三| 亚洲无码AV电影| 狠狠撸狠狠撸| 福利国产在线| 久久中文网| 伊人热久久| 黄色A片免费看| 青草中文娱乐网在线| 手机在线毛片| 自慰精品| www.seses| 国产丝袜在线视频| 超级碰碰碰碰碰碰碰碰碰| 欧美成人免费观看| 一级AV| 久久草视频在线播放| 91无码人妻一区二区成人AⅤ| 久草大香蕉视频| 美女自慰网站在线观看| 国产女人免费| 黄片视频免费播放| 大香蕉综合在线| 影音先锋三区| 成人午夜无码福利视频| 东京热网站在线观看| 永久免费一区二区| 亚洲AV秘一区二区色盗战流出| 少妇AV| 99热精品在线播放| 蜜桃一区| 不卡av在线| 二区三区在线观看| 在线AⅤ| 天天操天天操天天操天天| 国产尤物视频| 欧美综合网在线观看| 中文在线一区| 91成人做爰A片| 久久伊思人在| 91精东传媒果冻传媒| 欧美性爱在线播放| 国产一级18片视频| 奇米色网| 日韩三级视频| 免费A在线| 国产超碰在线| 午夜性福利视频| 性v天堂| 国产成人自拍偷拍视频| 老骚老B老太太BBW| 91艹逼| 婷婷激情五月| 在线观看av网站| 一本一道久久a久久精品综合| 一本大道东京热AV| 欧美国产在线观看综合| 亚洲最大福利视频| 操欧美女人| 亚洲成人AV在线观看| 久久九九视频| 99激情视频| 北条麻妃久久久| 东方成人av| 国产日B| 黄片入口| 色天堂污| www.zaixianshipin| 97日日| 黄片免费无码| 一道本一区| 久久精品人人| 大香蕉视频在线观看| 国色天香网站| 大香蕉网站在线观看| 豆花网| 自慰喷水在线观看| 日本在线免费观看| 日韩人妻码一区二区三区| 国产精品久久久久国产A级| 一区二区三区无码高清| 日韩特黄片| 无码精品一区二区三区同学聚会| 91爱爱·com| 中文字幕精品在线免费视频观看视频 | 亚洲成人无码精品| aaa免费| 91久久国产综合久| 操逼视频在线免费看| 久久久一区二区三区| 日本中文字幕不卡| 国产女人18毛片水18精品软件| 2025国产精品| 欧美性猛交XXXX乱大交HD| 国产无码成人电影| 在线无码视频播放| 日韩精品视频免费在线观看| 日本操B久久| 日韩久久免费视频| 激情国产AV| 亚洲AV在线看| 婷婷伊人綜合中文字幕| 亚洲视频,中文字幕| 日韩视频三区| ThePorn人妻白浆| 东京热久久综合| 北条麻妃无码一区三区| 污网站免费在线观看| YOUjiZZ欧美大全| 日日碰狠狠添| 欧美夜夜骑| 免费爱爱视频网站| 无码视频在线播放| 91丨国产丨熟女熟女| 屁屁影院CCYYCOM国产| 午夜精品久久久久久不卡8050 | 欧洲成人在线观看| 先锋影音成人资源| 国产人妖视频| 欧美黄片一区| 黄色av免费在线| 91少妇精品| 天天添天天操| 亚洲综合中文字幕在线| 伊人大香蕉在线网| 亚洲任你操超碰在线| 午夜AV无码| 日韩色在线| 日本免费A∨| 欧美精品午夜福利无码| 成人毛片18女人毛片| 欧美日韩精品在线视频| 一区二区三区水蜜桃| free性欧美| 午夜亚洲| 永久免费一区二区三区| 国产学生妹在线播放| 黄色电影一区二区| 欧美熟妇高潮流白浆| 日本一级片中文字幕| 五夜福利成人视频| 黄色片视频网站| 欧美一级婬片AAAA毛片| 熟妇女人妻丰满少妇中文字幕 | 97干网| 中文字幕第一页亚洲| 国产一区二区00000视频| 久久人妻免费视频| 免费的黄色视频| 超碰免费91| 日韩久久高清| 精品交换一区二区三区无码| 色逼视频| 日韩欧美视频一区| 在线视频久| 少妇高潮一区二区三区99| 天天日很很操| 日韩高清一区| 91豆花成人网站| 亚洲第一大网站| 精品狼友| 中文无码99| 黑人AV| 蜜桃av秘无码一区二区| 国产日韩欧美综合在线| 99热综合在线| 影音先锋三区| 成人视频高清无码| 丁香五月成人网| 欧美特级毛片| 日本在线播放| 人人艹人人摸| 欧美色图在线播放| 婷婷五月天黄色| 九九精品久久| 成人网站在线免费看| 久操操| 国产一级婬片A片免费无成人黑豆| 麻豆成人精品国产免费| 国产亲子乱XXXXimim/| 欧美成人免费在线| 亚欧精品久久久| 福利视频在线| 高圆圆一区二区三区| 国产精品视频导航| 四虎无码视频| 精品无码不卡| 天天操人人操| 在线色综合| 国产a片免费观看| 北岛玲丝袜办公室高跟| 国产精品美女久久久| 免费看国产黄色| 99热官方网站| 手机av网站| 国产精品久久久久久久久借妻| 久久都是精品| 欧美精品成人网站| 色综合久久88色综合| 久久激情av| 欧美高清另类| 欧美日韩亚洲成人| 亚州在线中文字幕经典a| 乱子伦毛片国产| 西西444WWW无码大胆知乎| 国产伦子伦一级A片在线| 亚洲www在线| A片视频免费观看| 在线免费毛片| 欧美老熟妇乱大交XXXXX| 亚洲欧美一区二区三区在线| 暖暖爱视频免费| 久热精品视频| 欧美三级在线| 欧美黄色站| 黄色网址av| 国产一精品| 未满十八18禁止免费无码网站 | 国产色情视频在线观看| 欧美一区二区三区成人片下载| 日韩VA| 男男做受A片AAAA| 国产AV中文字幕| 老熟女视频| 欧美激情一区二区| 二区无码| 淫一区二区| 黄色大片中国一级片-免费看特一级片-亚洲黄色AV | 午夜啊啊啊| x88AV吊钟奶熟女| 一级欧美日韩| 欧美大香蕉网| 青青草免费在线视频| 成人色播播| 无套内射免费视频| 色婷婷狠狠操| 毛片动态图| 男人资源网| 五月天婷婷基地| 豆花AV| 99视频网站| 日本成人中文字幕在线观看| 亚洲av二区| 日韩三级精品| 亚洲第一视频在线观看| 情侣av| 欧美成人黄色| 亚洲成人av在线| 国产黄色视频在线观看| AV女优天堂| 黄色视频在线观看地址| 小明看台湾成人永久免费视频网站 | 国产成人av在线播放| 麻豆一区二区| 视频一区二区免费| 999在线视频| 成人做爰黄A片免费| 亚洲a级| 自慰精品| 高颜值呻吟给力| 久久久久久久久成人| 91麻豆精品在线观看| 杨贵妃一级婬片90分钟| 久久综合电影| www天天操| 日韩三区在线| 亚洲成人无码精品| 成人大香蕉网| 日本免费一级片| 青娱乐偷窥成| 日韩精品中文无码| 日韩AV无码一区二区三区| 国产欧美日本| 玖玖爱AV| 五月天婷婷在线视频| 欧美成年人网站| 天天操天天干天天射| 久久精品免费| 欧美一区二区三区成人| 人人干天天干| 岛国AV免费看| 中文字幕精品在线免费视频观看视频| 午夜精品久久久久久久99热精东 | 久久视频免费| 先锋av资源| 三级理论网站| 黄片51| 蜜臀一区二区三区| 久久精品99视频| 91高清无码视频| 久久久无码视频| 亚洲成人av| 激情五月天在线视频| 97香蕉网| 天天操B| 东京热av一区二区| 欧美性爱福利视频| 久久久久99精品成人片欧美一区| 中文字幕北条麻妃| 久久免费国产视频| 无码网址| 99操99| 国产一级a毛一级a做免费高清视频 | 国产精品视频福利| 日韩影音| 国产香蕉在线视频| 亚洲一卡二卡| 免费一级欧美片在线观看| 大炕上公让我高潮了六次| 婷婷在线观看视频| 五月天丁香婷婷视频| 午夜AV电影| 亚洲色情网站| 一级a免一级a做免费线看内裤| 操逼视频在线看| 一级毛AA片| 9久9久9久9久女女女女| 亚洲欧美视频在线观看| 国产日韩欧美久久| 影音先锋在线视频| 99re6热在线精品视频功能 | 五月天婷婷在线播放视频免费观看| 人人草在线观看| 午夜一区二区三区| 欧美性生交18XXXXX无码| 91丨熟女丨首页| 国产一级黄色A片| 久久精品www人人爽人人| 6969电视影片最新更新| 中国丰满妇BBwBBwHD| 午夜成人免费视频| 久色婷婷在线| 免费色网站| 国产91白浆四溢| 影音先锋国产AV| 日韩一区二区三区在线观看| 日本黄色高清视频| 亚洲成人在线免费观看| 人妻18无码人伦一区二区三区精品| 午夜黄色影院| 成人做爰黄级A片免费看土方| 99国产精品99久久久久久粉嫩 | 蜜桃av秘无码一区二区三| 91精品国产乱码香蕉黄瓜草莓| 日日干干| 日本免费无码| 91视频美女模特| 欧美日韩免费在线| 一区二区三区四区五区六区高清无吗视频| 免费黄色视频网站大全| 91精品久久久久久| 亚洲精品国产精品国自产| 成人黄片网站| 精品视频网站| 大香蕉在线观看视频| 人成无码| 天天干天天日天天操| 欧美久久久久久| 亚洲va在线∨a天堂va欧美va| 午夜久久电影| 五月天色色小说| 69成人免费视频| 超碰日日夜夜| 国产V片| 蜜桃91在线| 蜜臀色欲AV无码人妻| 五十路老国产| 蜜桃黄片AV在线观看| 人人色人人操人人干| 新超碰在线观看| 国产五月婷婷| 亚洲精品视频在线观看免费| 欧美熟妇精品一级A片视色| 狠狠搞狠狠操| 美国久久久| 玖玖婷婷| 足浴店少妇69XXX| 黄片www.| 人妻超碰| 日韩操比视频| 搡BBBB搡BBB搡我瞎了| 国产真实乱婬A片久久久老牛| 亚洲va| 一级性爽AV毛片| 午夜操一操一级| 精品久久成人| 丁香五月激情啪啪| 久久精品福利视频| 婷婷毛片| 天天干夜夜操熟女| 大香蕉尹在线| 五月天综合在线| 黄片视频在线观看| 草久免费视频| 日本亚洲欧洲免费| 久热中文| 亚洲va欧洲va国产va不卡| 人人人人干| 人人操av| 极品av| 三级黄片免费看| 国产精品二区高清在线苍井空| 丁香五月天激情视频| 91精品国产综合久久久不打电影| 久久婷婷五月综合伊人| 中国黄色一级A片| 操逼视频无码| 91在线无码精品在线看| 99久久爱re热6在播放| 亚洲一级婬片A片AAAA网址| 激情国产av| 午夜ww| 伊人在线成人视频| 人人爽人人澡| 俄罗斯白嫩BBwBBwBBw91| 一道本视频在线免费观看| 成人不卡| 五月婷色| 精品一区二区三区四区学生| 五月天黄色电影| 欧美亚洲中文| 天天干天天天天| 久久久999精品视频| 无码免费一区二区| 色天使视频| 看A片在线| 肏少妇女情人大骚逼直播一区二区 | 69av视频在线观看| 中文字幕第6页| 中文字幕av免费观看| 欧美性爱免费在线视频| 熟女无码| 欧美囗交荫蒂AAAA| 神马午夜精品91| 西西人体BBBBBB| 人人妻人人澡人人爽久久av| 亚洲综合一区二区| 日韩AV无码专区亚洲AV| 福利视频在线| 4080yy午夜理论片成人| 黄色片视频网站| 国产精品每日更新| 欧美性爱无码在线| 国产熟妇码视频黑料| 久久国产性爱| 精品日韩一区二区三区| 成人在线激情| 躁BBB躁BBB躁BBBBBB日| 久久美女视频| 国产真实露脸乱子伦对白高清视频 | 日韩精彩视频| 青娱乐亚洲| а√最新版天堂中文在线| 天天操天天日天天操| 开心色播五月| 国产欧美一区二区三区视频| 国产激情无码视频| 九一九色国产| 熟女中文字幕| 欧美一级视频在线观看| 97资源在线视频| 欧美成人网站视频| 超碰免费在线观看| 爱操逼综合网| 在线观看亚洲一区| 国产精品免费一区二区三区四区视频 | 无码少妇视频| 四虎影院人妻| 超碰在线看| 人人爱人人摸人人操| av在线无码观看| 久草一区二区三区| 五月天天| 波多野结衣网址| 欧美图片小说| 成人aV无码精品国产一区二区| 色老久久| 国产成人无码毛片| 在线成人网站| 一区二区三区成人电影| 一道本无码在线播放| 动漫一区二区三区| 韩国一区二区三区在线观看| 人妻日韩精品中文字幕| aa无码| www.国产| 亚洲少妇熟女| 91亚洲一区| 豆花网无码视频观看| 成人电影一区二区三区| 欧美视频免费在线观看| 久草国产视频| 亚洲AV成人无码精品区| 亚洲三级视频在线播出| 亚洲a视频在线| 日韩一区二区三区在线观看| 特极西西444WWW大胆无码| 国产在线视频一区二区三区| 国产五月天婷婷| 91国啪| 欧美理伦| 韩剧《邻居的妻子》电视剧| 久久久久久久国产精品| 爆乳尤物一区二区三区| 欧美一区二区三区不卡| 日韩99在线| 黄色视频在线观看| 国产成人精品亚洲男人的天堂| 久久嫩草在线影院| 色欲av在线| 少妇搡BBBB搡BBB搡造水爽| 国产精品播放| 国产亲子乱XXXXimim/| 骚色综合| 亚洲无码视频免费在线观看| 伊人日日| 黄色毛片网站| 大香蕉日韩| 一级黄色片视频| 亚洲AV无一区二区三区久久| 亚洲一级性爱| 自拍欧美亚洲| 少妇搡BBBB搡BBB搡18禁| 亚洲美女网站在线观看| 久久久久久久久久国产精品免费观看-百度| 亚洲成人在线免费观看| 国产精品色色| 高清无码波多野结衣| 91无码秘蜜桃一区二区三区-百度 精品人妻一区二区三区在线视频不卡 | 成人久久| 青青草成人在线| 精品综合网| 国产91精品探花一区二区| 日韩av中文| 亚洲国产成人在线视频| 一本之道高清数码大全| 大色鬼在线天堂精品| 欧美,日韩,中文字幕| 青娱乐在线成人| 六月婷婷五月丁香| 天天干天天添| 日韩免费高清视频| 超碰啪啪| 伊人久久中文字幕| 在线观看免费国产| 美女极度色诱图片www视频| 桃花岛tⅴ+亚洲品质| 国产三级性爱视频| av在线小说| YOUjiZZ欧美大全| 欧美偷拍一区二区| 久久久久人妻| 褒姒AV无玛| 欧美黄片免费| 欧美视频一区二区| 成人A片一级| www.黄色在线观看| 少妇搡BBBB搡BBB搡造水爽| 久草青青草| 中文字幕第69页| 日韩欧美操逼视频| 国产女人18毛片水18精品| 日韩成人一级片| 日本韩国高清无码| 黄色免费av| 无码人妻蜜桃| 一级a片在线播放| 人人摸人人摸人人| 中文字幕成人在线播放| 久久久精品无码| 人妻少妇中文字幕久久牛牛| 苍井空无码一区二区三区| 91性爱嫩逼视频| 奇米成人片| 99热精品在线| 久久久久亚洲| 日本黄色电影网站| 蜜桃视频| 青草视频在线| 五月婷婷综合网| 高潮视频在线观看| 在线观看黄色小视频| 香蕉久草| 国产久久久久久| 91无码在线观看| 3D动漫啪啪精品一区二| 爱爱无码| 18禁91| 91Av视频| xxx综合网| 综合久久久| 国产精品色哟哟| 无码免费观看视频| 黑人无码视频| 青青操在线观看| 加勒比久久综合| 蜜柚AV| 亚洲美女视频| 免费看a| 中文字幕视频2023| 免费亚洲视频| 先锋影音资源站| 懂色av| 大香蕉一级红色片青青河边草| 最新va在线观看| 操碧一区| 国产欧美视频在线| 五月婷婷免费视频| 内射日韩| 国产欧美精品AAAAAA片| 欧美日韩国产三级| 人人爱人人干人人操| 日韩欧美性爱视频| 玖玖色视频| 国产真实乱婬A片久久久老牛| 欧美综合自拍| 偷拍亚洲色图| 少妇搡BBBB搡BBB搡AA| 黄色视频毛片| 日韩射| 亚洲综合影院| 微拍福利一区| 中文字幕免费视频在线观看| 欧美黄色片在线观看| 免费的AV| 午夜福利院| 国产成人亚洲日韩| 免费中文视频| 黃色A片一級二級三級免費久久久| 国产三级日本三级国产三级| 91天天综合在线| 国产人妻人伦精品1国产丝袜| 99r6热只有精品免费观看| 伊人激情五月| 俺也来最新色视频| 一级大片免费看| 成人在线毛片| 久久婷婷综合网| 国产高清无码一区二区| 五月婷婷一区| 操B视频网站| 欧美操| 色高清无码免费视频| 影音先锋成人视频| 亚洲欧美久久久久久久久久久久 | 亚洲无码成人网站| 91综合娱乐| 操逼视频免费观看| 中国免费看片| 91网在线观看| 亚洲永久天堂| 日韩高清无码观看| www免费视频在线观看播放| 国产成人无码免费| 粉嫩小泬BBBBBB免费| 亚洲中文字幕码mv| 日韩天堂在线| 久久大香蕉视频| 天天狠天天干| 婷婷五月福利| 草久伊人| 在线视频99| 国产秘精品一区二区三区免费 | 17.3c一起起草| 国产小视频在线观看| 久久久无码精品亚洲日韩男男| 三级毛片视频| 国产精品久久久久久无人区| 亚洲欧美不卡| 无码骚逼| 美女黄色视频网站| 91人妻中文字幕在线精品| 国产99热| 日本久久婷婷| 久久A级片| 91乱| а√在线中文8| 日韩性爱视频在线观看| 亚洲免费视频在线| 日韩理论片| 中文字幕播放| 亚洲视频天天射| 亚洲天堂影音先锋| 簧片在线免费观看| 91久久久久久久| 欧美日韩黄| 色婷婷一区二区三区四区五区精品视 | 国产三级三级三级| 欧美日韩在线一区| 午夜爽爽| 九九视屏| 性爱av在线观看| 加勒比操逼| 亚洲AV无一区二区三区久久| 偷拍视频网站| 日本无码在线观看| 日韩99热| 国产日B| 人人肏屄| 日本内射网站| 影音先锋男人站| 日本三级片在线动| 欧美日韩岛国| 亚洲天堂婷婷| 亚洲视频一区二区三区四区娇小视频在线观看视频 | 日韩黄色网址| 欧美不卡在线播放| 日日夜夜天天综合| 91性爱视频在线观看| 国产中文在线观看| 人人操人人插| 操比一区| 霸道总裁雷总各种姿势白浆爱情岛论坛 | 欧美成人在线免费视频| 极品人妻疯狂3p超刺激| 国产精品秘久久久久久久久| 久久久www| 东京热第一页| 色网站在线| 国产成人无码免费看片| 韩国av在线| 边吃奶边做爱| 操逼123首页| 亚洲成色A片77777在线小说| www.18禁| 91麻豆免费视频网站| 在线观看中文字幕视频| 香蕉成人网站| 婷婷五月一区| 在线无码一区| 激情内射| 天天舔九色婷婷| 日韩综合在线视频| 国产精品视频福利| 麻豆国产在线| 黄色永久免费| 午夜AAA| 麻豆视频在线观看| 亚洲第一色在线| P站免费版-永久免费的福利视频平台 | 亚洲天码中字| 一级免费黄色电影| 日韩性爱一区二区| 无码在线专区| 东方AV在线免费观看| 日韩人妻无码一区| 色天堂色天使| 中文字幕永久在线5| 成人网站一区| 欧美一级日韩| 久热在线资源福利站| 亚洲综合无码| 一道本一区二区| 日韩黄色免费电影| www日本在线| 日逼操| 亚洲欧美日韩国产| 99久久婷婷国产综合精品漫| 一本色道久久综合无码人妻四虎 | 内射一区二区| 国产精品乱码毛片在线人与| 成人AV天堂| 成人黄片免费| 人人看人人色| 无码蜜桃一区二区| 麻豆精品在线播放| 99在线观看| 伊人婷婷| a黄色片| 亚洲三级在线视频| aaa在线观看| 人人操97| 国产乱码精品一区二区三区的特点| 中文人妻第9页| 翔田千里一区二区| 臭小子晚上让你爽个够视频| www.日批| 青娱乐亚洲视频在线| 天天日天天日天天日| 好吊一区二区三区| 自拍偷拍综合| 一级日逼片| 黄色AV免费在线观看| 亚洲秘av无码一区二区| 国产一级a毛一级a做免费的视频| gay成人在线观看| 精品三区| 国产一区在线视频| 欧美日韩99| 国产一级婬片A片免费无成人黑豆| 亚洲成人AV电影| 激情五月俺也去| 黄色视频免费观看国产| 二区三区在线观看| 日本一本视频| 大奶一区二区| 日韩欧美综合| 日韩黄色网| 亚洲精品黄色| 国产秘久久一区二区| 污污污www精品国产网站| 午夜性爱剧场| 亚洲老鸭窝| a视频免费| 神马影院午夜福利| 国产精品久久久久精| 成人AV三级片| 国产做受91电影| 三级片免费网址| 国产手机精品视频| 亚洲AV秘成人久久无码海归| 激情五月婷婷综合| 在线观看免费黄网站| 少妇搡BBBB搡BBB搡毛片少妇 | 嫰BBB槡BBBB槡BBBB| 国产色情视频在线观看| 日本成人电影在线观看| av婷婷五月天| 在线操b| 99九九热| 大香蕉AV在线观看| 日本免费在线视频| 欧美人妻中文字幕| 国产高潮在线| 天天日夜夜草| 西西444WWW无码精品| 老熟妇一区二区三区啪啪| 免费播放婬乱男女婬视频国产| 国产亚洲欧美视频|