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

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

Vue2模版編譯流程詳解

瀏覽:4日期:2022-06-13 09:13:36
目錄1、起步項目結構App.vuewebpack.config.js打包構建vue-loader 源碼template-loader2、模板編譯流程parseHTML 階段genElement 階段compilerToFunction 階段parseHTML 階段genElement 階段3、總結

為了更好理解 vue 的模板編譯這里我整理了一份模板編譯的整體流程,如下所示,下面將用源碼解讀的方式來找到模板編譯中的幾個核心步驟,進行詳細說明:

1、起步

這里我使用 webpack 來打包 vue 文件,來分析 vue 在模板編譯中的具體流程,如下所示,下面是搭建的項目結構和文件內容:

項目結構├─package-lock.json├─package.json├─src| ├─App.vue| └index.js├─dist| └main.js├─config| ? └webpack.config.jsApp.vue<template> <div id='box'> ? {{ count }} </div></template>?<script>export default { props: {}, data() { ? return { ? ? count: 0 ? } }}</script>?<style scoped>#box { background: red;}</style>webpack.config.jsconst { VueLoaderPlugin } = require('vue-loader')?module.exports = { mode: 'development', module: { ? rules: [ ? ? { ? ? ? test: /.vue$/, ? ? ? loader: 'vue-loader' ? ? }, ? ? // 它會應用到普通的 `.js` 文件 ? ? // 以及 `.vue` 文件中的 `<script>` 塊 ? ? { ? ? ? test: /.js$/, ? ? ? loader: 'babel-loader' ? ? }, ? ? // 它會應用到普通的 `.css` 文件 ? ? // 以及 `.vue` 文件中的 `<style>` 塊 ? ? { ? ? ? test: /.css$/, ? ? ? use: [ ? ? ? ? 'vue-style-loader', ? ? ? ? 'css-loader' ? ? ? ] ? ? } ? ] }, plugins: [ ? new VueLoaderPlugin() ]}

如上 webpack.config.js 所示,webpack 可以通過 vue-loader 識別 vue 文件,vue-loader 是 webpack 用來解析 .vue 文件的 loader,主要作用是將單文件組件(SFC),解析成為 webpack 可識別的 JavaScript 模塊。

打包構建

搭建好整個目錄項目后,執行 npm run build ,會將 vue 文件解析打包成對應的 bundle,并輸出至 dist 目錄下,下面是打包后的產出,對應 App.vue 的產物:

/***/ './src/App.vue'?__webpack_require__.r(__webpack_exports__);/* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ? 'default': () => (__WEBPACK_DEFAULT_EXPORT__) \n/* harmony export */});?var _App_vue_vue_type_template_id_7ba5bd90_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__('./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true&');?var _App_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__( './src/App.vue?vue&type=script&lang=js&');???var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__('./node_modules/vue-loader/lib/runtime/componentNormalizer.js');?var component = (0, _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__['default'])( _App_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__['default'], _App_vue_vue_type_template_id_7ba5bd90_scoped_true___WEBPACK_IMPORTED_MODULE_0__.render, _App_vue_vue_type_template_id_7ba5bd90_scoped_true___WEBPACK_IMPORTED_MODULE_0__.staticRenderFns, false, null, '7ba5bd90', null,/* hot reload */)

從上方的產物可以看出,App.vue 文件被編譯分為三塊,_App_vue_vue_type_template_id_7ba5bd90_scoped_true___WEBPACK_IMPORTED_MODULE_0__ 、 _App_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__,_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__,這三個模塊恰好對應vue模板中的 template、script、style這三個標簽的模板內容,所以得出結論:vue-loader 會將 vue 模板中的template、script、style 標簽內容分解為三個模塊。 為此,我找到 vue-loader 的源碼,下面分析其源碼邏輯:

vue-loader 源碼

源碼里很清楚的可以看到 vue-loader 使用了 vue/compiler-sfc 中的 parse 方法對 vue 的源文件進行的解析,將模板語法解析為一段可描述的對象

module.exports = function (source) { // 這里就是.vue文件的AST const loaderContext = this? ? ... // 解析.vue原文件,source對應的就是.vue模板 const descriptor = compiler.parse({ ? source, ? compiler: options.compiler || templateCompiler, ? filename, ? sourceRoot, ? needMap: sourceMap })? ? ...? // 使用webpack query source let templateImport = `var render, staticRenderFns` let templateRequest if (descriptor.template) { ? const src = descriptor.template.src || resourcePath ? const idQuery = `&id=${id}` ? const scopedQuery = hasScoped ? `&scoped=true` : `` ? const attrsQuery = attrsToQuery(descriptor.template.attrs) ? // const tsQuery = ? // options.enableTsInTemplate !== false && isTS ? `&ts=true` : `` ? const query = `?vue&type=template${idQuery}${scopedQuery}${attrsQuery}${inheritQuery}` ? const request = (templateRequest = stringifyRequest(src + query)) ? templateImport = `import { render, staticRenderFns } from ${request}` }? ? ...? code += `\nexport default component.exports` return code}

對 descriptor 進行打印,輸出結果如下,vue-loader 對源文件編譯后,vue 模板會被轉化成抽象語法樹(AST),此處便是模板編譯的入口,使用編譯后的 AST 將 vue 模板拆分為 template 、script 和 style 三部分,方便后面 webpack 通過 resourceQuery 匹配分發到各個loader 進行二次解析編譯,template 部分會被 template-loader 進行二次編譯解析,最終生成render 函數。

{ source: '<template>\n' + ? ' <div id='box'>\n' + ? ' ? {{ count }}\n' + ? ' </div>\n' + ? '</template>\n' + ? '\n' + ? '<script>\n' + ? 'export default {\n' + ? ' props: {},\n' + ? ' data() {\n' + ? ' ? return {\n' + ? ' ? ? count: 0\n' + ? ' ? }\n' + ? ' }\n' + ? '}\n' + ? '</script>\n' + ? '\n' + ? '<style>\n' + ? '#box {\n' + ? ' background: red;\n' + ? '}\n' + ? '</style>\n', filename: 'App.vue', template: { ? type: 'template', ? content: '\n<div id='box'>\n {{ count }}\n</div>\n', ? start: 10, ? end: 53, ? attrs: {} }, script: { ? type: 'script', ? content: '\n' + ? ? 'export default {\n' + ? ? ' props: {},\n' + ? ? ' data() {\n' + ? ? ' ? return {\n' + ? ? ' ? ? count: 0\n' + ? ? ' ? }\n' + ? ? ' }\n' + ? ? '}\n', ? start: 74, ? end: 156, ? attrs: {} }, ....}template-loader

template-loader 的作用是將 import { render, staticRenderFns } from "./App.vue?vue&type=template&id=7ba5bd90&" 模塊編譯成 render 函數并導出,以下是編譯產物:

// 編譯前<div id='box'> {{ count }}</div>?// 編譯后var render = function render() { var _vm = this, ? _c = _vm._self._c return _c('div', { attrs: { id: 'box' } }, [ ? _vm._v('\n ' + _vm._s(_vm.count) + '\n'), ])}var staticRenderFns = []render._withStripped = true?export { render, staticRenderFns }

template-loader 核心原理是通過 vue/compiler-sfc 將模板轉換成為 render 函數,并返回 template 編譯產物

module.exports = function (source) { const loaderContext = this ? ... // 接收模板編譯核心庫 const { compiler, templateCompiler } = resolveCompiler(ctx, loaderContext)? ? ...? // 開啟編譯 const compiled = compiler.compileTemplate(finalOptions)? ? ...? // 編譯后產出,code就是render函數 const { code } = compiled? // 導出template模塊 return code + `\nexport { render, staticRenderFns }`}2、模板編譯流程

vue/compiler-sfc 是模板編譯的核心庫,在 vue2.7 版本中使用,而 vue2.7 以下的版本都是使用vue-template-compiler,本質兩個包的功能是一樣的,都可以將模板語法編譯為 JavaScript,接下來我們來解析一下在模板編譯過程中使用的方法:

parseHTML 階段

可以將 vue 文件中的模板語法轉義為 AST,為后續創建 dom 結構做預處理

export function parseHTML(html, options: HTMLParserOptions) { // 存儲解析后的標簽 const stack: any[] = [] const expectHTML = options.expectHTML const isUnaryTag = options.isUnaryTag || no const canBeLeftOpenTag = options.canBeLeftOpenTag || no let index = 0 let last, lastTag // 循環 html 字符串結構 while (html) { // 記錄當前最新html last = html if (!lastTag || !isPlainTextElement(lastTag)) { // 獲取以 < 為開始的位置 let textEnd = html.indexOf('<') if (textEnd === 0) {// 解析注釋if (comment.test(html)) { const commentEnd = html.indexOf('-->') if (commentEnd >= 0) { if (options.shouldKeepComment && options.comment) { options.comment(html.substring(4, commentEnd),index,index + commentEnd + 3 ) } advance(commentEnd + 3) continue }}// 解析條件注釋if (conditionalComment.test(html)) { const conditionalEnd = html.indexOf(']>') if (conditionalEnd >= 0) { advance(conditionalEnd + 2) continue }}// 解析 Doctypeconst doctypeMatch = html.match(doctype)if (doctypeMatch) { advance(doctypeMatch[0].length) continue}// 解析截取結束標簽const endTagMatch = html.match(endTag)if (endTagMatch) { const curIndex = index advance(endTagMatch[0].length) parseEndTag(endTagMatch[1], curIndex, index) continue}// 解析截取開始標簽const startTagMatch = parseStartTag()if (startTagMatch) { handleStartTag(startTagMatch) if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) { advance(1) } continue} } let text, rest, next if (textEnd >= 0) {rest = html.slice(textEnd)while ( !endTag.test(rest) && !startTagOpen.test(rest) && !comment.test(rest) && !conditionalComment.test(rest)) { // < in plain text, be forgiving and treat it as text next = rest.indexOf('<', 1) if (next < 0) break textEnd += next rest = html.slice(textEnd)}text = html.substring(0, textEnd) } // 純文本節點 if (textEnd < 0) {text = html } // 截取文本節點 if (text) {advance(text.length) } if (options.chars && text) {options.chars(text, index - text.length, index) } } else { let endTagLength = 0 const stackedTag = lastTag.toLowerCase() const reStackedTag =reCache[stackedTag] ||(reCache[stackedTag] = new RegExp( '([\s\S]*?)(</' + stackedTag + '[^>]*>)', 'i')) const rest = html.replace(reStackedTag, function (all, text, endTag) {endTagLength = endTag.lengthif (!isPlainTextElement(stackedTag) && stackedTag !== 'noscript') { text = text .replace(/<!--([\s\S]*?)-->/g, '$1') // #7298 .replace(/<![CDATA[([\s\S]*?)]]>/g, '$1')}if (shouldIgnoreFirstNewline(stackedTag, text)) { text = text.slice(1)}if (options.chars) { options.chars(text)}return '' }) index += html.length - rest.length html = rest parseEndTag(stackedTag, index - endTagLength, index) } if (html === last) { options.chars && options.chars(html) break } } // 清空閉合標簽 parseEndTag() // 截取標簽,前后推進位置 function advance(n) { index += n html = html.substring(n) } // 解析開始標簽 function parseStartTag() { const start = html.match(startTagOpen) if (start) { const match: any = {tagName: start[1],attrs: [],start: index } advance(start[0].length) let end, attr while (!(end = html.match(startTagClose)) &&(attr = html.match(dynamicArgAttribute) || html.match(attribute)) ) {attr.start = indexadvance(attr[0].length)attr.end = indexmatch.attrs.push(attr) } if (end) {match.unarySlash = end[1]advance(end[0].length)match.end = indexreturn match } } } // 匹配處理開始標簽 function handleStartTag(match) { const tagName = match.tagName const unarySlash = match.unarySlash if (expectHTML) { if (lastTag === 'p' && isNonPhrasingTag(tagName)) {parseEndTag(lastTag) } if (canBeLeftOpenTag(tagName) && lastTag === tagName) {parseEndTag(tagName) } } const unary = isUnaryTag(tagName) || !!unarySlash const l = match.attrs.length const attrs: ASTAttr[] = new Array(l) for (let i = 0; i < l; i++) { const args = match.attrs[i] const value = args[3] || args[4] || args[5] || '' const shouldDecodeNewlines =tagName === 'a' && args[1] === 'href' ? options.shouldDecodeNewlinesForHref : options.shouldDecodeNewlines attrs[i] = {name: args[1],value: decodeAttr(value, shouldDecodeNewlines) } if (__DEV__ && options.outputSourceRange) {attrs[i].start = args.start + args[0].match(/^\s*/).lengthattrs[i].end = args.end } } if (!unary) { stack.push({tag: tagName,lowerCasedTag: tagName.toLowerCase(),attrs: attrs,start: match.start,end: match.end }) lastTag = tagName } if (options.start) { options.start(tagName, attrs, unary, match.start, match.end) } } // 解析結束標簽 function parseEndTag(tagName?: any, start?: any, end?: any) { let pos, lowerCasedTagName if (start == null) start = index if (end == null) end = index // Find the closest opened tag of the same type if (tagName) { lowerCasedTagName = tagName.toLowerCase() for (pos = stack.length - 1; pos >= 0; pos--) {if (stack[pos].lowerCasedTag === lowerCasedTagName) { break} } } else { // If no tag name is provided, clean shop pos = 0 } if (pos >= 0) { // Close all the open elements, up the stack for (let i = stack.length - 1; i >= pos; i--) {if (__DEV__ && (i > pos || !tagName) && options.warn) { options.warn(`tag <${stack[i].tag}> has no matching end tag.`, { start: stack[i].start, end: stack[i].end })}if (options.end) { options.end(stack[i].tag, start, end)} } // Remove the open elements from the stack stack.length = pos lastTag = pos && stack[pos - 1].tag } else if (lowerCasedTagName === 'br') { if (options.start) {options.start(tagName, [], true, start, end) } } else if (lowerCasedTagName === 'p') { if (options.start) {options.start(tagName, [], false, start, end) } if (options.end) {options.end(tagName, start, end) } } }}genElement 階段

genElement 會將 AST 預發轉義為字符串代碼,后續可將其包裝成 render 函數的返回值

// 將AST預發轉義成render函數字符串export function genElement(el: ASTElement, state: CodegenState): string { if (el.parent) { el.pre = el.pre || el.parent.pre } if (el.staticRoot && !el.staticProcessed) { // 輸出靜態樹 return genStatic(el, state) } else if (el.once && !el.onceProcessed) { // 處理v-once指令 return genOnce(el, state) } else if (el.for && !el.forProcessed) { // 處理循環結構 return genFor(el, state) } else if (el.if && !el.ifProcessed) { // 處理條件語法 return genIf(el, state) } else if (el.tag === 'template' && !el.slotTarget && !state.pre) { // 處理子標簽 return genChildren(el, state) || 'void 0' } else if (el.tag === 'slot') { // 處理插槽 return genSlot(el, state) } else { // 處理組件和dom元素 ... return code }}

通過genElement函數包裝處理后,將vue 模板的 template 標簽部分轉換為 render 函數,如下所示:

const compiled = compiler.compileTemplate({ source: '\n' + '<div id='box'>\n' + ' {{ count }}\n' + ' <button @add='handleAdd'>+</button>\n' + '</div>\n'});const { code } = compiled;// 編譯后var render = function render() { var _vm = this, _c = _vm._self._c return _c('div', { attrs: { id: 'box' } }, [ _vm._v('\n ' + _vm._s(_vm.count) + '\n '), _c('button', { on: { add: _vm.handleAdd } }, [_vm._v('+')]), ])}var staticRenderFns = []render._withStripped = truecompilerToFunction 階段

將 genElement 階段編譯的字符串產物,通過 new Function將 code 轉為函數

export function createCompileToFunctionFn(compile: Function): Function { const cache = Object.create(null) return function compileToFunctions( template: string, options?: CompilerOptions, vm?: Component ): CompiledFunctionResult { ... // 編譯 const compiled = compile(template, options) // 將genElement階段的產物轉化為function function createFunction(code, errors) { try {return new Function(code) } catch (err: any) {errors.push({ err, code })return noop } } const res: any = {} const fnGenErrors: any[] = [] // 將code轉化為function res.render = createFunction(compiled.render, fnGenErrors) res.staticRenderFns = compiled.staticRenderFns.map(code => { return createFunction(code, fnGenErrors) }) ... }}

為了方便理解,使用斷點調試,來看一下 compileTemplate 都經歷了哪些操作:

首先會判斷是否需要預處理,如果需要預處理,則會對 template 模板進行預處理并返回處理結果,此處跳過預處理,直接進入 actuallCompile 函數

這里可以看到本身內部還有一層編譯函數對 template 進行編譯,這才是最核心的編譯方法,而這個 compile 方法來源于 createCompilerCreator

createCompilerCreator 返回了兩層函數,最終返回值則是 compile 和 compileToFunction,這兩個是將 template 轉為 render 函數的關鍵,可以看到 template 會被解析成 AST 樹,最后通過 generate 方法轉義成函數 code,接下來我們看一下parse函數中是如何將 template 轉為 AST 的。

繼續向下 debug 后,會走到 parseHTML 函數,這個函數是模板編譯中用來解析 HTML 結構的核心方法,通過回調 + 遞歸最終遍歷整個 HTML 結構并將其轉化為 AST 樹。

parseHTML 階段

使用 parseHTML 解析成的 AST 創建 render 函數和 Vdom

genElement 階段

將 AST 結構解析成為虛擬 dom 樹

最終編譯輸出為 render 函數,得到最終打包構建的產物。

3、總結

到此我們應該了解了 vue 是如何打包構建將模板編譯為渲染函數的,有了渲染函數后,只需要將渲染函數的 this 指向組件實例,即可和組件的響應式數據綁定。vue 的每一個組件都會對應一個渲染 Watcher ,他的本質作用是把響應式數據作為依賴收集,當響應式數據發生變化時,會觸發 setter 執行響應式依賴通知渲染 Watcher 重新執行 render 函數做到頁面數據的更新。

以上就是Vue2模版編譯流程詳解的詳細內容,更多關于Vue2模版編譯的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
主站蜘蛛池模板: 999在线观看精品免费不卡网站 | 欧美国产一区二区 | 七七婷婷婷婷精品国产 | 欧美午夜一区二区三区免费大片 | 69av在线视频 | 亚洲风情在线观看 | 国产3区 | 国产美女网站视频 | 欧美第一页 | 中文字幕一区二区三区四区 | 一级毛片免费 | 国产99一区| 久久99久久98精品免观看软件 | jlzzxxxx18hd护士 | 久久国产精品无码网站 | 在线观看黄 | 欧美福利视频 | 国产视频一区二区三区四区 | 国产成人欧美一区二区三区的 | 在线观看黄色大片 | 欧美精品一区二 | 国产日韩欧美精品一区二区 | 亚洲一区二区三区四区五区中文 | 欧美a级在线观看 | 成年人视频在线观看免费 | 少妇性l交大片免费一 | 成人免费在线看片 | 九九热精品视频 | 一区在线视频 | 欧美日韩大片在线观看 | 国产日韩欧美 | 欧美日韩激情 | 国产福利91精品一区二区 | 中文字幕99 | 蜜桃精品久久久久久久免费影院 | 欧美日韩三级在线 | 精品美女久久久 | 在线成人免费观看www | 久久精品亚洲精品国产欧美kt∨ | 国产在线播 | 亚洲人成在线播放 | 欧美一级片在线观看 | 羞羞视频在线观免费观看 | 日本黄色免费大片 | 日韩在线精品强乱中文字幕 | 亚洲久久久 | 欧美精品一区二区三区四区在线 | 日韩一区二区在线视频 | 精品欧美一区二区在线观看 | 91久久国产综合久久 | 99国产精品| 国产精品一区在线看 | 国产精品一区人伦免视频播放 | 三级色网站 | 亚洲一区二区在线视频 | 一区二区三区四区免费 | 奇米影视四色777me | 精品一区av | 国产成人久久 | 国产激情精品一区二区三区 | 国产女人和拘做受视频 | 免费福利视频一区二区三区 | 亚洲人成一区 | 一区在线视频 | 伊人激情av一区二区三区 | 五月网婷婷| 国产精品毛片无码 | 亚洲高清精品视频 | 欧美日韩欧美日韩 | 精品乱码久久久 | 久久精品小视频 | 国产免费观看一区二区三区 | 国家aaa的一级看片 操操操夜夜操 | 91久久国产综合久久 | 成人在线观看av | 久久久久久久免费 | 国产精品色 | 亚洲国产精品自拍 | 久久国产欧美日韩精品 | 久久久久国产精品免费免费搜索 | 久久一区 | 亚洲日本乱码一区两区在线观看 | 午夜免费福利视频 | 日韩av网页 | 成人免费在线观看视频 | 99久久婷婷| 操到爽| 一区二区三区不卡视频 | 国产成人精品免费视频大全最热 | 91精品国产乱码久久久久久久久 | 国产亚洲一区二区三区 | 一区二区不卡 | 欧美日韩一区二区在线 | 午夜a级理论片915影院 | 日本三级视频 | 99久久免费精品国产男女性高好 | 欧美日韩视频一区二区 | 天堂亚洲 | 欧美精品xx | 国产日韩一区二区 | 91av免费在线观看 | 国产精久| 精品日韩一区二区 | 9色网站 | 91福利网站在线观看 | av片免费 | 玖玖操| 精品国偷自产在线 | 国产精品毛片久久久久久久 | 日韩国产欧美一区 | 国外成人在线视频网站 | 色先锋av资源中文字幕 | 国产一区二区综合 | 亚洲国产精品va在线看黑人 | 黄p在线看 | 二区欧美| 国产永久免费 | 中文字幕精品一区 | 欧美二区三区视频 | 日韩不卡一二三 | 伊人久操| 国产综合精品一区二区三区 | 人人干网站 | 国产成人在线一区二区 | 国产精选一区二区三区不卡催乳 | 国产老头老太作爱视频 | 日韩成人精品在线 | 国产1区2区3区 | 日韩av在线不卡 | av在线成人 | 在线亚洲一区二区 | 欧美日韩一二区 | 玖色视频 | 国产91在线免费观看 | 午夜男人网 | 欧美日韩在线视频免费 | 亚洲精品一区二区三区 | 国产精品一区二区三区在线免费观看 | 成人在线播放 | 欧美激情视频一区二区三区 | 日韩欧美在线视频 | 午夜噜噜噜 | 亚洲成人免费在线 | 成年人精品视频在线观看 | 欧美激情在线精品一区二区三区 | 伊人电影综合网 | 日韩欧美在线观看一区二区三区 | 99国产精品 | 亚洲网站在线免费观看 | 日韩福利在线观看 | 色吊丝2288sds中文字幕 | 国产美女精品视频免费观看 | 999国产一区二区三区四区 | 999久久久 | 日韩视频在线观看一区 | 欧美精品v国产精品v日韩精品 | 中文乱码一区 | 欧美一区二区三区aa大片漫 | 日韩在线播放一区 | 日韩欧美综合 | 天天操网址 | 欧美日韩一区二区三区四区 | 在线观看第一页 | 毛片a片| 成人精品视频免费 | 色视频免费在线观看 | 久久国产精品久久久久久 | 精品一区二区久久久久久久网站 | 日本久久综合 | 亚洲一区二区三区四区的 | 亚洲国产精品精华液com | 欧美综合激情 | 综合色综合 | 精品影院 | 成人午夜sm精品久久久久久久 | 黄色大片视频网站 | 亚洲九九 | 亚洲永久 | 成人网在线观看 | 欧美日韩免费一区二区三区 | 毛片网页| 日韩中文字幕一区二区 | 日韩欧美在线观看一区 | 在线观看视频91 | 欧美1级 | 国产精品18久久久 | avmans最新导航地址 | 免费观看av毛片 | 国产三级精品在线 | 99久久婷婷国产综合精品电影 | 久久国产精品免费一区二区三区 | 亚洲国产精品视频 | 国产va| 国产精品久久久久久福利一牛影视 | 日本综合久久 | 激情福利视频 | 国产精品毛片一区二区在线看 | 91视频在线免费观看 | 日韩成人在线免费视频 | 欧美日韩在线精品 | 成人无遮挡毛片免费看 | 欧美视频一二 | 成人av电影网址 | 国产精品观看 | 国产日韩欧美91 | 免费一二二区视频 | 午夜爱爱毛片xxxx视频免费看 | 欧美成在线观看 | 国产在线专区 | 欧美午夜视频 | 在线看亚洲 | 日韩亚洲精品在线观看 | 久久成人免费视频 | 精品国产乱码久久久久久88av | 色毛片 | 久久久久一区 | 欧美,日韩,国产精品免费观看 | 国产精品久久久久国产a级 99精品欧美一区二区三区综合在线 | 青青久视频 | 亚州中文字幕蜜桃视频 | 婷婷激情在线 | 欧美日韩在线播放 | 特级理论片 | 日韩蜜桃 | 久热久爱 | 黄色一级大片在线免费看产 | 亚洲视频在线观看 | 亚洲欧美一区二区三区在线 | 日韩综合在线 | 午夜影院免费看 | 国产精品一区二区在线观看 | 久久无码精品一区二区三区 | 欧洲亚洲精品久久久久 | 国产在线小视频 | 国产成人精品午夜视频' | 人人操日日干 | 亚州视频在线 | 国产成人欧美一区二区三区的 | 丰满少妇久久久久久久 | 久久久久久久中文 | aaa大片免费观看 | 黄的视频网站 | 成人免费一区二区三区视频网站 | 这里有精品视频 | 成人片免费看 | 国产欧美日本 | 婷婷免费在线观看 | 精品免费国产 | 欧美日韩视频在线观看一区 | 成人区一区二区三区 | www,99热| 久草院线 | 美女国产| 不卡在线 | 欧美色综合一区二区三区 | 国产欧美精品一区二区 | 男人天堂社区 | 亚洲 欧美 日韩在线 | 欧美一级在线观看 | 国产精品a免费一区久久电影 | 成人午夜在线观看 | 亚洲一区二区在线播放 | 女男羞羞视频网站免费 | 亚洲二区在线 | 国产高清av在线一区二区三区 | 龙珠z国语版291集全 | 成人免费影院 | 欧美亚洲视频在线观看 | 欧美精品1 | 视频精品一区 | 日韩电影一区二区三区 | 亚洲午夜免费视频 | 国产精品欧美一区二区三区 | 国精品一区| 99久久99| 久久综合亚洲 | 日日夜夜av | 日韩成人中文字幕 | 九九热在线免费视频 | 久久亚洲精品国产一区 | 成人免费精品 | 人人草在线观看视频 | 精品一区视频 | 久久久性色精品国产免费观看 | 亚洲www啪成人一区二区 | 中国av在线| 综合二区| xxxx午夜| 操操操av| 福利网址 | 精品国产91乱码一区二区三区 | 小泽玛丽娅| 国产男人的天堂 | 国产精品高潮呻吟av久久4虎 | 韩国一区二区视频 | 91精品视频在线播放 | 欧美一级片在线观看 | 日韩成人av在线 | 亚洲免费在线视频 | 成人av电影网址 | 色欧美视频 | 欧美淫视频| 日韩国产欧美视频 | 91视频观看| 成人激情视频在线观看 | 久久精品在线 | 日韩a在线 | ririsao久久精品一区 | 99久久国产综合精品女不卡 | 91社区在线播放 | 在线精品观看 | 久久99国产精品久久99大师 | 欧美国产精品一区 | 一区二区三区高清 | 91精品欧美久久久久久久 | 久久综合香蕉 | 亚洲一区二区三区蜜桃 | 亚洲国产精品99久久久久久久久 | 亚洲高清在线观看 | 亚洲国产欧美一区二区三区久久 | 久久免费精品 | 天天操操| 欧美三级电影在线观看 | 操久久 | 性培育学校羞耻椅子调教h 欧美精品网站 | 国产高清视频在线 | 欧美一级高清在线 | 亚洲大片免费观看 | 国产福利视频在线观看 | 亚洲蜜臀av乱码久久精品蜜桃 | 国产黄色av| 不卡欧美 | 成人免费xxxxx在线视频软件 | 波多野结衣一区二区三区高清 | 国产传媒毛片精品视频第一次 | 日韩免费| 国产一区二区三区免费 | 一区二区不卡视频在线观看 | 一区二区免费播放 | 日韩国产高清在线 | 欧美性猛片aaaaaaa做受 | 亚洲国产精品一区二区久久,亚洲午夜 | 国产在线视频网站 | 操久在线 | 国产精品成人国产乱一区 | 黑人精品xxx一区一二区 | 久久91| 亚洲综合一二区 | 一区二区三区在线 | 欧 | 一级篇| 黄色片网站视频 | 中文字幕在线视频免费播放 | 黄色一级大片在线免费看产 | 欧美激情视频一区二区三区在线播放 | 久久一区二区三 | 一区二区三区免费视频网站 | 成人午夜影院 | 亚洲国产精品99久久久久久久久 | 日韩精品免费在线视频 | 日韩三区| 一级黄色录像视频 | 亚洲成人精品视频 | 亚洲视频一区二区 | 91视频免费播放 | 日韩亚洲视频在线观看 | 国产一区二区在线免费 | 伊人伊人 | 免费在线观看一级毛片 | 国产成人在线一区二区 | 91久久 | 日韩一级免费在线观看 | 狠狠狠干 | 四虎最新影视 | 亚洲第一av | 自拍偷拍视频网站 | 男女午夜网站 | 欧美激情国产日韩精品一区18 | 日韩久久久久久 | 精品久久久久久久久久久久 | 欧美精品一区二区三区在线播放 | 国产第一区二区三区 | 日本精品免费 | 国产一区二区三区视频 | 国产精品91久久久久 | 午夜视频在线观看网站 | 国产高清视频一区 | av免费观看网站 | 一级毛片视频播放 | 日本三级一区二区 | 国产精品中文字幕在线观看 | 视频在线一区 | 成人免费福利视频 | 中文字幕免费看 | 黑人一级片视频 | 国产成人精品无人区一区 | 久久婷婷国产麻豆91天堂 | 久久丝袜| 国产精选一区二区 | 国产在线观看一区二区三区 | 国产999精品久久久影片官网 | 精品一区二区三区免费毛片 | 久久精品国产99精品国产亚洲性色 | 亚洲久草视频 | 欧美精产国品一二三区 | 在线观看成人网 | 国产精品久久久久久久久久99 | 国产欧美综合一区二区三区 | 91麻豆精品国产91久久久资源速度 | 中文字幕在线一区 | 国产在线成人 | 国产区在线观看 | 一级毛片在线播放 | 国产精品伦理一区 | 亚洲国产精品成人综合色在线婷婷 | 在线观看中文字幕亚洲 | 精品在线一区二区三区 | 亚洲小视频| 亚洲一区二区三区免费视频 | 亚洲欧美久久久 | 日韩视频免费在线观看 | 夜本色| 在线免费观看激情视频 | 中文字幕在线观看亚洲 | 国产福利在线观看视频 | 国产伦精品一区二区三区四区视频 | 国产精品久久久久久久久久久久冷 | 天天舔天天干 | 在线观看毛片网站 | 日韩福利在线 | 久久亚洲一区 | 可以在线观看的av网站 | 日韩在线资源 | 久久久精品网站 | 波多野结衣一区二区三区高清 | 国产综合精品一区二区三区 | 精品国产乱码久久久久久1区二区 | 97人人干| 国产日韩欧美一区二区 | 中文字幕亚洲一区 | 狠狠爱天天干 | 精品国产一区二区三区久久影院 | 日韩一区二区在线视频 | 天天插天天 | 日韩成人小视频 | 亚洲国产一区二区在线 | 国产成人综合网 | 久久成人国产 | 久久99精品久久久久子伦 | 天堂资源网 | 国产亚洲在线 | 国产精品一区二区视频 | 在线看片网站 | 久久成人综合 | 国产精品久久久999 成人亚洲视频 | 欧美成人影院在线 | 日韩成人影院在线观看 | 在线一区观看 | 97成人在线 | 操操操操操操操操操操操操操操 | 亚洲精品色 | 久久国产成人 | 国产乱a视频在线 | 日本在线视频观看 | 4hu网站| 国产福利一区二区三区视频 | 亚洲欧美日韩国产 | 免费看的毛片 | 亚洲国产日韩a在线播放性色 | 高清国产一区二区三区 | 日本一区二区三区四区 | 国产羞羞视频 | 欧美精品一区二区三区四区在线 | 97碰碰碰免费公开在线视频 | 狠狠操麻豆| 国产一级黄色大片 | 精品视频久久 | 国产香蕉视频在线播放 | 日韩中文在线观看 | 日韩免费在线观看视频 | 中文字幕日韩一区二区三区 | 日韩中文字幕免费在线播放 | 国产精品久久久久久妇女6080 | 羞羞视频在线网站观看 | 99视频精品在线 | 亚洲成人av在线 | 婷婷久久综合 | 中文字幕国产 | 亚洲网站久久 | 国产中文字幕在线观看 | 久久国产精品视频 | 国产精品一区二区三区四区 | 夜夜骑天天操 | 亚洲一区二区在线 | 中文字幕av一区 | 国产一区免费视频 | 国产精品入口久久 | 久久国产香蕉视频 | 欧美日日 | 色吊丝在线永久观看最新版本 | 国产精品久久国产精麻豆99网站 | 中文字幕日韩欧美一区二区三区 | 精品国产一区二区三区小蝌蚪 | 毛片黄片| 欧美日韩综合精品 | 欧美性猛交一区二区三区精品 | 精品久久久久久久久久久久 | 日韩中文字幕电影在线观看 | 成人在线观 | 97国产精品视频人人做人人爱 | 国产精品网站在线观看 | 一区二区三区四区视频 | 精品久久久久久亚洲精品 | 亚洲欧美日韩系列 | 亚洲精品国产二区 | 亚州中文字幕蜜桃视频 | 亚洲精品一 | 色播开心网 | 男人的天堂在线视频 | 精品视频一区二区三区在线观看 | 欧美成人一区二区三区片免费 | 成人免费av | 日韩精品 电影一区 亚洲 | 亚洲精品视频区 | 午夜男人的天堂 | 国产一区在线免费观看 | 精品亚洲一区二区三区四区五区 | 欧美日韩精品一区二区在线播放 | 一区精品视频 | 国产精品久久久久久久久久妞妞 | 一区二区三区国产亚洲网站 | 男女视频一区二区 | 精品久久久久久久久久久 | 欧美精品成人一区二区三区四区 | 日韩一区二区三区在线观看 | 日本一区二区精品 | 亚洲日韩aⅴ在线视频 | 国产欧美综合一区二区三区 | 国产精品99久久久久久久vr | 欧美男人天堂 | 久在线视频 | 成人国产在线 | 欧美一区二区三区在线 | 在线视频 中文字幕 | 亚洲午夜电影在线 | 欧美精品成人一区二区三区四区 | 国产精品一区二区三区免费 | 日韩一区二区在线免费观看 | 中文字幕视频免费观看 | 午夜大片网 | 国产精品久久久久久久午夜片 | 亚洲精品成人在线 | 国产亚洲精品久久久久久久 | 色综合激情 | 天天综合网久久综合网 | 成人做爰9片免费视频 | 国产九九九 | 91精品国产日韩91久久久久久 | 国产深夜视频在线观看 | 午夜小电影 | 久久久精 | 欧美日韩视频 | 欧美天天 | 亚洲电影一区 | ririsao久久精品一区 | 日韩一区二区不卡 | 性瘾调教校园h | 久久久www成人免费精品 | 欧美一区二区视频 | 精品久久电影 | 亚洲日本欧美 | 黄色在线视频网 | 一级片免费视频 | 日韩天堂| 久久国产经典视频 | 亚洲精品乱码久久久久久国产主播 | 热久久这里只有精品 | 一区二区三区在线免费观看 | 最新日韩精品在线观看 | 欧美成人精品一区二区三区 | 中文字幕亚洲欧美日韩在线不卡 | 亚洲一二三区电影 | 粉嫩高清一区二区三区精品视频 | 欧美视频免费看 | 精品视频久久 | 青青草国产成人av片免费 | 国产激情免费 | 日韩美香港a一级毛片免费 国产综合av | 欧洲一区 | www中文字幕 | 欧美日韩国产不卡 | 欧美视频免费在线 | 亚洲成人毛片 | 一级在线看 | www视频在线观看 | 欧美在线一区二区 | 日本国产欧美 | 天堂一区二区三区 | 亚洲动漫在线观看 | 国产99页| 亚洲欧美中文日韩在线v日本 | 亚洲激情一区二区 | 精品在线一区二区 | 久久99这里只有精品 | 亚洲欧美中文字幕 | 欧美在线一区二区 | 亚洲精品一区二三区不卡 | 欧美日韩高清在线一区 | 在线播放黄色片网站 | 日韩精品一区二区三区在线观看 | 久久精品久久久 | 成人在线精品 | 精品国产91久久久久久久 | 日韩精品www| 亚洲免费视频在线 | 欧美精品综合在线 |