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

聊聊Vue3 的模板編譯優化

開發 前端
Vue3 正式發布已經有一段時間了,前段時間寫了一篇文章(《Vue 模板編譯原理》)分析 Vue 的模板編譯原理。今天的文章打算學習下 Vue3 下的模板編譯與 Vue2 下的差異,以及 VDOM 下 Diff 算法的優化。

[[351771]]

Vue3 正式發布已經有一段時間了,前段時間寫了一篇文章(《Vue 模板編譯原理》)分析 Vue 的模板編譯原理。今天的文章打算學習下 Vue3 下的模板編譯與 Vue2 下的差異,以及 VDOM 下 Diff 算法的優化。

編譯入口

了解過 Vue3 的同學肯定知道 Vue3 引入了新的組合 Api,在組件 mount 階段會調用 setup 方法,之后會判斷 render 方法是否存在,如果不存在會調用 compile 方法將 template 轉化為 render。

  1. // packages/runtime-core/src/renderer.ts 
  2. const mountComponent = (initialVNode, container) => { 
  3.   const instance = ( 
  4.     initialVNode.component = createComponentInstance( 
  5.       // ...params 
  6.     ) 
  7.   ) 
  8.   // 調用 setup 
  9.   setupComponent(instance) 
  10.  
  11. // packages/runtime-core/src/component.ts 
  12. let compile 
  13. export function registerRuntimeCompiler(_compile) { 
  14.   compile = _compile 
  15. export function setupComponent(instance) { 
  16.   const Component = instance.type 
  17.   const { setup } = Component 
  18.   if (setup) { 
  19.     // ...調用 setup 
  20.   } 
  21.   if (compile && Component.template && !Component.render) { 
  22.    // 如果沒有 render 方法 
  23.     // 調用 compile 將 template 轉為 render 方法 
  24.     Component.render = compile(Component.template, {...}) 
  25.   } 

這部分都是 runtime-core 中的代碼,之前的文章有講過 Vue 分為完整版和 runtime 版本。如果使用 vue-loader 處理 .vue 文件,一般都會將 .vue 文件中的 template 直接處理成 render 方法。

  1. //  需要編譯器 
  2. Vue.createApp({ 
  3.   template: '<div>{{ hi }}</div>' 
  4. }) 
  5.  
  6. // 不需要 
  7. Vue.createApp({ 
  8.   render() { 
  9.     return Vue.h('div', {}, this.hi) 
  10.   } 
  11. }) 

完整版與 runtime 版的差異就是,完整版會引入 compile 方法,如果是 vue-cli 生成的項目就會抹去這部分代碼,將 compile 過程都放到打包的階段,以此優化性能。runtime-dom 中提供了 registerRuntimeCompiler 方法用于注入 compile 方法。

主流程

在完整版的 index.js 中,調用了 registerRuntimeCompiler 將 compile 進行注入,接下來我們看看注入的 compile 方法主要做了什么。

  1. // packages/vue/src/index.ts 
  2. import { compile } from '@vue/compiler-dom' 
  3.  
  4. // 編譯緩存 
  5. const compileCache = Object.create(null
  6.  
  7. // 注入 compile 方法 
  8. function compileToFunction( 
  9.  // 模板 
  10.   template: string | HTMLElement, 
  11.   // 編譯配置 
  12.   options?: CompilerOptions 
  13. ): RenderFunction { 
  14.   if (!isString(template)) { 
  15.     // 如果 template 不是字符串 
  16.     // 則認為是一個 DOM 節點,獲取 innerHTML 
  17.     if (template.nodeType) { 
  18.       template = template.innerHTML 
  19.     } else { 
  20.       return NOOP 
  21.     } 
  22.   } 
  23.  
  24.   // 如果緩存中存在,直接從緩存中獲取 
  25.   const key = template 
  26.   const cached = compileCache[key
  27.   if (cached) { 
  28.     return cached 
  29.   } 
  30.  
  31.   // 如果是 ID 選擇器,這獲取 DOM 元素后,取 innerHTML 
  32.   if (template[0] === '#') { 
  33.     const el = document.querySelector(template) 
  34.     template = el ? el.innerHTML : '' 
  35.   } 
  36.  
  37.   // 調用 compile 獲取 render code 
  38.   const { code } = compile( 
  39.     template, 
  40.     options 
  41.   ) 
  42.  
  43.   // 將 render code 轉化為 function 
  44.   const render = new Function(code)(); 
  45.  
  46.  // 返回 render 方法的同時,將其放入緩存 
  47.   return (compileCache[key] = render) 
  48.  
  49. // 注入 compile 
  50. registerRuntimeCompiler(compileToFunction) 

在講 Vue2 模板編譯的時候已經講過,compile 方法主要分為三步,Vue3 的邏輯類似:

  1. 模板編譯,將模板代碼轉化為 AST;
  2. 優化 AST,方便后續虛擬 DOM 更新;
  3. 生成代碼,將 AST 轉化為可執行的代碼;
  1. // packages/compiler-dom/src/index.ts 
  2. import { baseCompile, baseParse } from '@vue/compiler-core' 
  3. export function compile(template, options) { 
  4.   return baseCompile(template, options) 
  5.  
  6. // packages/compiler-core/src/compile.ts 
  7. import { baseParse } from './parse' 
  8. import { transform } from './transform' 
  9.  
  10. import { transformIf } from './transforms/vIf' 
  11. import { transformFor } from './transforms/vFor' 
  12. import { transformText } from './transforms/transformText' 
  13. import { transformElement } from './transforms/transformElement' 
  14.  
  15. import { transformOn } from './transforms/vOn' 
  16. import { transformBind } from './transforms/vBind' 
  17. import { transformModel } from './transforms/vModel' 
  18.  
  19. export function baseCompile(template, options) { 
  20.   // 解析 html,轉化為 ast 
  21.   const ast = baseParse(template, options) 
  22.   // 優化 ast,標記靜態節點 
  23.   transform(ast, { 
  24.     ...options, 
  25.     nodeTransforms: [ 
  26.       transformIf, 
  27.       transformFor, 
  28.       transformText, 
  29.       transformElement, 
  30.       // ... 省略了部分 transform 
  31.     ], 
  32.     directiveTransforms: { 
  33.       on: transformOn, 
  34.       bind: transformBind, 
  35.       model: transformModel 
  36.     } 
  37.   }) 
  38.   // 將 ast 轉化為可執行代碼 
  39.   return generate(ast, options) 

計算 PatchFlag

這里大致的邏輯與之前的并沒有多大的差異,主要是 optimize 方法變成了 transform 方法,而且默認會對一些模板語法進行 transform。這些 transform 就是后續虛擬 DOM 優化的關鍵,我們先看看 transform 的代碼 。

  1. // packages/compiler-core/src/transform.ts 
  2. export function transform(root, options) { 
  3.   const context = createTransformContext(root, options) 
  4.   traverseNode(root, context) 
  5. export function traverseNode(node, context) { 
  6.   context.currentNode = node 
  7.   const { nodeTransforms } = context 
  8.   const exitFns = [] 
  9.   for (let i = 0; i < nodeTransforms.length; i++) { 
  10.     // Transform 會返回一個退出函數,在處理完所有的子節點后再執行 
  11.     const onExit = nodeTransforms[i](node, context) 
  12.     if (onExit) { 
  13.       if (isArray(onExit)) { 
  14.         exitFns.push(...onExit) 
  15.       } else { 
  16.         exitFns.push(onExit) 
  17.       } 
  18.     } 
  19.   } 
  20.   traverseChildren(node, context) 
  21.   context.currentNode = node 
  22.   // 執行所以 Transform 的退出函數 
  23.   let i = exitFns.length 
  24.   while (i--) { 
  25.     exitFns[i]() 
  26.   } 

我們重點看一下 transformElement 的邏輯:

  1. // packages/compiler-core/src/transforms/transformElement.ts 
  2. export const transformElement: NodeTransform = (node, context) => { 
  3.   // transformElement 沒有執行任何邏輯,而是直接返回了一個退出函數 
  4.   // 說明 transformElement 需要等所有的子節點處理完后才執行 
  5.   return function postTransformElement() { 
  6.     const { tag, props } = node 
  7.  
  8.     let vnodeProps 
  9.     let vnodePatchFlag 
  10.     const vnodeTag = node.tagType === ElementTypes.COMPONENT 
  11.       ? resolveComponentType(node, context) 
  12.       : `"${tag}"
  13.      
  14.     let patchFlag = 0 
  15.     // 檢測節點屬性 
  16.     if (props.length > 0) { 
  17.       // 檢測節點屬性的動態部分 
  18.       const propsBuildResult = buildProps(node, context) 
  19.       vnodeProps = propsBuildResult.props 
  20.       patchFlag = propsBuildResult.patchFlag 
  21.     } 
  22.  
  23.     // 檢測子節點 
  24.     if (node.children.length > 0) { 
  25.       if (node.children.length === 1) { 
  26.         const child = node.children[0] 
  27.         // 檢測子節點是否為動態文本 
  28.         if (!getStaticType(child)) { 
  29.           patchFlag |= PatchFlags.TEXT 
  30.         } 
  31.       } 
  32.     } 
  33.  
  34.     // 格式化 patchFlag 
  35.     if (patchFlag !== 0) { 
  36.         vnodePatchFlag = String(patchFlag) 
  37.     } 
  38.  
  39.     node.codegenNode = createVNodeCall( 
  40.       context, 
  41.       vnodeTag, 
  42.       vnodeProps, 
  43.       vnodeChildren, 
  44.       vnodePatchFlag 
  45.     ) 
  46.   } 

buildProps 會對節點的屬性進行一次遍歷,由于內部源碼涉及很多其他的細節,這里的代碼是經過簡化之后的,只保留了 patchFlag 相關的邏輯。

  1. export function buildProps( 
  2.   node: ElementNode, 
  3.   context: TransformContext, 
  4.   props: ElementNode['props'] = node.props 
  5. ) { 
  6.   let patchFlag = 0 
  7.   for (let i = 0; i < props.length; i++) { 
  8.     const prop = props[i] 
  9.     const [keyname] = prop.name.split(':'
  10.     if (key === 'v-bind' || key === '') { 
  11.       if (name === 'class') { 
  12.        // 如果包含 :class 屬性,patchFlag | CLASS 
  13.         patchFlag |= PatchFlags.CLASS 
  14.       } else if (name === 'style') { 
  15.        // 如果包含 :style 屬性,patchFlag | STYLE 
  16.         patchFlag |= PatchFlags.STYLE 
  17.       } 
  18.     } 
  19.   } 
  20.  
  21.   return { 
  22.     patchFlag 
  23.   } 

上面的代碼只展示了三種 patchFlag 的類型:

  • 節點只有一個文本子節點,且該文本包含動態的數據(TEXT = 1)
  1. <p>name: {{name}}</p> 
  • 節點包含可變的 class 屬性(CLASS = 1 << 1)
    1. <div :class="{ active: isActive }"></div> 

節點包含可變的 style 屬性(STYLE = 1 << 2)

  1. <div :style="{ color: color }"></div> 

可以看到 PatchFlags 都是數字 1 經過 左移操作符 計算得到的。

  1. export const enum PatchFlags { 
  2.   TEXT = 1,             // 1, 二進制 0000 0001 
  3.   CLASS = 1 << 1,       // 2, 二進制 0000 0010 
  4.   STYLE = 1 << 2,       // 4, 二進制 0000 0100 
  5.   PROPS = 1 << 3,       // 8, 二進制 0000 1000 
  6.   ... 

從上面的代碼能看出來,patchFlag 的初始值為 0,每次對 patchFlag 都是執行 | (或)操作。如果當前節點是一個只有動態文本子節點且同時具有動態 style 屬性,最后得到的 patchFlag 為 5(二進制:0000 0101)。

  1. <p :style="{ color: color }">name: {{name}}</p> 

我們將上面的代碼放到 Vue3 中運行:

  1. const app = Vue.createApp({ 
  2.   data() { 
  3.     return { 
  4.       color: 'red'
  5.       name'shenfq' 
  6.     } 
  7.   }, 
  8.   template: `<div> 
  9.    <p :style="{ color: color }">name: {{name}}</p> 
  10.   </div>` 
  11. }) 
  12.  
  13. app.mount('#app'

最后生成的 render 方法如下,和我們之前的描述基本一致。

function render() {}

render 優化

Vue3 在虛擬 DOM Diff 時,會取出 patchFlag 和需要進行的 diff 類型進行 &(與)操作,如果結果為 true 才進入對應的 diff。

patchFlag 判斷

還是拿之前的模板舉例:

  1. <p :style="{ color: color }">name: {{name}}</p> 

如果此時的 name 發生了修改,p 節點進入了 diff 階段,此時會將判斷 patchFlag & PatchFlags.TEXT ,這個時候結果為真,表明 p 節點存在文本修改的情況。

patchFlag

  1. patchFlag = 5 
  2. patchFlag & PatchFlags.TEXT 
  3. // 或運算:只有對應的兩個二進位都為1時,結果位才為1。 
  4. // 0000 0101 
  5. // 0000 0001 
  6. // ------------ 
  7. // 0000 0001  =>  十進制 1 
  1. if (patchFlag & PatchFlags.TEXT) { 
  2.   if (oldNode.children !== newNode.children) { 
  3.     // 修改文本 
  4.     hostSetElementText(el, newNode.children) 
  5.   } 

但是進行 patchFlag & PatchFlags.CLASS 判斷時,由于節點并沒有動態 Class,返回值為 0,所以就不會對該節點的 class 屬性進行 diff,以此來優化性能。

patchFlag

  1. patchFlag = 5 
  2. patchFlag & PatchFlags.CLASS 
  3. // 或運算:只有對應的兩個二進位都為1時,結果位才為1。 
  4. // 0000 0101 
  5. // 0000 0010 
  6. // ------------ 
  7. // 0000 0000  =>  十進制 0 

總結

其實 Vue3 相關的性能優化有很多,這里只單獨將 patchFlag 的十分之一的內容拿出來講了,Vue3 還沒正式發布的時候就有看到說 Diff 過程會通過 patchFlag 來進行性能優化,所以打算看看他的優化邏輯,總的來說還是有所收獲。

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

 

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

2021-01-15 05:16:37

Vue3開源代碼量

2021-12-01 08:11:44

Vue3 插件Vue應用

2020-09-14 08:56:30

Vue模板

2025-07-07 03:00:00

2021-11-30 08:19:43

Vue3 插件Vue應用

2023-11-28 09:03:59

Vue.jsJavaScript

2025-08-12 09:13:03

2025-07-03 09:36:35

2021-12-02 05:50:35

Vue3 插件Vue應用

2024-07-26 08:50:57

2020-09-19 21:15:26

Composition

2021-12-08 09:09:33

Vue 3 Computed Vue2

2021-05-12 08:57:56

項目搭建工具

2025-10-17 07:10:00

前端開發Vue

2025-11-19 08:23:42

2025-01-20 00:00:06

Vue開發工具庫

2025-05-06 09:35:00

2022-06-21 12:09:18

Vue差異

2021-11-16 08:50:29

Vue3 插件Vue應用

2021-05-26 10:40:28

Vue3TypeScript前端
點贊
收藏

51CTO技術棧公眾號

欧美亚洲综合在线| 国产欧美熟妇另类久久久| 亚洲va天堂va欧美ⅴa在线| 美女一区二区在线观看| 日本中文字幕一区二区视频 | 亚洲区一区二区三区| 亚洲最大成人综合网| 国产ktv在线视频| 91精品国产视频| 在线观看亚洲一区| 久久伊人一区| 日韩av一二三区| 亚洲综合色婷婷在线观看| 国产精品国产三级国产普通话99 | 手机看片久久| 本田岬高潮一区二区三区| 久久精品国产视频| 亚洲免费黄色网| eeuss影院在线观看| 欧美一区=区| 日韩精品视频在线播放| 国产freexxxx性播放麻豆| 国产深喉视频一区二区| 亚洲女同在线| 欧美成人精品在线播放| а 天堂 在线| 成人在线观看免费网站| 狠狠久久亚洲欧美| 不卡中文字幕av| 无码国产精品久久一区免费| 欧美xxxx做受欧美88bbw| 国产成人aaa| 久久免费视频网| bl动漫在线观看| 日本乱码一区二区三区不卡| 91免费观看在线| 国产成人精品一区二区在线| 成人小视频免费看| 久久91视频| 亚洲欧洲成人av每日更新| 96sao精品视频在线观看| 乱h高h女3p含苞待放| 久久免费精品| 亚洲第一精品在线| 免费日韩av电影| www天堂在线| 一本色道88久久加勒比精品| 亚洲人成网7777777国产| 国产精品人人爽人人爽| 国产鲁鲁视频在线观看特色| 国产不卡一区视频| 91免费高清视频| 日韩av黄色片| 狠狠干成人综合网| 亚洲区免费影片| 亚洲黄色在线网站| 青草综合视频| 亚洲国产精品久久一线不卡| 中国 免费 av| 色视频免费在线观看| 蜜乳av一区二区| 久久久免费av| 国产污视频在线观看| 精品日韩免费| 精品日韩一区二区| 青青草av网站| 免费男女羞羞的视频网站在线观看 | 欧美日韩国产一中文字不卡| 婷婷四月色综合| www日本高清视频| 国产不卡视频在线观看| 成人欧美一区二区三区视频xxx| 丁香六月婷婷综合| 亚洲九九视频| 国产小视频国产精品| 性鲍视频在线观看| 国产一区一一区高清不卡| 亚洲精品福利视频网站| 色播五月综合| а√中文在线8| 亚洲午夜电影网| 天天成人综合网| 91cn在线观看| 国产精品女人毛片| 精品一区久久久久久| 国产精品久久久久久久成人午夜 | 亚洲色成人www永久在线观看 | www.四虎精品| 国产精品久久久久久妇女| 亚洲综合自拍偷拍| 亚洲黄色一区二区三区| av在线麻豆| 欧美性色xo影院| 国产极品尤物在线| 日本无删减在线| 亚洲视频每日更新| 亚洲天堂电影网| 伊人在我在线看导航| 午夜亚洲国产au精品一区二区| 中文字幕一区二区三区在线乱码| 视频在线观看你懂的| 成人毛片在线观看| 97超级在线观看免费高清完整版电视剧| 九九热最新视频| 午夜亚洲伦理| 成人日韩在线电影| 91片黄在线观看喷潮| 美腿丝袜亚洲综合| 国产精品久久亚洲| 噜噜噜久久,亚洲精品国产品| 国产精品中文有码| 3d精品h动漫啪啪一区二区| 日韩精品一二| 一区二区三区.www| 亚洲老女人av| 日韩黄色碟片| 国产视频欧美视频| 无码人妻精品一区二区中文| 免费看av成人| 国产亚洲激情在线| 精品一区二区三区人妻| 亚洲理论在线| 欧美一级视频在线观看| 伊人中文字幕在线观看| 久久综合九色综合欧美狠狠| 国产精品激情av在线播放| 一区二区乱子伦在线播放| 日本91福利区| 久久久久九九九| 黄色片免费在线| 欧美极品xxx| 一区二区视频在线免费| 中文字幕不卡三区视频| 日本高清免费不卡视频| 久久撸在线视频| 久久久久九九精品影院| 一本一本久久a久久精品牛牛影视| 黄色av免费播放| 欧美一级网站| 欧美日韩精品免费观看视一区二区| 伦理片一区二区三区| 国产欧美精品区一区二区三区 | 亚洲国产美女视频| 精品日韩欧美一区| 欧美一区二区大胆人体摄影专业网站| 成 人片 黄 色 大 片| 一区二区中文字幕在线| 黄色手机在线视频| 99re久久最新地址获取| 久久精品这里热有精品| 成人一级免费视频| 国产欧美日韩另类一区| 亚洲一区二区蜜桃| 久久美女视频| 国产在线精品播放| 欧美 日韩 国产 精品| 久久久久九九视频| 在线观看成人免费| 亚洲美女久久精品| 欧美一级视频精品观看| 91视频在线网站| 欧美 日韩 国产 一区| 5278欧美一区二区三区| 香蕉视频免费在线看| 1000部国产精品成人观看| av污在线观看| 欧美一区精品| 国产专区一区二区| 黄色网址在线免费观看| 777a∨成人精品桃花网| 大又大又粗又硬又爽少妇毛片| 99热这里只有成人精品国产| 蜜桃麻豆www久久国产精品| 日韩一区二区三区免费| 欧美精品一区二区三区很污很色的| 在线免费观看麻豆| 日韩成人免费电影| 精品国产乱码久久久久久久软件| 天堂8中文在线最新版在线| 亚洲欧洲一区二区三区久久| 亚洲一区二区激情| 久久婷婷综合激情| 日韩人妻无码精品久久久不卡| 精品成人自拍视频| 国产激情999| 婷婷av在线| 日韩精品视频在线播放| 亚洲天堂男人网| 亚洲午夜日本在线观看| 亚洲色成人网站www永久四虎| 国精产品一区一区三区mba视频 | 久久久精品视频免费观看| 99久久伊人久久99| 黄色一级片黄色| 国产一区二区三区免费在线| 中文字幕国产亚洲| 男人天堂视频在线| 亚洲激情欧美激情| 老熟妇一区二区| 丁香天五香天堂综合| 天天干天天干天天干天天干天天干| 亚洲欧美亚洲| 手机在线观看国产精品| 超碰cao国产精品一区二区| 久久6精品影院| 国产成人精品一区二区无码呦 | 日韩不卡中文字幕| 国产又粗又猛又黄又爽| 一本色道a无线码一区v| 国产精品无码网站| 国产精品亚洲成人| 国产成人黄色网址| 午夜亚洲视频| 日韩黄色短视频| 亚洲精品在线观看91| 色爱区成人综合网| 天天躁日日躁狠狠躁欧美巨大小说 | 成人一级片免费看| 久久精品免费观看| 欧美性受xxxx黑人猛交88| 免费一区二区三区视频导航| 99在线热播| 大桥未久在线视频| 理论片在线不卡免费观看| 成年人在线观看| 精品亚洲一区二区| 日本高清视频www| 日韩欧美国产不卡| 五月天婷婷综合网| 国产亚洲一区二区三区在线观看| 污污的网站18| 男女精品视频| 亚洲一区影院| 欧美少妇xxxx| 91丝袜脚交足在线播放| 免费成人毛片| 国产精品入口免费视| 成人福利在线观看视频| 日韩专区中文字幕| 日本精品一区二区在线观看| 91精品国产综合久久香蕉的特点 | 欧美精品资源| 国产国语videosex另类| 电影一区二区| 国产欧美一区二区白浆黑人| 国产成人精品一区二区三区视频| 国产成人+综合亚洲+天堂| 日韩欧美精品一区二区三区| 性亚洲最疯狂xxxx高清| аⅴ资源新版在线天堂| 亚洲人成网在线播放| 春暖花开成人亚洲区| 国产亚洲精品va在线观看| 第三区美女视频在线| 精品欧美一区二区在线观看| 午夜精品久久久久久久99热黄桃 | 伊人影院在线视频| 欧美日韩成人在线观看| 久久99亚洲网美利坚合众国| 欧美激情精品久久久久久久变态| 青青草视频在线观看| 国产网站欧美日韩免费精品在线观看| 天天摸天天碰天天爽天天弄| 欧美日韩免费一区二区三区| 国产真实乱偷精品视频| 婷婷开心久久网| 国产日韩欧美在线观看视频| 亚洲精选一二三| 五月婷六月丁香| 成人欧美一区二区三区黑人麻豆| 日本福利片在线观看| 一区二区三区高清不卡| 久久国产精品免费看| 一区二区在线观看免费| 国产主播在线观看| 色婷婷久久一区二区三区麻豆| wwwwww在线观看| 9191精品国产综合久久久久久| 国产又粗又黄又爽视频| 精品乱码亚洲一区二区不卡| 视频一区二区三区在线看免费看| 国产一区二区精品丝袜| 黄色网址在线免费| 欧美亚洲日本黄色| 亚洲青青久久| 国产噜噜噜噜久久久久久久久| 午夜激情电影在线播放| 国产精品网址在线| 国产毛片久久久| 丁香婷婷久久久综合精品国产 | 国产美女一区二区| 99热这里只有精品在线播放| 国产一区二区不卡在线| 丰满少妇在线观看资源站| 99视频有精品| 亚洲色图100p| 国产精品久久福利| 国产精品111| 欧洲精品一区二区| 欧美在线 | 亚洲| 色av中文字幕一区| 麻豆网站在线免费观看| xxxxx成人.com| 欧美日韩国产观看视频| 成人淫片在线看| 久久综合欧美| 丰满少妇久久久| 最新日韩欧美| 久久精品久久99| 国产一区二区日韩精品| 白白色免费视频| 午夜久久电影网| 国产伦子伦对白视频| 亚洲偷熟乱区亚洲香蕉av| 1234区中文字幕在线观看| 久久久久久中文| 天堂电影一区| 97视频中文字幕| 99久久亚洲精品| 亚洲成色www.777999| 91在线精品一区二区三区| 无遮挡aaaaa大片免费看| 亚洲精品日产精品乱码不卡| 99re热视频| 亚洲丝袜在线视频| 竹内纱里奈兽皇系列在线观看| 国产精品毛片va一区二区三区| 99久久亚洲精品蜜臀| 国产野外作爱视频播放| 久久亚洲欧美国产精品乐播 | 亚洲精品乱码久久久久久久久久久久| 亚洲va韩国va欧美va| 亚洲欧美另类视频| 久热精品视频在线免费观看 | 欧美一区二区人人喊爽| 日本三级视频在线播放| 美女精品久久久| 91嫩草国产线观看亚洲一区二区| 午夜精品福利一区二区| 日韩国产高清在线| 欧美激情亚洲色图| 欧美最猛性xxxxx直播| 欧美高清成人| 日韩美女免费线视频| 精品国产第一国产综合精品| 一本一本a久久| 精品一区二区三区的国产在线播放| 久久久久亚洲av无码专区首jn| 日韩一区在线免费观看| 91片黄在线观看喷潮| 欧美成人高清视频| **爰片久久毛片| 福利视频一二区| 精久久久久久久久久久| 极品魔鬼身材女神啪啪精品| 欧美日韩免费在线| 日韩在线免费看| 国产精品igao视频| 日韩88av| jizzjizzxxxx| 国产精品一区二区不卡| 青娱乐国产精品| 欧美日韩综合不卡| 五月天婷婷视频| 日韩av电影国产| 日韩欧美一区免费| 国产精品久久久久久久99| 亚洲最色的网站| 欧美孕妇性xxxⅹ精品hd| 国产精品美腿一区在线看| 久久一区二区三区电影| 人妻少妇偷人精品久久久任期| 国产亚洲精品中文字幕| 中文字幕在线视频第一页| 亚洲精品久久7777777| 自由的xxxx在线视频| 国产精品三区在线| 久久一区国产| 91视频最新网址| 亚洲高清久久网| 国产探花视频在线观看| 91免费高清视频| 一本一本久久| 国产传媒视频在线| 欧美成人一区二区三区片免费 | 91香蕉亚洲精品| 亚洲欧洲日本mm| 国精产品一区一区| 亚洲第一网站免费视频| 国产日本久久| 精品国产一区三区| 中文字幕一区三区| 日韩中文字幕观看| 91精品国产综合久久久久久久久| 精品福利电影| 韩国三级hd中文字幕有哪些| 欧美午夜激情在线| 亚洲七七久久综合桃花剧情介绍| 欧美日韩电影一区二区三区| 国产精品综合av一区二区国产馆|