日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计

發(fā)布時(shí)間:2024/7/23 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

需求分析

當(dāng)我們?nèi)?shí)現(xiàn)一個(gè)組件庫(kù)的時(shí)候,并不會(huì)一上來(lái)就擼碼,而是把它當(dāng)做產(chǎn)品一樣,思考一下我們的組件庫(kù)的需求。那么對(duì)于 element-ui,除了基于 Vue.js 技術(shù)棧開(kāi)發(fā)組件,它還有哪些方面的需求呢。

  • 豐富的 feature:豐富的組件,自定義主題,國(guó)際化。

  • 文檔 & demo:提供友好的文檔和 demo,維護(hù)成本小,支持多語(yǔ)言。

  • 安裝 & 引入:支持 npm 方式和 cdn 方式,并支持按需引入。

  • 工程化:開(kāi)發(fā),測(cè)試,構(gòu)建,部署,持續(xù)集成。

  • 需求有了,接下來(lái)就需要去思考如何去實(shí)現(xiàn),本文會(huì)依據(jù) element-ui 2.11.1 版本的源碼來(lái)分析這些需求是如何實(shí)現(xiàn)的。當(dāng)然,element-ui 早期一定不是這樣子的,我們分析的這個(gè)版本已經(jīng)是經(jīng)過(guò)它多次迭代優(yōu)化后的,如果你想去了解它的發(fā)展歷程,可以去 GitHub 搜索它的歷史版本。

    豐富的 feature

    豐富的組件

    組件庫(kù)最核心的還是組件,先來(lái)看一下 element-ui 組件的設(shè)計(jì)原則:一致、反饋、效率、可控。具體的解釋在官網(wǎng)有,我就不多貼了,在 element-ui 開(kāi)發(fā)團(tuán)隊(duì)背后,有一個(gè)強(qiáng)大的設(shè)計(jì)團(tuán)隊(duì),這也得益于 element-ui 的創(chuàng)始人 sofish 在公司的話語(yǔ)權(quán)和地位,爭(zhēng)取到這么好的資源。所以 element-ui 組件的外型、配色、交互都做的非常不錯(cuò)。

    作為一個(gè)基礎(chǔ)組件庫(kù),還有一個(gè)很重要的方面就是組件種類豐富。element-ui 官方目前有 55 個(gè)組件,分成了 6 大類,分別是基礎(chǔ)組件、表單類組件、數(shù)據(jù)類組件、提示類組件、導(dǎo)航類組件和其它類型組件。這些豐富的基礎(chǔ)組件能很好地滿足大部分 PC 端 to B 業(yè)務(wù)開(kāi)發(fā)需求。

    開(kāi)發(fā)這么多組件,需要大量的時(shí)間和精力,所以這里要非常感謝 element-ui 團(tuán)隊(duì),為我們提供了這些基礎(chǔ)組件,我們基于它們做二次開(kāi)發(fā),節(jié)約了非常多的時(shí)間。

    element-ui 的組件源碼在 packages 目錄里維護(hù),而并不在 src 目錄中。這么做并不是為了要采用 monorepo,我也并沒(méi)有找到 lerna 包管理工具,這么做的目的我猜測(cè)是為了讓每個(gè)組件可以單獨(dú)打包,支持按需引入。但實(shí)際上想達(dá)到這個(gè)目的也并不一定需要這么去組織維護(hù)代碼,我更推薦把組件庫(kù)中的組件代碼放在 src/components 目錄中維護(hù),然后通過(guò)修改 webpack 配置腳本也可以做到每個(gè)組件單獨(dú)打包以及支持按需引入,源碼放在 src 目錄總是更合理的。

    自定義主題

    element-ui 的一大特色是支持自定義主題,你可以使用在線主題編輯器,可以修改定制 Element 所有全局和組件的 Design Tokens,并可以方便地實(shí)時(shí)預(yù)覽樣式改變后的視覺(jué)。同時(shí)它還可以基于新的定制樣式生成完整的樣式文件包,供直接下載使用,那么它是如何做到這點(diǎn)的呢?

    element-ui 組件的樣式、公共樣式都在 packages/theme-chalk 文件中,并且它是可以獨(dú)立發(fā)布的。element-ui 組件樣式中的顏色、字體、線條等等樣式都是通過(guò)變量的方式引入的,在 packages/theme-chalk/src/common/var.scss 中我們可以看到這些變量的定義,這樣就給做多主題提供了方便,因?yàn)槲抑灰薷倪@些變量,就可以實(shí)現(xiàn)組件的主題改變。

    了解了基本原理,做在線替換主題也并不是難事了,我并不會(huì)詳細(xì)去講在線定制主題前端交互部分,感興趣的同學(xué)可以自己去看源碼,都在 examples 目錄中,我這里只說(shuō)一下本質(zhì)的原理。

    想要做到在線換膚,并且實(shí)時(shí)預(yù)覽,需要借助 server 的幫助,比如主題可以通過(guò)一個(gè)配置去維護(hù),用戶做一系列操作后,會(huì)生成新的主題配置,把這個(gè)配置通過(guò)接口提交的方式告訴 server,然后 server 會(huì)根據(jù)這個(gè)配置做返回生成新的 CSS(具體的實(shí)施的方案未開(kāi)源,大致會(huì)做一些變量替換,然后編譯),新的 CSS 的樣式就會(huì)覆蓋默認(rèn)的樣式,達(dá)到了切換主題的目的。

    我們可以在主題編輯頁(yè)面打開(kāi)網(wǎng)絡(luò)面板,可以看到有 2 個(gè) xhr 請(qǐng)求,如圖:


    其中,updateVarible 是一個(gè) POST 請(qǐng)求,他會(huì)把你修改的的主題配置提交到后端 server,提交的數(shù)據(jù)你可以自己去查看它的 Request Payload,這個(gè) POST 請(qǐng)求會(huì)返回一段 CSS 文本,然后會(huì)動(dòng)態(tài)插入到 head 標(biāo)簽的底部,來(lái)覆蓋默認(rèn)樣式,你可以通過(guò)審查元素看到 head 底部會(huì)動(dòng)態(tài)插入一個(gè) id 為 chalk-style 的標(biāo)簽。

    下圖就是該請(qǐng)求返回的樣式文本 :


    相關(guān)代碼在 examples/components/theme/loader/index.vue 中。

    ????onAction()?{
    ??????this.triggertProgressBar(true);
    ??????const?time?=?+new?Date();
    ??????updateVars(this.userConfig)
    ????????.then(res?=>?{
    ??????????this.applyStyle(res,?time);
    ????????})
    ????????.catch(err?=>?{
    ??????????this.onError(err);
    ????????})
    ????????.then(()?=>?{
    ??????????this.triggertProgressBar(false);
    ????????});
    ????},
    ????applyStyle(res,?time)?{
    ??????if?(time?this.lastApply)?return;
    ??????this.updateDocs(()?=>?{
    ????????updateDomHeadStyle('chalk-style',?res);
    ??????});
    ??????this.lastApply?=?time;
    ????}

    onAction 函數(shù)中的 updateVars 就是去發(fā)送 POST 請(qǐng)求,而 applyStyle 函數(shù)就是去修改和覆蓋默認(rèn)樣式,updateDocs 函數(shù)會(huì)去更新默認(rèn)主題顏色,updateDomHeadStyle 樣式會(huì)添加或者修改 id 為 chalk-style 的 style 標(biāo)簽,目的就是覆蓋默認(rèn)樣式,應(yīng)用新主題樣式。

    updateVars 請(qǐng)求在頁(yè)面加載的時(shí)候會(huì)發(fā)起,在你修改完主題配置后也會(huì)發(fā)起。

    再來(lái)看一下 getVarible 請(qǐng)求,它是一個(gè) GET 請(qǐng)求,返回的內(nèi)容是主題配置頁(yè)面右側(cè)配置面板的數(shù)據(jù)源,如下圖所示:

    主題配置面板根據(jù)該數(shù)據(jù)源生成,并且當(dāng)你去編輯其中一項(xiàng)的時(shí)候,又會(huì)發(fā)起 updateVars POST 請(qǐng)求,把更新的配置提交,然后后端會(huì)返回新的 CSS 并在前端生效。

    另外,用戶修改的配置還利用了 localStorage 在本地保存了一份,這樣用戶每次編輯都可以保存一份主題,下次也可以繼續(xù)基于某個(gè)主題繼續(xù)編輯。

    不過(guò),這么實(shí)現(xiàn)多主題也并非完美,為了編譯加速,element-ui 把樣式部分單獨(dú)抽離出單獨(dú)的文件,這樣給開(kāi)發(fā)組件的同學(xué)帶來(lái)很大的不便,當(dāng)你去編寫(xiě)組件的樣式的時(shí)候,需要在多個(gè)文件中來(lái)回切換,而且這樣也不符合組件就近管理的原則。但是如果把樣式寫(xiě)在組件中,server 端去編譯生成單獨(dú)樣式文件的時(shí)間就會(huì)增長(zhǎng)(需要從組件中提取 CSS),所以這是一個(gè)需要權(quán)衡的問(wèn)題。

    國(guó)際化

    說(shuō)到 Vue 的國(guó)際化方案,大家很容易會(huì)聯(lián)想到 vue-i18n 方案,element-ui 并未引入 vue-i18n,不過(guò)它是可以很好地與 vue-i18n 兼容的。

    所有的國(guó)際化方案都會(huì)用到語(yǔ)言包,語(yǔ)言包通常會(huì)返回一個(gè) JSON 格式的數(shù)據(jù),element-ui 組件庫(kù)的語(yǔ)言包在 src/locale/lang 目錄下,以英語(yǔ)語(yǔ)言包為例:

    export?default?{
    ??el:?{
    ????colorpicker:?{
    ??????confirm:?'OK',
    ??????clear:?'Clear'
    ????}
    ????//?...
    ??}
    }


    在 packages/color-picker/src/components/picker-dropdown.vue 中,我們?cè)谀0宀糠挚梢钥吹竭@個(gè)語(yǔ)言包的使用:

    <el-buttonsize="mini"type="text"class="el-color-dropdown__link-btn"
    ??@click="$emit('clear')">
    ??{{?t('el.colorpicker.clear')?}}
    el-button>
    <el-buttonplainsize="mini"class="el-color-dropdown__btn"
    ??@click="confirmValue">
    ??{{?t('el.colorpicker.confirm')?}}
    el-button>

    模板中用到的 t 函數(shù),它定義在 src/mixins/locale.js 中:

    import?{?t?}?from?'element-ui/src/locale';

    export?default?{
    ??methods:?{
    ????t(...args)?{
    ??????return?t.apply(this,?args);
    ????}
    ??}
    };


    實(shí)際上是在 src/locale/index.js 中定義的 t 函數(shù):

    export?const?t?=?function(path,?options)?{
    ??let?value?=?i18nHandler.apply(this,?arguments);
    ??if?(value?!==?null?&&?value?!==?undefined)?return?value;

    ??const?array?=?path.split('.');
    ??let?current?=?lang;

    ??for?(let?i?=?0,?j?=?array.length;?i?????const?property?=?array[i];
    ????value?=?current[property];
    ????if?(i?===?j?-?1)?return?format(value,?options);
    ????if?(!value)?return?'';
    ????current?=?value;
    ??}
    ??return?'';
    };


    這個(gè)函數(shù)是根據(jù)傳入的 path 路徑,比如我們例子中的 el.colorpicker.confirm,從語(yǔ)言包中找到對(duì)應(yīng)的文案。其中 i18nHandler 是一個(gè) i18n 的處理函數(shù),這塊邏輯就是用來(lái)兼容外部的 i18n 方案如 vue-i18n。

    let?i18nHandler?=?function()?{
    ??const?vuei18n?=?Object.getPrototypeOf(this?||?Vue).$t;
    ??if?(typeof?vuei18n?===?'function'?&&?!!Vue.locale)?{
    ????if?(!merged)?{
    ??????merged?=?true;
    ??????Vue.locale(
    ????????Vue.config.lang,
    ????????deepmerge(lang,?Vue.locale(Vue.config.lang)?||?{},?{?clone:?true?})
    ??????);
    ????}
    ????return?vuei18n.apply(this,?arguments);
    ??}
    };

    export?const?i18n?=?function(fn)?{
    ??i18nHandler?=?fn?||?i18nHandler;
    };

    export?const?use?=?function(l)?{
    ??lang?=?l?||?lang;
    };


    可以看到 i18nHandler 默認(rèn)會(huì)嘗試去找 Vue 原型中的 $t 函數(shù),這是 vue-i18@5.x 的實(shí)現(xiàn),會(huì)在 Vue 的原型上掛載 $t 方法。

    另外它也暴露了 i18n 方法,可以外部傳入其它的 i18n 方法,覆蓋 i18nHandler。

    如果沒(méi)有外部提供的 i18n 方法,那么就直接找到當(dāng)前的語(yǔ)言包 let current = lang;,接下來(lái)的邏輯就是從這個(gè)語(yǔ)言包對(duì)象中讀到對(duì)應(yīng)的字符串值,當(dāng)然如果字符串需要格式化則調(diào)用 format 函數(shù),這塊邏輯同學(xué)們感興趣可以自己看。

    因此在使用對(duì)應(yīng)的語(yǔ)言包的時(shí)候一定要注冊(cè):

    import?lang?from?'element-ui/lib/locale/lang/en'
    import?locale?from?'element-ui/lib/locale'

    //?設(shè)置語(yǔ)言
    locale.use(lang)


    這樣就注冊(cè)了英文語(yǔ)言包,在模板中就可以正常使用并找到對(duì)應(yīng)的語(yǔ)言了。

    如果你要開(kāi)發(fā)一個(gè)國(guó)際化項(xiàng)目,在運(yùn)行時(shí)才能知道用戶的語(yǔ)言,可以考慮使用異步動(dòng)態(tài)加載的方式,在渲染頁(yè)面前先獲取語(yǔ)言包,另外也可以考慮做緩存優(yōu)化,不過(guò)這個(gè)話題延伸起來(lái)就有點(diǎn)多了,未來(lái)我可能會(huì)單開(kāi)一個(gè)主題去分享業(yè)務(wù)如何做國(guó)際化。

    文檔 & demo

    作為一個(gè)優(yōu)秀的開(kāi)源組件庫(kù),友好的文檔和 demo 是必不可少的,它也能幫你招攬到不少用戶。作為一個(gè)組件庫(kù)的開(kāi)發(fā)者和維護(hù)者,也希望用最小的成本來(lái)維護(hù)文檔和 demo。

    element-ui 的文檔和 demo 是融為一體的,我們打開(kāi)它的文檔,可以看到文檔不僅介紹了每個(gè)組件的使用方式,還展示了組件的各種示例,并且還可以清楚地看到每個(gè)示例的源碼,對(duì)用戶而言非常友好。那么 element-ui 內(nèi)部是如何去編寫(xiě)這些 demo 和文檔的呢?實(shí)際上,每個(gè)組件的文檔和 demo 都是通過(guò)一個(gè)單獨(dú)的 .md 文件生成的,那么它又是如何做到這點(diǎn)的呢?

    element-ui 的 demo 源碼都在 examples 目錄中維護(hù),當(dāng)我們?cè)?element-ui 工程下運(yùn)行 npm run dev 的時(shí)候,會(huì)啟動(dòng)它的開(kāi)發(fā)調(diào)試模式,并且運(yùn)行官方文檔和 demo。

    看一下 npm scripts:

    "scripts":?{
    ????"bootstrap":?"yarn?||?npm?i",
    ????"build:file":?"node?build/bin/iconInit.js?&?node?build/bin/build-entry.js?&?node?build/bin/i18n.js?&?node?build/bin/version.js",
    ????"dev":?"npm?run?bootstrap?&&?npm?run?build:file?&&?cross-env?NODE_ENV=development?webpack-dev-server?--config?build/webpack.demo.js?&?node?build/bin/template.js",
    }


    我們省略了其它的 scripts,重點(diǎn)看 dev 和相關(guān)的幾個(gè)命令,其中 bootstrap 的作用是安裝依賴,build:file 的作用是運(yùn)行 build 目錄下幾個(gè)命令,包括對(duì) icon、entry、i18n、version 等初始化。在執(zhí)行完 bootstrap 和 build:file 后,通過(guò) webpack-dev-server 運(yùn)行 build/webpack.demo.js,這個(gè)是重點(diǎn),我們來(lái)看一下這個(gè) webpack 的配置文件。

    const?webpackConfig?=?{
    ??mode:?process.env.NODE_ENV,
    ??entry:?isProd???{
    ????docs:?'./examples/entry.js',
    ????'element-ui':?'./src/index.js'
    ??}?:?(isPlay???'./examples/play.js'?:?'./examples/entry.js'),
    ??output:?{
    ????path:?path.resolve(process.cwd(),?'./examples/element-ui/'),
    ????publicPath:?process.env.CI_ENV?||?'',
    ????filename:?'[name].[hash:7].js',
    ????chunkFilename:?isProd???'[name].[hash:7].js'?:?'[name].js'
    ??},
    ??resolve:?{
    ????extensions:?['.js',?'.vue',?'.json'],
    ????alias:?config.alias,
    ????modules:?['node_modules']
    ??},
    ??devServer:?{
    ????host:?'0.0.0.0',
    ????port:?8085,
    ????publicPath:?'/',
    ????hot:?true
    ??},
    ??module:?{
    ????rules:?[
    ??????{
    ????????test:?/\.vue$/,
    ????????loader:?'vue-loader',
    ????????options:?{
    ??????????compilerOptions:?{
    ????????????preserveWhitespace:?false
    ??????????}
    ????????}
    ??????},
    ??????{
    ????????test:?/\.md$/,
    ????????use:?[
    ??????????{
    ????????????loader:?'vue-loader',
    ????????????options:?{
    ??????????????compilerOptions:?{
    ????????????????preserveWhitespace:?false
    ??????????????}
    ????????????}
    ??????????},
    ??????????{
    ????????????loader:?path.resolve(__dirname,?'./md-loader/index.js')
    ??????????}
    ????????]
    ??????}
    ????]
    ??}
    };


    由于整個(gè)配置文件內(nèi)容比較長(zhǎng),我只保留了重點(diǎn)的部分,重點(diǎn)看一下 entry 和 module 下的 rules。

    element-ui 官網(wǎng)本質(zhì)上就是一個(gè)用 vue 開(kāi)發(fā)的應(yīng)用,當(dāng)我們運(yùn)行 npm run dev 的時(shí)候,入口文件是 examples 目錄下的 entry.js:

    import?Vue?from?'vue';
    import?entry?from?'./app';
    import?VueRouter?from?'vue-router';
    import?Element?from?'main/index.js';
    import?hljs?from?'highlight.js';
    import?routes?from?'./route.config';
    import?demoBlock?from?'./components/demo-block';
    import?MainFooter?from?'./components/footer';
    import?MainHeader?from?'./components/header';
    import?SideNav?from?'./components/side-nav';
    import?FooterNav?from?'./components/footer-nav';
    import?title?from?'./i18n/title';

    import?'packages/theme-chalk/src/index.scss';
    import?'./demo-styles/index.scss';
    import?'./assets/styles/common.css';
    import?'./assets/styles/fonts/style.css';
    import?icon?from?'./icon.json';

    Vue.use(Element);
    Vue.use(VueRouter);
    Vue.component('demo-block',?demoBlock);
    Vue.component('main-footer',?MainFooter);
    Vue.component('main-header',?MainHeader);
    Vue.component('side-nav',?SideNav);
    Vue.component('footer-nav',?FooterNav);

    const?globalEle?=?new?Vue({
    ??data:?{?$isEle:?false?}?//?是否?ele?用戶
    });

    Vue.mixin({
    ??computed:?{
    ????$isEle:?{
    ??????get:?()?=>?(globalEle.$data.$isEle),
    ??????set:?(data)?=>?{globalEle.$data.$isEle?=?data;}
    ????}
    ??}
    });

    Vue.prototype.$icon?=?icon;?//?Icon?列表頁(yè)用

    const?router?=?new?VueRouter({
    ??mode:?'hash',
    ??base:?__dirname,
    ??routes
    });

    router.afterEach(route?=>?{
    ??//?https://github.com/highlightjs/highlight.js/issues/909#issuecomment-131686186
    ??Vue.nextTick(()?=>?{
    ????const?blocks?=?document.querySelectorAll('pre?code:not(.hljs)');
    ????Array.prototype.forEach.call(blocks,?hljs.highlightBlock);
    ??});
    ??const?data?=?title[route.meta.lang];
    ??for?(let?val?in?data)?{
    ????if?(new?RegExp('^'?+?val,?'g').test(route.name))?{
    ??????document.title?=?data[val];
    ??????return;
    ????}
    ??}
    ??document.title?=?'Element';
    ??ga('send',?'event',?'PageView',?route.name);
    });

    new?Vue({?//?eslint-disable-line
    ??...entry,
    ??router
    }).$mount('#app');


    入口文件做的事情很簡(jiǎn)單,全引入的方式注冊(cè)了 element-ui 組件庫(kù),注冊(cè)了一些官網(wǎng)用到的組件,注冊(cè)了路由以及路由的全局鉤子函數(shù)。

    這里我們要重點(diǎn)關(guān)注路由部分,路由的配置都在 examples/route.config.js 中:

    import?navConfig?from?'./nav.config';
    import?langs?from?'./i18n/route';

    const?LOAD_MAP?=?{
    ??'zh-CN':?name?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./pages/zh-CN/${name}.vue`)),
    ????'zh-CN');
    ??},
    ??'en-US':?name?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./pages/en-US/${name}.vue`)),
    ????'en-US');
    ??},
    ??'es':?name?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./pages/es/${name}.vue`)),
    ????'es');
    ??},
    ??'fr-FR':?name?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./pages/fr-FR/${name}.vue`)),
    ????'fr-FR');
    ??}
    };

    const?load?=?function(lang,?path)?{
    ??return?LOAD_MAP[lang](path);
    };

    const?LOAD_DOCS_MAP?=?{
    ??'zh-CN':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/zh-CN${path}.md`)),
    ????'zh-CN');
    ??},
    ??'en-US':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/en-US${path}.md`)),
    ????'en-US');
    ??},
    ??'es':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/es${path}.md`)),
    ????'es');
    ??},
    ??'fr-FR':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/fr-FR${path}.md`)),
    ????'fr-FR');
    ??}
    };

    const?loadDocs?=?function(lang,?path)?{
    ??return?LOAD_DOCS_MAP[lang](path);
    };

    const?registerRoute?=?(navConfig)?=>?{
    ??let?route?=?[];
    ??Object.keys(navConfig).forEach((lang,?index)?=>?{
    ????let?navs?=?navConfig[lang];
    ????route.push({
    ??????path:?`/${?lang?}/component`,
    ??????redirect:?`/${?lang?}/component/installation`,
    ??????component:?load(lang,?'component'),
    ??????children:?[]
    ????});
    ????navs.forEach(nav?=>?{
    ??????if?(nav.href)?return;
    ??????if?(nav.groups)?{
    ????????nav.groups.forEach(group?=>?{
    ??????????group.list.forEach(nav?=>?{
    ????????????addRoute(nav,?lang,?index);
    ??????????});
    ????????});
    ??????}?else?if?(nav.children)?{
    ????????nav.children.forEach(nav?=>?{
    ??????????addRoute(nav,?lang,?index);
    ????????});
    ??????}?else?{
    ????????addRoute(nav,?lang,?index);
    ??????}
    ????});
    ??});
    ??function?addRoute(page,?lang,?index)?{
    ????const?component?=?page.path?===?'/changelog'
    ????????load(lang,?'changelog')
    ??????:?loadDocs(lang,?page.path);
    ????let?child?=?{
    ??????path:?page.path.slice(1),
    ??????meta:?{
    ????????title:?page.title?||?page.name,
    ????????description:?page.description,
    ????????lang
    ??????},
    ??????name:?'component-'?+?lang?+?(page.title?||?page.name),
    ??????component:?component.default?||?component
    ????};

    ????route[index].children.push(child);
    ??}

    ??return?route;
    };

    let?route?=?registerRoute(navConfig);

    const?generateMiscRoutes?=?function(lang)?{
    ??let?guideRoute?=?{
    ????path:?`/${?lang?}/guide`,?//?指南
    ????redirect:?`/${?lang?}/guide/design`,
    ????component:?load(lang,?'guide'),
    ????children:?[{
    ??????path:?'design',?//?設(shè)計(jì)原則
    ??????name:?'guide-design'?+?lang,
    ??????meta:?{?lang?},
    ??????component:?load(lang,?'design')
    ????},?{
    ??????path:?'nav',?//?導(dǎo)航
    ??????name:?'guide-nav'?+?lang,
    ??????meta:?{?lang?},
    ??????component:?load(lang,?'nav')
    ????}]
    ??};

    ??let?themeRoute?=?{
    ????path:?`/${?lang?}/theme`,
    ????component:?load(lang,?'theme-nav'),
    ????children:?[
    ??????{
    ????????path:?'/',?//?主題管理
    ????????name:?'theme'?+?lang,
    ????????meta:?{?lang?},
    ????????component:?load(lang,?'theme')
    ??????},
    ??????{
    ????????path:?'preview',?//?主題預(yù)覽編輯
    ????????name:?'theme-preview-'?+?lang,
    ????????meta:?{?lang?},
    ????????component:?load(lang,?'theme-preview')
    ??????}]
    ??};

    ??let?resourceRoute?=?{
    ????path:?`/${?lang?}/resource`,?//?資源
    ????meta:?{?lang?},
    ????name:?'resource'?+?lang,
    ????component:?load(lang,?'resource')
    ??};

    ??let?indexRoute?=?{
    ????path:?`/${?lang?}`,?//?首頁(yè)
    ????meta:?{?lang?},
    ????name:?'home'?+?lang,
    ????component:?load(lang,?'index')
    ??};

    ??return?[guideRoute,?resourceRoute,?themeRoute,?indexRoute];
    };

    langs.forEach(lang?=>?{
    ??route?=?route.concat(generateMiscRoutes(lang.lang));
    });

    route.push({
    ??path:?'/play',
    ??name:?'play',
    ??component:?require('./play/index.vue')
    });

    let?userLanguage?=?localStorage.getItem('ELEMENT_LANGUAGE')?||?window.navigator.language?||?'en-US';
    let?defaultPath?=?'/en-US';
    if?(userLanguage.indexOf('zh-')?!==?-1)?{
    ??defaultPath?=?'/zh-CN';
    }?else?if?(userLanguage.indexOf('es')?!==?-1)?{
    ??defaultPath?=?'/es';
    }?else?if?(userLanguage.indexOf('fr')?!==?-1)?{
    ??defaultPath?=?'/fr-FR';
    }

    route?=?route.concat([{
    ??path:?'/',
    ??redirect:?defaultPath
    },?{
    ??path:?'*',
    ??redirect:?defaultPath
    }]);

    export?default?route;


    這個(gè)路由配置文件提供了指南、組件、主題、資源等多個(gè)路由頁(yè)面的配置,并且支持了多語(yǔ)言,我們重點(diǎn)關(guān)注一下組件路由是如何生成的,它主要通過(guò) registerRoute(navConfig) 方法生成。

    其中 navConfig 讀取的是 examples/nav.config.json 文件,這個(gè)配置文件太長(zhǎng)我就不貼了,它包括了多個(gè)語(yǔ)言的配置,維護(hù)了左側(cè)組件導(dǎo)航菜單路徑映射關(guān)系。

    registerRoute 函數(shù)內(nèi)部就是遍歷 navConfig,根據(jù)它內(nèi)部元素的數(shù)據(jù)結(jié)構(gòu)生成路由配置,如果數(shù)據(jù)中有 children 則生成子路由。

    我們知道 Vue Router 的本質(zhì)是根據(jù)不同的 URL path, 組件映射到對(duì)應(yīng)的路由組件,對(duì)于每一個(gè)組件的路由,都是通過(guò) addRoute(nav, lang, index) 方法生成的,該方法內(nèi)部又調(diào)用了 loadDocs(lang, page.path) 獲取到對(duì)應(yīng)的路由組件。

    const?loadDocs?=?function(lang,?path)?{
    ??return?LOAD_DOCS_MAP[lang](path);
    };

    const?LOAD_DOCS_MAP?=?{
    ??'zh-CN':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/zh-CN${path}.md`)),
    ????'zh-CN');
    ??},
    ??'en-US':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/en-US${path}.md`)),
    ????'en-US');
    ??},
    ??'es':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/es${path}.md`)),
    ????'es');
    ??},
    ??'fr-FR':?path?=>?{
    ????return?r?=>?require.ensure([],?()?=>
    ??????r(require(`./docs/fr-FR${path}.md`)),
    ????'fr-FR');
    ??}
    };


    以中文為例,我們獲取到某個(gè) path 下的路由組件就是一個(gè)工廠函數(shù),它對(duì)應(yīng)加載的組件路徑是 exmaples/docs/zh-CN/${path}.md。這里要注意的是,和我們普通的異步組件加載方式不同,這里加載的居然是一個(gè) .md 文件,而并非一個(gè) .vue 文件,但卻能和 .vue 文件一樣能渲染成一個(gè) Vue 組件,這是如何做到的呢?

    我們知道,webpack 的理念是一切資源都可以 require,只要配置了對(duì)應(yīng)的 loader。回到 build/webpack.demo.js,我們發(fā)現(xiàn)對(duì)于 .md 文件我們配置了相應(yīng)的 loader:

    ??{
    ????test:?/\.md$/,
    ????use:?[
    ??????{
    ????????loader:?'vue-loader',
    ????????options:?{
    ??????????compilerOptions:?{
    ????????????preserveWhitespace:?false
    ??????????}
    ????????}
    ??????},
    ??????{
    ????????loader:?path.resolve(__dirname,?'./md-loader/index.js')
    ??????}
    ????]
    ??}

    對(duì)于 .md 文件,這里 use 數(shù)組中配置了 2 項(xiàng),它們執(zhí)行順序是逆序的,也就是先執(zhí)行 md-loader,再執(zhí)行 vue-loader,md-loader 的代碼在 build/md-loader/index.js 中:

    const?{
    ??stripScript,
    ??stripTemplate,
    ??genInlineComponentText
    }?=?require('./util');
    const?md?=?require('./config');

    module.exports?=?function(source)?{
    ??const?content?=?md.render(source);

    ??const?startTag?=?'';
    ??const?endTagLen?=?endTag.length;

    ??let?componenetsString?=?'';
    ??let?id?=?0;?//?demo?的?id
    ??let?output?=?[];?//?輸出的內(nèi)容
    ??let?start?=?0;?//?字符串開(kāi)始位置

    ??let?commentStart?=?content.indexOf(startTag);
    ??let?commentEnd?=?content.indexOf(endTag,?commentStart?+?startTagLen);
    ??while?(commentStart?!==?-1?&&?commentEnd?!==?-1)?{
    ????output.push(content.slice(start,?commentStart));

    ????const?commentContent?=?content.slice(commentStart?+?startTagLen,?commentEnd);
    ????const?html?=?stripTemplate(commentContent);
    ????const?script?=?stripScript(commentContent);
    ????let?demoComponentContent?=?genInlineComponentText(html,?script);
    ????const?demoComponentName?=?`element-demo${id}`;
    ????output.push(`<${demoComponentName}?/>`);
    ????componenetsString?+=?`${JSON.stringify(demoComponentName)}:?${demoComponentContent},`;

    ????//?重新計(jì)算下一次的位置
    ????id++;
    ????start?=?commentEnd?+?endTagLen;
    ????commentStart?=?content.indexOf(startTag,?start);
    ????commentEnd?=?content.indexOf(endTag,?commentStart?+?startTagLen);
    ??}

    ??//?僅允許在?demo?不存在時(shí),才可以在?Markdown?中寫(xiě)?script?標(biāo)簽
    ??//?todo:?優(yōu)化這段邏輯
    ??let?pageScript?=?'';
    ??if?(componenetsString)?{
    ????pageScript?=?`;
    ??}?else?if?(content.indexOf(')?+?''.length;
    ????pageScript?=?content.slice(0,?start);
    ??}

    ??output.push(content.slice(start));
    ??return?`${output.join('')}${pageScript}
    ??`;
    };

    webpack loader 的原理很簡(jiǎn)單,輸入是文件的原始內(nèi)容,返回的是經(jīng)過(guò) loader 處理后的內(nèi)容。對(duì)于 md-loader,輸入的是 .md 文檔,輸出的則是一個(gè) Vue SFC 格式的字符串,這樣它的輸出就可以作為下一個(gè) vue-loader 的輸入做處理了。

    我們來(lái)簡(jiǎn)單看一下 md-loader 中間處理過(guò)程。首先執(zhí)行了 md.render(source) 對(duì) md 文檔解析,提取文檔中 :::demo {content} ::: 內(nèi)容,分別生成一些 Vue 的模板字符串,然后再?gòu)倪@個(gè)模板字符串中循環(huán)查找 包裹的內(nèi)容,從中提取模板字符串到 output 中,提取 script 到 componenetsString 中,然后構(gòu)造 pageScript,最后返回的內(nèi)容就是:

    ??return?`${output.join('')}${pageScript}
    ??`;

    最終生成的字符串滿足我們通常編寫(xiě)的 .vue SFC 格式,它會(huì)作為下一個(gè) vue-loader 的輸入,所以這樣我們就相當(dāng)于通過(guò)加載一個(gè) .md 格式的文件的方式加載了 Vue 組件。

    這里面還有很多和 .md 文件解析的細(xì)節(jié),如果你對(duì)最終生成的 output 和 pageScript 代碼是什么感興趣,建議你自己調(diào)試一番。

    element-ui 這種文檔和 demo 的實(shí)現(xiàn)方式是非常巧妙的,大大減少了 demo 和文檔的維護(hù)成本,并且對(duì)于用戶來(lái)說(shuō)也非常友好,如果你也為自己的庫(kù)構(gòu)建文檔,不妨參考它的實(shí)現(xiàn)。

    安裝 & 引入

    通常 JS 庫(kù)都會(huì)支持 npm 和 CDN 2 種安裝方式,element-ui 也不例外。

    先說(shuō)一下 CDN 的安裝方式,實(shí)際上 element-ui 會(huì)把所有組件打包生成一份 CSS 和 JS,官方也提供了例子:


    <link?rel="stylesheet"?href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><script?src="https://unpkg.com/element-ui/lib/index.js">script>


    CDN 安裝方式有它的好處,不需要構(gòu)建工具,開(kāi)箱即用,但缺點(diǎn)也很明顯,全量引入了所有組件,體積非常大。

    由于大部分人在開(kāi)發(fā) Vue 項(xiàng)目都是基于 vue-cli 腳手架初始化項(xiàng)目的,所以更推薦使用 npm 方式安裝。

    npm?i?element-ui?-S

    說(shuō)到 npm 安裝,不得不提 element-ui 提供的 2 種組件引入方式,完整引入和部分引入。

    支持完整引入非常容易,把所有組件打包成一份 CSS 和 JS,并且在 package.json 中配置:

    ?"main":?"lib/element-ui.common.js"


    這樣當(dāng)用戶執(zhí)行 import ElementUI from 'element-ui' 的時(shí)候就可以完整引入了組件的 JS 代碼了。正如我們之前說(shuō)的,element-ui 會(huì)單獨(dú)發(fā)布 CSS,所以你還需要 import 'element-ui/lib/theme-chalk/index.css'。

    完整引入的好處是方便,只需要 2 行代碼就可以完整地使用 element-ui 所有的組件,但缺點(diǎn)也很明顯,引入的組件包體積很大,通常一個(gè)項(xiàng)目也用不到所有的組件,會(huì)有資源浪費(fèi)。

    因此最佳實(shí)踐就是按需引入:

    import?Vue?from?'vue'
    import?{?Button?}?from?'element-ui'

    Vue.component(Button.name,?Button)


    大部分人這么用的時(shí)候會(huì)覺(jué)得理所當(dāng)然,不知道大家有沒(méi)有想過(guò):為什么這種引入方式可以實(shí)現(xiàn)按需引入呢?要搞清楚這個(gè)問(wèn)題,就要搞清楚 import { Button } from 'element-ui' 這個(gè)背后都做了什么。

    其實(shí)官網(wǎng)已經(jīng)有答案了,在使用按需引入的時(shí)候,要借助 babel-plugin-component 這個(gè) webpack 插件,并且配置 .babelrc:

    {
    ??"presets":?[["es2015",?{?"modules":?false?}]],
    ??"plugins":?[
    ????[
    ??????"component",
    ??????{
    ????????"libraryName":?"element-ui",
    ????????"styleLibraryName":?"theme-chalk"
    ??????}
    ????]
    ??]
    }


    實(shí)際上它是把 import { Button } from 'element-ui' 轉(zhuǎn)換成:

    var?button?=?require('element-ui/lib/button')
    require('element-ui/lib/theme-chalk/button.css')

    這樣我們就精準(zhǔn)地引入了對(duì)應(yīng) lib 下的 Button 組件的 JS 和 CSS 代碼了,也就實(shí)現(xiàn)了按需引入 Button 組件。

    element-ui 這種按需引入的方式雖然方便,但背后卻要解決幾個(gè)問(wèn)題,由于我們支持每個(gè)組件可以單獨(dú)引入,那么如果產(chǎn)生了組件依賴并且同時(shí)按需引入的時(shí)候,代碼冗余問(wèn)題怎么解決。舉個(gè)例子,在 element-ui 中,Table 組件依賴了 CheckBox 組件,那么當(dāng)我同時(shí)引入了 Table 組件和 CheckBox 組件的時(shí)候,會(huì)不會(huì)產(chǎn)生代碼冗余呢?

    import?{?Table,?CheckBox?}?from?'element-ui'

    如果你不做任何處理的話,答案是會(huì),你最終引入的包會(huì)有 2 份 CheckBox 的代碼。那么 element-ui 是怎么解決這個(gè)問(wèn)題的呢?實(shí)際上只是部分解決了,它的 webpack 配置文件中配置了 externals,在 build/config.js 中我們可以看到這些具體的配置:

    var?externals?=?{};

    Object.keys(Components).forEach(function(key)?{
    ??externals[`element-ui/packages/${key}`]?=?`element-ui/lib/${key}`;
    });

    externals['element-ui/src/locale']?=?'element-ui/lib/locale';
    utilsList.forEach(function(file)?{
    ??file?=?path.basename(file,?'.js');
    ??externals[`element-ui/src/utils/${file}`]?=?`element-ui/lib/utils/${file}`;
    });
    mixinsList.forEach(function(file)?{
    ??file?=?path.basename(file,?'.js');
    ??externals[`element-ui/src/mixins/${file}`]?=?`element-ui/lib/mixins/${file}`;
    });
    transitionList.forEach(function(file)?{
    ??file?=?path.basename(file,?'.js');
    ??externals[`element-ui/src/transitions/${file}`]?=?`element-ui/lib/transitions/${file}`;
    });

    externals?=?[Object.assign({
    ??vue:?'vue'
    },?externals),?nodeExternals()];

    externals 可以防止將這些 import 的包打包到 bundle 中,并在運(yùn)行時(shí)再去從外部獲取這些擴(kuò)展依賴。

    我們來(lái)看一下打包后的 lib/table.js,我們可以看到編譯后的 table.js 對(duì) CheckBox 組件的依賴引入:

    module.exports?=?require("element-ui/lib/checkbox");


    這么處理的話,就不會(huì)打包生成 2 份 CheckBox JS 部分的代碼了,但是對(duì)于 CSS 部分,element-ui 并未處理冗余情況,可以看到 lib/theme-chalk/checkbox.css 和 lib/theme-chalk/table.css 中都會(huì)有 CheckBox 組件的 CSS 樣式。

    其實(shí),要解決按需引入的 JS 和 CSS 的冗余問(wèn)題并非難事,可以用后編譯的思想,即依賴包提供源碼,而編譯交給應(yīng)用處理,這樣不僅不會(huì)有組件冗余代碼,甚至連編譯的冗余代碼都不會(huì)有,實(shí)際上我們基于 element-ui fork 的組件庫(kù) zoom-ui 就應(yīng)用了后編譯技術(shù),之前在滴滴搞的開(kāi)源組件庫(kù)cube-ui 組件庫(kù)也是這么玩的。更多后編譯相關(guān)介紹可以參考滴滴團(tuán)隊(duì)在掘金發(fā)布的 《webpack 應(yīng)用編譯優(yōu)化之路》。

    工程化

    前端對(duì)于工程化的要求越來(lái)越高,element-ui 作為一個(gè)組件庫(kù),它在工程化方面做了哪些事情呢?

    首先是開(kāi)發(fā)階段,為了保證大家代碼風(fēng)格的一致性,使用了 ESLint,甚至專門(mén)寫(xiě)了 eslint-config-elemefe 作為 ESint 的擴(kuò)展規(guī)則配置;為了方便本地開(kāi)發(fā)調(diào)試,借助了 webpack 并配置了 Hot Reload;利用模塊化開(kāi)發(fā)的思想把組件依賴的一些公共模塊放在了 src 目錄,并依據(jù)功能拆分出 directives、locale、mixins、transitions、utils 等模塊。

    其次是測(cè)試方面,使用了 karma 測(cè)試框架,為每一個(gè)組件編寫(xiě)了單元測(cè)試,并且利用 Travis CI 集成了測(cè)試。

    接著是構(gòu)建方面,element-ui 編寫(xiě)了很多 npm scripts,以 dist 這個(gè) script 為例:

    ?"dist":?"npm?run?clean?&&?npm?run?build:file?&&?npm?run?lint?&&?webpack?--config?build/webpack.conf.js?&&?webpack?--config?build/webpack.common.js?&&?webpack?--config?build/webpack.component.js?&&?npm?run?build:utils?&&?npm?run?build:umd?&&?npm?run?build:theme"

    它內(nèi)部會(huì)依次執(zhí)行多個(gè)命令,最終會(huì)生成 lib 目錄和打包后的文件。我并不打算介紹所有的命令,感興趣同學(xué)可自行研究,這里我想介紹一下 build:file 這個(gè) script 做的事情:

    "build:file":?"node?build/bin/iconInit.js?&?node?build/bin/build-entry.js?&?node?build/bin/i18n.js?&?node?build/bin/version.js",

    這里會(huì)依次執(zhí)行 build/bin 目錄下的一些 Node 腳本,對(duì) icon、entry、i18n、version 等做了一系列的初始化工作,它們的內(nèi)容都是根據(jù)一些規(guī)則做文件的 IO,這么做的好處就是完全通過(guò)工具的手段自動(dòng)化生成文件,比人工靠譜且效率更高,這波操作非常值得我們學(xué)習(xí)和應(yīng)用。

    最后是部署,通過(guò) pub 這個(gè) npm script 完成:

    ?"pub":?"npm?run?bootstrap?&&?sh?build/git-release.sh?&&?sh?build/release.sh?&&?node?build/bin/gen-indices.js?&&?sh?build/deploy-faas.sh"


    主要是通過(guò)運(yùn)行一系列的 bash 腳本,實(shí)現(xiàn)了代碼的提交、合并、版本管理、npm 發(fā)布、官網(wǎng)發(fā)布等,讓整個(gè)發(fā)布流程自動(dòng)化完成,腳本具體內(nèi)容感興趣的同學(xué)可自行查看。

    總結(jié)

    至此,element-ui 的組件庫(kù)的整體設(shè)計(jì)介紹完畢,可以看到除了這些豐富的組件背后,還有很完整的一套解決方案,很多經(jīng)驗(yàn)都值得我們學(xué)習(xí)和借鑒,不完美的地方也值得我們?nèi)ニ伎?#xff0c;其中有很多技術(shù)細(xì)節(jié)可以深入挖掘。

    把不會(huì)的東西學(xué)會(huì)了,那么你就進(jìn)步了,如果你覺(jué)得這類文章有幫助,也歡迎把它推薦給你身邊的小伙伴。

    下一篇預(yù)告 :Element-UI ?技術(shù)揭秘(3)— Layout 布局組件的設(shè)計(jì)與實(shí)現(xiàn)。

    在這里留下你的爪印喔~

    總結(jié)

    以上是生活随笔為你收集整理的element ui 多个子组件_ElementUI 技术揭秘(2) 组件库的整体设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    中文字幕一区二区在线观看 | 成人一区二区在线 | 国产精品美女久久久久久久网站 | 91九色蝌蚪国产 | 亚洲动漫在线观看 | 欧美一级日韩三级 | 国产精品成人自产拍在线观看 | 亚洲91av| 欧美日韩91 | 国产精品久久久久久久久久久久午 | 国产亚洲精品久 | 韩国三级在线一区 | 久久综合之合合综合久久 | 国产一区二区中文字幕 | 九九九九精品九九九九 | 亚洲乱码中文字幕综合 | 国产成人精品一区二区三区网站观看 | 人人草人人草 | 国产在线更新 | 在线综合 亚洲 欧美在线视频 | 成人免费在线播放视频 | 美女激情影院 | 日韩欧美精品免费 | 久久久久久国产精品久久 | 啪啪免费观看网站 | 香蕉视频在线播放 | 国产日韩一区在线 | 成人毛片一区 | 在线观看视频在线观看 | 在线观看中文字幕av | 久久精品欧美一区 | 亚洲欧美日韩一区二区三区在线观看 | 97视频成人 | 女女av在线| 亚洲另类视频在线 | 久久久精品影视 | 成人一区在线观看 | 国内精品免费 | 色婷婷视频网 | 亚洲丁香久久久 | 免费在线国产视频 | 伊人中文在线 | 成人在线免费观看视视频 | 成人毛片100免费观看 | 日本爽妇网| 久久精品免费看 | 综合网伊人 | 日批在线看 | 中文字幕精品一区二区三区电影 | 久久人人97超碰精品888 | 国产破处视频在线播放 | 国产美女黄网站免费 | 日韩精品一区在线播放 | 国产午夜麻豆影院在线观看 | 91丨九色丨蝌蚪丨对白 | 丁香五月亚洲综合在线 | 狠狠色丁香久久婷婷综合五月 | 在线亚洲观看 | 久久综合色播五月 | freejavvideo日本免费 | 色婷婷综合在线 | 九精品 | 黄色网在线播放 | 欧美另类人妖 | 久久久91精品国产一区二区三区 | 久久久久久久影院 | 91亚色视频在线观看 | 爱情影院aqdy鲁丝片二区 | 91九色九色 | 久热香蕉视频 | 国产丝袜一区二区三区 | 亚洲精品系列 | 成人av av在线 | 久久久精品 | 亚洲va天堂va欧美ⅴa在线 | 国产精品一区二区电影 | 超碰在线天天 | a黄色片 | 亚洲成av人影片在线观看 | 黄色小说18 | 丁香视频全集免费观看 | 色综合天天狠天天透天天伊人 | 欧美日韩午夜 | 亚洲一区二区观看 | 亚洲精品美女在线 | 中文字幕成人网 | 亚洲午夜激情网 | 欧美日韩一区二区在线 | 在线观看成人 | 一区二区精品在线 | 天堂在线视频免费观看 | 视频在线国产 | 久久国产精品免费观看 | 国产在线v| 亚洲激情在线播放 | 精品嫩模福利一区二区蜜臀 | 中文字幕 婷婷 | 久久人人做 | 亚洲激情综合 | 黄色成年片 | 91日韩在线 | 中文字幕在线观看免费高清完整版 | 中文字幕丝袜一区二区 | 日韩久久久久久久久久 | 精品亚洲国产视频 | 国产一级免费观看 | 国产一区在线免费 | 丁香资源影视免费观看 | 中文成人字幕 | 亚洲美女精品 | 日本精品视频免费 | 中文字幕在线影院 | 久草在线高清视频 | 一二区电影| 精品一区在线看 | 亚洲视频精选 | 久久国产成人午夜av影院潦草 | 国产在线不卡一区 | 欧美日韩高清一区二区三区 | 人人爱人人做人人爽 | 亚洲欧美日韩在线一区二区 | 丝袜少妇在线 | 韩日电影在线免费看 | 一色屋精品视频在线观看 | 国产精品国产三级在线专区 | 精品福利国产 | 婷婷激情综合五月天 | 色综合天天综合网国产成人网 | 人人舔人人爽 | www看片网站 | 亚洲精品乱码久久久久久写真 | 91av网址| 日韩激情小视频 | 午夜av免费在线观看 | 婷婷在线资源 | 伊人狠狠色丁香婷婷综合 | 亚洲精品资源在线观看 | 久久国产精品影视 | a级国产乱理论片在线观看 特级毛片在线观看 | 国产一区黄色 | 欧美一级片在线免费观看 | 开心综合网| 国产精品久久久久久久久久久久久 | 久久激情影院 | 婷婷激情在线 | 色婷婷亚洲婷婷 | 欧美一级免费片 | 国产福利不卡视频 | 亚洲国产精品成人精品 | 综合色狠狠 | 在线视频 影院 | 天天射狠狠干 | 天天天天色综合 | 成人午夜片av在线看 | 国产精品va | 日本黄色特级片 | 国内精品久久久久久久久久久 | 久久精品一区二区三区视频 | www免费在线观看 | 韩国av电影网 | 亚洲视频久久久 | 久久国产精品99精国产 | 色噜噜在线观看视频 | 麻豆影视在线播放 | 久久er99热精品一区二区三区 | 丁香 婷婷 激情 | 国产精品久久久久久久免费大片 | 亚洲精品午夜久久久久久久 | 三级毛片视频 | 免费a网站 | 免费色视频网站 | 色狠狠综合天天综合综合 | 一级黄色av | 欧美一区二区精美视频 | 色99导航 | 久久综合亚洲鲁鲁五月久久 | av在线免费网站 | 午夜丰满寂寞少妇精品 | 亚洲国产综合在线 | 精品在线不卡 | 久草在线视频免赞 | 国产自在线观看 | 91精品色 | 最新影院 | 91精品免费看 | 久久99热这里只有精品 | 中文字幕字幕中文 | 亚洲一区日韩精品 | 久久一及片 | 在线观看一区二区视频 | 免费av大全| 成人免费看电影 | 国产日产在线观看 | 婷婷在线网 | 久久99亚洲精品久久 | 国产一区高清在线 | 欧美男男激情videos | 婷婷综合影院 | 91丨九色丨丝袜 | 特片网久久| 亚洲国产69 | 国产资源站| 亚洲区另类春色综合小说校园片 | 欧美专区日韩专区 | 国产资源免费在线观看 | 午夜美女福利直播 | 天天躁天天躁天天躁婷 | 黄色在线观看污 | 成人av电影在线观看 | 超碰九九 | 9999国产精品 | 久久99亚洲精品久久久久 | 91精品免费在线视频 | 全久久久久久久久久久电影 | 成人全视频免费观看在线看 | 人人舔人人舔 | 中文字幕一区二区三区四区 | 天天综合入口 | 少妇自拍av| 国产成人高清在线 | 在线日韩精品视频 | 国产精品专区一 | 91久久久国产精品 | 欧美日韩亚洲精品在线 | 在线免费色视频 | 久久国产精品久久久久 | 亚洲天天摸日日摸天天欢 | 91视视频在线直接观看在线看网页在线看 | 狠狠干天天色 | 久草在线免费看视频 | 美女网站黄在线观看 | 国产精品人成电影在线观看 | av在线看片| 日韩二区三区在线观看 | 国内精品久久天天躁人人爽 | 国产精品麻豆视频 | 国产精品门事件 | 日韩专区在线观看 | 黄色在线观看污 | 亚洲成av人电影 | 久久精品1区2区 | 成人三级视频 | 99精品视频在线观看播放 | 日韩一区二区三区高清在线观看 | 成人h电影 | 中文字幕日韩无 | 成人91在线观看 | 亚洲精品99 | av在线永久免费观看 | 免费高清在线观看电视网站 | 三级av免费看 | 在线影视 一区 二区 三区 | 伊人久久精品久久亚洲一区 | 999视频在线观看 | 国产精品麻 | 美女视频免费一区二区 | 婷婷五综合 | 青青啪| 欧美做受高潮 | 51久久成人国产精品麻豆 | 日韩天堂在线观看 | 亚洲女裸体 | 成人在线观看你懂的 | 又长又大又黑又粗欧美 | 国产九九热 | 日韩在线高清视频 | 九九日九九操 | 亚洲精品成人av在线 | 国产成视频在线观看 | 在线观看一级 | 亚洲精品av在线 | 超碰公开97 | 中文字幕在线观看免费观看 | 日韩在线网址 | 国产二级视频 | 精品久久久久久国产 | 中文字幕xxxx| 国内一区二区视频 | 天天综合婷婷 | 成人网444ppp | 最近2019好看的中文字幕免费 | 人人狠狠综合久久亚洲 | 狠狠搞,com | 麻豆免费观看视频 | 国产一级a毛片视频爆浆 | 亚洲精品久久在线 | 久爱综合| 国产精品久久久久久久久久妇女 | 99热这里是精品 | 四虎在线视频免费观看 | 992tv在线观看 | 在线成人免费电影 | 91成年人在线观看 | 国产成人av电影在线 | 国产精品久久久久久久妇 | 欧美伦理一区二区 | 日韩在线观看视频网站 | 国产香蕉在线 | av在线播放一区二区三区 | 欧美激情第八页 | av免费网站 | 久久精品视频在线观看 | 久久视频这里只有精品 | 91 在线视频 | 国产一级片播放 | 亚洲伦理一区 | 欧美日韩国产高清视频 | 久久99热精品 | 国产成人免费网站 | 成人黄色在线 | 国内精品视频免费 | 亚洲欧美在线综合 | 日韩一区二区在线免费观看 | 九九九视频精品 | 国产精品久久久久一区 | 一级黄色在线视频 | 国产福利免费看 | 日韩videos高潮hd | 日韩免费播放 | 天天干,天天射,天天操,天天摸 | 精品欧美一区二区在线观看 | 日韩免费一级a毛片在线播放一级 | 国产精久久久久久妇女av | 久久久人人爽 | 日韩一级电影在线 | 成人免费视频播放 | 99999精品视频 | 经典三级一区 | 欧美日韩电影在线播放 | 国产美女视频免费 | 西西444www大胆高清图片 | 97成人在线 | 香蕉视频在线播放 | 亚洲精品小区久久久久久 | 97免费在线观看 | 亚洲天堂网站 | 欧美日韩精品在线播放 | 国产精品99免费看 | 狠狠色伊人亚洲综合网站野外 | 成人夜晚看av | 精品久久一区二区三区 | 女人18精品一区二区三区 | 国产欧美久久久精品影院 | 日韩激情久久 | 久热av | 中文字幕在线观看资源 | 国产色网| 伊人成人久久 | 日韩高清免费观看 | 日本中文字幕网站 | 精品国产123| 国产在线观看国语版免费 | www.777奇米| 久久99国产精品视频 | 久久97超碰 | 伊人狠狠色 | 亚洲激情久久 | 欧洲激情综合 | 成人av一区二区三区 | 日韩亚洲精品电影 | 9999精品 | 又黄又刺激的视频 | 久久成人亚洲欧美电影 | 深爱五月激情网 | 亚洲电影影音先锋 | 香蕉视频91 | 免费福利在线视频 | 在线观看视频免费大全 | 免费高清无人区完整版 | 久久久久免费观看 | 欧美精彩视频在线观看 | 久久超碰99| 欧美一级特黄aaaaaa大片在线观看 | 成人a免费看 | 成年人视频在线免费播放 | 黄色片毛片| 玖玖精品在线 | 久久久免费高清视频 | 国产精品永久免费观看 | 91手机在线看片 | 91视视频在线直接观看在线看网页在线看 | 在线香蕉视频 | 7777精品伊人久久久大香线蕉 | 午夜免费福利片 | 国产黄色成人av | 激情久久伊人 | 337p日本欧洲亚洲大胆裸体艺术 | 黄色三级av | 成人动漫一区二区 | 天天干天天怕 | 天天躁日日躁狠狠躁av麻豆 | av国产在线观看 | av网站免费在线 | 五月婷婷播播 | 色婷婷六月天 | 午夜美女福利 | 99精品国产免费久久久久久下载 | 特级黄色电影 | 亚洲精品99久久久久中文字幕 | 久久91久久久久麻豆精品 | 成人久久18免费网站图片 | 丁香婷婷色 | 在线亚洲欧美日韩 | 九九热精品国产 | 国产麻豆电影 | 欧美一区免费在线观看 | 日韩视频区 | 射射色| 亚洲九九九在线观看 | 狠狠色婷婷丁香六月 | 欧美精品第一 | 麻豆精品在线 | 99视频99| www.天天射 | 精品国产aⅴ一区二区三区 在线直播av | 成人资源在线观看 | 97操碰 | 国产一区二区三区网站 | 国产区精品区 | 久久久久久久99 | 521色香蕉网站在线观看 | 日韩在线观看视频一区二区三区 | 国产综合久久 | 狠狠干夜夜爱 | 丁香五月缴情综合网 | 国产精品福利av | 久久久久久网址 | 亚洲高清精品在线 | 天天操天天操天天操天天操天天操天天操 | av福利免费 | 色婷婷五 | 97香蕉超级碰碰久久免费软件 | 日韩区欧美久久久无人区 | 97成人啪啪网| 欧美日韩在线观看一区 | 成人久久18免费网站 | 免费在线一区二区三区 | 国产亚洲一区二区在线观看 | 久久精品一区二区 | 久久网站免费 | 丁香六月久久综合狠狠色 | 91亚洲精品久久久蜜桃借种 | 久久久久在线 | 日韩在线观看你懂得 | 天天天天天天干 | 中文不卡视频在线 | 久久久久久高潮国产精品视 | 97精品国产97久久久久久久久久久久 | 亚洲另类久久 | 人人澡人人爱 | 成人av资源 | 91视频高清免费 | 欧美男同网站 | 色www精品视频在线观看 | 激情久久一区二区三区 | 又黄又色又爽 | 亚洲理论电影网 | 精品一区二区免费在线观看 | 国产亚洲一区二区在线观看 | 国产精品久久久久久欧美 | 成人毛片在线视频 | av中文字幕免费在线观看 | 亚洲精欧美一区二区精品 | 四虎影视国产精品免费久久 | 久久成人精品视频 | 国产精品久久久久婷婷二区次 | 午夜国产在线观看 | 97夜夜澡人人双人人人喊 | 国产xvideos免费视频播放 | 视频国产一区二区三区 | 国产精品完整版 | 91成人在线视频 | 免费在线看成人av | 亚洲视频综合在线 | 天天操夜夜操国产精品 | 免费观看午夜视频 | 草莓视频在线观看免费观看 | 中文字幕一区2区3区 | 九九精品毛片 | 97碰碰视频 | 成年美女黄网站色大片免费看 | 91av视频免费在线观看 | av大片免费在线观看 | 国产精品成人久久 | 国产97在线看 | av福利超碰网站 | 玖玖在线播放 | 国产成人一区二区在线观看 | 色婷婷综合久久久久中文字幕1 | 国产欧美精品一区二区三区四区 | 国产黄色片一级 | 在线观看一区二区视频 | 日本中文字幕视频 | 青青河边草观看完整版高清 | 欧美成人视 | 狠狠综合网 | 久久久av电影 | 欧美人操人| 天天亚洲| 天天操天天干天天操天天干 | 国产三级视频在线 | 中文资源在线播放 | 在线观看播放av | 国产中文字幕在线观看 | 不卡中文字幕在线 | 天天射网 | 国产男男gay做爰 | 欧美电影黄色 | 三级av免费看 | 欧美日韩国产页 | 九九免费在线观看视频 | 夜夜操天天干, | 黄色.com| 97在线观看视频 | 国产经典av | 在线电影 你懂得 | 四虎影视成人永久免费观看亚洲欧美 | 中文字幕乱码日本亚洲一区二区 | 国产视频日韩视频欧美视频 | 久久久性 | 国产美女网站在线观看 | 天天操天天操天天操天天操天天操 | 少妇啪啪av入口 | 国产尤物在线视频 | 五月婷婷激情六月 | 免费观看日韩 | 在线观看成人国产 | 国产精品美女久久久久久久久 | 在线免费av网 | 国产精品6 | 国产中文字幕久久 | 91av在线视频免费观看 | 国产涩图 | 97夜夜澡人人爽人人免费 | 中文字幕之中文字幕 | 蜜臀av性久久久久蜜臀av | 69国产成人综合久久精品欧美 | 国产欧美在线一区二区三区 | 亚洲1区 在线 | 亚洲我射av | 香蕉久久国产 | 欧美精品一区二区免费 | 97天堂网| 国产成人精品av在线观 | 国产天天爽 | 97视频免费在线看 | 韩国三级在线一区 | 国产小视频在线观看 | 久久精品99国产精品亚洲最刺激 | 日韩视频1区 | 久久久九九 | 97人人模人人爽人人喊网 | 久久久99国产精品免费 | 91亚·色| 插插插色综合 | 丁香六月婷婷开心婷婷网 | 中文字幕精品视频 | 日韩欧美国产精品 | 黄色av免费看 | 色欧美成人精品a∨在线观看 | 欧美日韩三级在线观看 | 日韩免费在线观看网站 | 玖玖视频在线 | 日韩丝袜| 日韩中文在线观看 | 日韩高清一二区 | 日韩精品三区四区 | 久久成人免费 | 久久看毛片 | 99理论片| 婷婷伊人五月 | 中文字幕在线看片 | 亚洲精品视频久久 | 国产免费美女 | 在线电影 你懂得 | 精品国产成人在线影院 | 99在线观看精品 | 国产精品中文 | 亚洲视频axxx | 91在线视频在线观看 | 精品在线视频一区二区三区 | 99热国内精品 | 国产精品中文字幕在线观看 | 激情综合婷婷 | 久久免费在线观看视频 | 亚洲精品成人 | 免费高清av在线看 | 激情综合网婷婷 | 99日精品| 日韩av手机在线看 | 婷婷婷国产在线视频 | 免费视频久久久 | 亚洲综合最新在线 | 日本一区二区高清不卡 | 久久视频这里只有精品 | 97品白浆高清久久久久久 | av在线播放中文字幕 | 国产人免费人成免费视频 | 一区二区三区在线观看免费视频 | 91九色性视频 | 成人av免费电影 | 成人av视屏| 亚洲国产精品日韩 | 色悠悠久久综合 | 精品国产免费一区二区三区五区 | 日韩视频一二三区 | 亚洲国产中文字幕 | 久久毛片网 | 狠狠狠色丁香综合久久天下网 | 亚洲一区二区三区四区在线视频 | 综合色综合色 | 亚洲国产成人高清精品 | 涩涩色亚洲一区 | 久久er99热精品一区二区 | 色综合久久88色综合天天6 | 欧美亚洲国产日韩 | 日韩手机视频 | 中文字幕免 | 97在线视| 精品国产美女在线 | 久久久在线免费观看 | 18女毛片 | 中文字幕在线视频第一页 | 亚洲精品色婷婷 | 久久久久久久国产精品 | 欧美一区日韩一区 | 天天人人综合 | 欧美一级免费高清 | 97电影在线看视频 | 日韩午夜在线观看 | 美女精品在线观看 | 天天色成人 | 91在线91 | 亚洲婷婷网 | 成人aⅴ视频 | 亚洲国产视频直播 | 在线观看视频一区二区三区 | 日韩av电影中文字幕在线观看 | 国产黄色免费 | 日日操操操 | 久久色在线观看 | 日韩精品视频免费看 | 日日日爽爽爽 | 亚洲精品91天天久久人人 | 国产精品18久久久久久久网站 | 中文国产字幕在线观看 | 亚洲精品久久久蜜桃直播 | 美女网站视频免费黄 | 九九激情视频 | 久久99久久精品国产 | 国产理论一区二区三区 | 国产视频久 | 天天做日日做天天爽视频免费 | 日韩在线大片 | 日本中文字幕视频 | 久久综合久久88 | 国产精品一二 | 欧美日韩国产亚洲乱码字幕 | 成人av电影在线播放 | 在线免费色 | 色av色av色av| 正在播放 久久 | 中文字幕 影院 | 欧美一二在线 | 久热久草在线 | 午夜狠狠干 | 国产美女网站视频 | 免费在线观看成人av | 亚洲精品乱码久久久久久蜜桃不爽 | 亚洲精品成人 | 麻豆播放| 视频在线观看国产 | 日本69hd | 久草在线视频中文 | 国产一区二区在线播放视频 | 日日爽天天爽 | 久久 精品一区 | 午夜精品久久久久久99热明星 | 国产午夜精品在线 | 天天干天天干天天射 | 色综合久久久久综合体 | 免费观看一级一片 | 亚洲国产精品一区二区久久,亚洲午夜 | 国产一区二区三区高清播放 | zzijzzij亚洲日本少妇熟睡 | 久久国产精品系列 | 91av视频免费观看 | 国产日韩精品在线观看 | 在线黄色国产电影 | 黄色一级免费电影 | 国产女教师精品久久av | 国产一级片网站 | 人人盈棋牌 | 青春草视频| 午夜国产福利在线 | 亚洲精品在线网站 | 91精品免费在线观看 | 一本一本久久a久久精品综合小说 | 成人av免费看 | 中文字幕国产视频 | 免费在线观看不卡av | aaawww| 国产视频一 | 九色91视频 | 国产亚洲永久域名 | 91最新地址永久入口 | 黄色三级免费观看 | 在线观看国产永久免费视频 | 欧美永久视频 | 国产一区二区三区在线免费观看 | 国产视频亚洲视频 | 99久久99热这里只有精品 | 国产在线播放一区二区 | 偷拍精偷拍精品欧洲亚洲网站 | 国产高清成人 | 久草在线视频精品 | 91人人在线 | 国产黄色大全 | 免费久久99精品国产 | 曰本三级在线 | 午夜久久视频 | 麻豆91在线看 | 三级黄在线 | 日韩www在线 | 精品一区电影国产 | 西西4444www大胆无视频 | 国产在线观看地址 | 国产视频日韩视频欧美视频 | 婷婷激情av | 欧美国产日韩一区二区三区 | 91精品国产乱码久久桃 | 欧美成人在线免费观看 | 成人超碰97 | 黄色毛片在线观看 | 人成免费网站 | 天堂av网站 | 一级久久精品 | 99久久久国产精品免费99 | 一级免费黄视频 | 日韩av午夜 | 久久在线精品视频 | 一本一本久久a久久精品综合小说 | 亚洲电影自拍 | 亚洲 综合 国产 精品 | 国产精品成人av在线 | 国产九九在线 | 91麻豆产精品久久久久久 | 999抗病毒口服液 | 精品999在线观看 | 99久久夜色精品国产亚洲96 | 亚洲综合色网站 | 一区二区三区免费在线观看 | 国产麻豆精品久久一二三 | 99精品在线免费视频 | 久久精品国产精品亚洲精品 | 99久久国产免费,99久久国产免费大片 | 精品久久久久久久久久久久久久久久久久 | 日韩欧美在线一区二区 | 日韩av一卡二卡三卡 | 亚洲黄色片 | 欧美日韩国内在线 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 欧美另类高清 | 国产区精品视频 | 亚洲va综合va国产va中文 | 最新午夜 | 国内亚洲精品 | 国产亚洲精品久久久久久移动网络 | 国产四虎在线 | 久草新在线 | 国产不卡免费av | 天天干,天天射,天天操,天天摸 | 日本99久久 | 国产视频久久久 | 香蕉网站在线观看 | 人人超碰人人 | 久草观看 | 麻豆播放 | 成人av电影免费 | 97超碰人人模人人人爽人人爱 | 国产精品免费视频观看 | 成人一级电影在线观看 | 97视频在线免费 | 99久久免费看| 涩五月婷婷 | 亚洲va在线va天堂 | 亚洲一区二区三区毛片 | 国产伦精品一区二区三区无广告 | 噜噜色官网 | 亚洲狠狠婷婷综合久久久 | 99免费在线观看视频 | 日韩精品久久久久久中文字幕8 | 日韩精品不卡 | ,午夜性刺激免费看视频 | 亚洲精品在线视频观看 | 午夜精品区 | 午夜精品久久 | 在线观看成人 | 国产一级精品在线观看 | 精品日韩中文字幕 | 中文有码在线视频 | 美女视频黄是免费的 | 黄色福利网站 | 色综合久久精品 | 亚洲黄色区 | www国产亚洲精品久久麻豆 | 国产精品免费视频久久久 | 天天干天天干天天射 | 成人在线视频免费观看 | 亚洲精品大片www | 国产在线自 | 日日干 天天干 | 91丨九色丨蝌蚪丨老版 | 日本久久久久久久久 | 91看片在线播放 | 久久手机看片 | 午夜精品久久久久久中宇69 | 99热这里只有精品在线观看 | 日日夜夜精品免费 | 成人免费看片网址 | 91理论电影 | 精品国产理论 | 正在播放国产91 | 久久久99精品免费观看app | 欧日韩在线视频 | av免费黄色| 日韩三级.com | 综合中文字幕 | 四季av综合网站 | 色香蕉在线 | 99日精品 | 99热这里| 美女中文字幕 | 欧美男同视频网站 | 免费看三级黄色片 | 99视频精品全部免费 在线 | 久久久网站 | 国产99久久久久久免费看 | 91在线精品秘密一区二区 | 丁五月婷婷| 婷婷国产一区二区三区 | 97成人资源站 | 就色干综合 | 99精彩视频在线观看免费 | 在线观看深夜福利 | 在线看国产精品 | 高潮毛片无遮挡高清免费 | 狠狠躁日日躁狂躁夜夜躁av | 天堂av免费 | 免费观看完整版无人区 | 久久精品伊人 | 色欧美88888久久久久久影院 | 在线免费试看 | 久久精品欧美 | 黄色免费网战 | 天天色天天干天天色 | 爱爱一区 | 1024手机在线看 | 中文字幕电影网 | 国内毛片毛片 | 88av视频 | 狠狠干网址| 精品伊人久久久 | 国产91免费在线 | 国模精品一区二区三区 | av丁香花| 国内精品久久久久影院一蜜桃 | 丁香六月国产 | 中国黄色一级大片 | 69久久99精品久久久久婷婷 | 国产精品久久久久久久久久久久久久 | 日韩欧美精选 | 2023av在线 | 成人中文字幕av | www.xxxx变态.com| 国产成人综合在线观看 | 91夫妻自拍 | 精品一区二区三区久久久 | 国产欧美日韩精品一区二区免费 | 丰满少妇高潮在线观看 | 日韩伦理片hd | 成人毛片一区二区三区 | 99久久精品免费看国产 | 亚洲精品1区2区3区 超碰成人网 | 亚洲国产日韩精品 | 日韩二级毛片 | 国产一区免费视频 | 久久精品高清 | 久久久久久久久久久影院 | 精品少妇一区二区三区在线 | 欧美激情奇米色 | 久久久网址 | 男女激情片在线观看 | 狠狠色狠狠色综合日日92 | 亚洲精品一区二区三区四区高清 | 久久久久久久福利 | 日韩精品极品视频 | 三级黄色免费 | 国产高清中文字幕 | 91看片看淫黄大片 | 91精品在线免费观看视频 | 亚洲永久字幕 | 日日干夜夜操视频 | 看毛片网站 | 久久成人视屏 | 精品久久久影院 | 玖玖国产精品视频 | 97天天干 | 国产黄色片免费在线观看 | 美女视频永久黄网站免费观看国产 | 中文亚洲欧美日韩 | 国产在线a视频 | 91精品国产一区 | 国产免费高清视频 | 九九在线高清精品视频 | 韩国av三级| 久久久久这里只有精品 | 国产资源网| 国产色婷婷精品综合在线手机播放 | 九九色综合 | www.午夜视频 | 中文字幕在线观看2018 | 国产xxxx性hd极品 | 91精品久久久久久综合乱菊 | 粉嫩高清一区二区三区 | 91日韩精品 | 91视频高清 | 六月丁香婷婷久久 | 蜜臀久久99精品久久久无需会员 | 黄色大片入口 | 99久精品视频 | 国产美女精品人人做人人爽 | 夜夜骑天天操 | 成人一区二区在线 | av免费福利 | 久久综合给合久久狠狠色 | 2018亚洲男人天堂 | 国产精品视频你懂的 | 国产一区二区电影在线观看 | 日韩有码第一页 | 亚洲综合少妇 | 亚洲91av| 亚洲精品小视频 | 久久成人人人人精品欧 | 91精品国产91热久久久做人人 | 国产精品av一区二区 | 四虎www. | 欧美一进一出抽搐大尺度视频 | 中文字幕免费观看全部电影 | 色橹橹欧美在线观看视频高清 | 亚洲最快最全在线视频 | 欧美激情第一页xxx 午夜性福利 | 国产成人免费精品 | 婷婷5月激情5月 | www.天堂av| 91成人看片 | 在线观看www视频 | 日韩性xxx | 九色琪琪久久综合网天天 | 丁香婷婷综合激情五月色 | 天天干夜夜 | 98精品国产自产在线观看 | 最近免费在线观看 | 日本一区二区三区视频在线播放 | 岛国精品一区二区 | 日韩精品1区2区 | 天天干天天摸天天操 | 午夜久久久久久久 | 丁香婷婷激情网 | 国产精品一区二区白浆 | 欧亚日韩精品一区二区在线 | 亚洲v欧美v国产v在线观看 | 久久免费av | 国产无套精品久久久久久 | 97在线影院| 国产高清免费观看 | 日韩av免费一区二区 | 日韩国产在线观看 | 五月天网页 | 99免费在线视频 | 亚洲性xxxx | www国产亚洲| 在线免费观看一区二区三区 | 亚洲国产午夜视频 | 国产成人精品区 | 成人毛片一区 | 亚洲精品国产精品国自产观看浪潮 | 一二区电影 | 天天天天色射综合 | 探花视频免费在线观看 | 色综合久久久久 | 中文字幕在线播放第一页 | 亚洲1级片 | 日韩激情av在线 | 91成人黄色 | 97色视频在线| 国产成人三级在线 | 91精品国产成人观看 |