整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          如何在Vue.js中創(chuàng)建模態(tài)彈窗

          載說明:原創(chuàng)不易,未經(jīng)授權(quán),謝絕任何形式的轉(zhuǎn)載

          開篇

          模態(tài)框(彈出層對(duì)話框)在大多數(shù)現(xiàn)代應(yīng)用程序中非常常見。它們主要用于呈現(xiàn)簡潔的信息,非常適合顯示廣告和促銷內(nèi)容。模態(tài)框提供了一種快速傳達(dá)信息的方式,并提供了用戶友好的關(guān)閉選項(xiàng)。

          在本文中,我們將使用Vuejs構(gòu)建一個(gè)彈出模態(tài)框。該模態(tài)框?qū)ㄒ粋€(gè)取消或關(guān)閉按鈕,以方便用戶在完成任務(wù)后關(guān)閉它。此外,我們還將實(shí)現(xiàn)一個(gè)功能,允許用戶在模態(tài)框區(qū)域外點(diǎn)擊以關(guān)閉它。

          模態(tài)彈出組件

          <script setup lang="ts">
          import { ref } from 'vue';
          
          const message = ref('This is a modal popup');
          const emit = defineEmits(['close']);
          
          const closeModal = () => {
            emit('close');
          };
          </script>
          <template>
            <div class="popup" @click.self="closeModal">
              <div class="popup-content">
                <div class="popup-header">
                  <h2 class="popup-title">{{ message }}</h2>
                  <button class="popup-close-button" @click.prevent="closeModal">X</button>
                </div>
                <article>
                  <div class="popup-content-text">
                    This is a simple modal popup in Vue.js
                  </div>
                </article>
              </div>
            </div>
          </template>

          Script Section

          <script setup lang="ts">
          import { ref } from 'vue';
          const message = ref('This is a modal popup');
          const emit = defineEmits(['close']);
          const closeModal = () => {
           emit('close');
          };
          </script>

          在這個(gè)部分,我們從Vue中導(dǎo)入所需的功能。

          • ref 用于創(chuàng)建一個(gè)包含在模態(tài)框中顯示的響應(yīng)式變量消息。
          • emit用于定義一個(gè)名為“close”的事件,該事件可被觸發(fā)以關(guān)閉模態(tài)框。
          • closeModal是一個(gè)函數(shù),當(dāng)調(diào)用時(shí)會(huì)觸發(fā)“close”事件,從而有效地關(guān)閉模態(tài)框。

          Template Section

          <template>
             <div class="popup" @click.self="closeModal">
             <div class="popup-content">
             <div class="popup-header">
             <h2 class="popup-title">{{ message }}</h2>
             <button class="popup-close-button" @click.prevent="closeModal">X</button>
           </div>
           <article>
             <div class="popup-content-text">
             This is a simple modal popup in Vue.js
             </div>
           </article>
           </div>
           </div>
          </template>

          本段代碼義了模板中模態(tài)框的結(jié)構(gòu)。

          • 具有“popup”類的最外層div用作模態(tài)框的背景。
          • @click.self="closeModal"事件監(jiān)聽器附加到背景上,允許在其內(nèi)容之外點(diǎn)擊時(shí)關(guān)閉模態(tài)框。
          • 內(nèi)容包括一個(gè)標(biāo)題(popup-title)和一個(gè)關(guān)閉按鈕(popup-close-button)。
          • 在標(biāo)題下方,有一個(gè)文章部分,其中包含了模態(tài)框的主要內(nèi)容。

          渲染模態(tài)框組件

          <script setup lang="ts">
          import { ref } from 'vue'
          import Popup from "@/components/Popup.vue"; // @ is an alias to /src
          
          const msg = ref('Hello World!')
          const isOpened = ref(false)
          
          </script>
          <template>
            <div>
              <h1>{{ msg }}</h1>
              <button @click="isOpened = !isOpened">Open Popup</button>
              <Teleport to="body">
                <Popup v-if="isOpened" @close="isOpened = !isOpened" />
              </Teleport>
            </div>
          </template>

          數(shù)據(jù)和狀態(tài)管理:

          代碼使用Vue的ref函數(shù)創(chuàng)建了兩個(gè)響應(yīng)式變量:

          • - msg: 初始設(shè)置為“Hello World!”的文本消息被存儲(chǔ)。
          • - isOpened: 這是一個(gè)布爾變量,初始值為false,表示彈出窗口是否打開或關(guān)閉。

          按鈕點(diǎn)擊事件

          模板中有一個(gè)帶有點(diǎn)擊事件監(jiān)聽器(@click)的<button>元素。當(dāng)按鈕被點(diǎn)擊時(shí),它會(huì)切換isOpened變量的值,從而有效地打開或關(guān)閉彈出窗口。

          導(dǎo)入彈出框組件

          • 代碼導(dǎo)入了一個(gè)彈出組件(Popup.vue)。
          • 在模板中,使用v-if條件渲染彈出窗口組件。只有當(dāng)isOpened變量為true時(shí)(v-if="isOpened"),彈出窗口才會(huì)顯示,表示彈出窗口應(yīng)該是打開的。
          • <Teleport>用于將彈出窗口組件移動(dòng)到HTML文檔的元素中。這樣可以確保彈出窗口在當(dāng)前組件的DOM層次結(jié)構(gòu)之外渲染,并且可以顯示在頁面上的其他內(nèi)容之上。

          組件之間的通信:

          • 當(dāng)需要關(guān)閉彈出組件時(shí),Popup組件會(huì)觸發(fā)一個(gè)關(guān)閉事件@close。父組件使用@close事件監(jiān)聽器來監(jiān)聽此關(guān)閉事件。
          • 當(dāng)Popup組件發(fā)出事件時(shí),它切換isOpened變量,從而關(guān)閉彈出窗口。

          您可以在CodeSandbox上使用本文中設(shè)計(jì)的代碼進(jìn)行操作。

          https://codesandbox.io/s/suspicious-kepler-993dmh?file=%2Fsrc%2Fviews%2FHome.vue%3A0-420

          結(jié)束

          由于文章內(nèi)容篇幅有限,今天的內(nèi)容就分享到這里,文章結(jié)尾,我想提醒您,文章的創(chuàng)作不易,如果您喜歡我的分享,請(qǐng)別忘了點(diǎn)贊和轉(zhuǎn)發(fā),讓更多有需要的人看到。同時(shí),如果您想獲取更多前端技術(shù)的知識(shí),歡迎關(guān)注我,您的支持將是我分享最大的動(dòng)力。我會(huì)持續(xù)輸出更多內(nèi)容,敬請(qǐng)期待。

          作為 TOB 的業(yè)務(wù)方,我們偶爾會(huì)收到一些如下圖所示的反饋。

          作為 PC 頁面為主的業(yè)務(wù)方,大多數(shù)用戶在一天的工作中,可能都不太會(huì)刷新或者重新打開我們的頁面,導(dǎo)致我們在下午或者白天發(fā)布的前端版本,往往需要到幾個(gè)小時(shí)甚至第二天,才能覆蓋到 98% 以上的用戶。

          我們統(tǒng)計(jì)了 bscm 平臺(tái) 5 次下午 2-3 點(diǎn)左右發(fā)布的版本,在發(fā)布后每個(gè)時(shí)間段內(nèi)老版本用戶的占比情況。選擇這個(gè)時(shí)間點(diǎn)發(fā)布的原因是這個(gè)時(shí)間點(diǎn)基本是平臺(tái)用戶的上班時(shí)間,是最有可能出現(xiàn)用戶已經(jīng)打開了頁面同時(shí)我們在發(fā)布新代碼的場景的,比較具有代表性。按平臺(tái)用戶六七點(diǎn)下班來看,我們可以看到還有將近 6% 的用戶在當(dāng)天是會(huì)一直訪問老版本的前端代碼的,按照 bscm 平臺(tái) 1w+的 uv 來看,約有 600 多人會(huì)可能遇到前端版本過低導(dǎo)致的使用問題。

          方案

          彈窗內(nèi)容

          彈窗的觸發(fā)條件

          首先介紹兩個(gè)概念,本地版本號(hào)和云端版本號(hào)。本地版本號(hào)是用戶請(qǐng)求到的前端頁面的代碼版本號(hào),是用戶訪問頁面時(shí)決定;云端版本號(hào)可以理解為最新前端版本號(hào),它是每次開發(fā)者發(fā)布前端代碼時(shí)決定的。

          判斷觸發(fā)條件的時(shí)機(jī)

          有了彈窗的觸發(fā)條件,我們還需要去決定什么時(shí)候判斷彈窗是否滿足觸發(fā)的條件,上面也提到了,出現(xiàn)這類問題的場景多見于用戶在使用過程中,開發(fā)者進(jìn)行了前端代碼發(fā)布,那我們主要可以有兩個(gè)類型的時(shí)機(jī)去進(jìn)行觸發(fā)條件的判斷。

          1. 前端代碼去感知什么時(shí)候有新版本的代碼發(fā)布了,去進(jìn)行條件判斷(消息推送)
          2. 前端在一定的條件下主動(dòng)去判斷觸發(fā)條件(輪詢,請(qǐng)求后端接口時(shí),一些中頻前端事件的監(jiān)聽)

          我們對(duì)這些時(shí)機(jī)在更新是否及時(shí),判斷次數(shù)多少、實(shí)現(xiàn)成本高低等維度進(jìn)行一個(gè)對(duì)比。

          ?? 越多表示這個(gè)維度得分越高

          根據(jù)表格可以看到 websocket 消息推送和前端事件監(jiān)聽這兩種方案綜合來看是更合適一些的,但是前端事件監(jiān)聽其實(shí)它的劣勢在實(shí)際運(yùn)用場景中會(huì)被弱化(一天的上線數(shù)量有限,請(qǐng)求次數(shù)一天不會(huì)多太多次),但是實(shí)現(xiàn)成本遠(yuǎn)低于 websocket,所以無疑是實(shí)際落地場景中比較理想的選擇。

          根據(jù) can i use 的結(jié)果我們也可以發(fā)現(xiàn) visibilitychange 事件也基本符合我們目前 B 端頁面對(duì)于 PC 瀏覽器的要求。

          版本號(hào)的生成

          本地版本號(hào)

          本地版本號(hào)是用戶訪問時(shí)決定的,那無疑頁面的 html 文件就是這個(gè)版本號(hào)存在的最佳載體,我們可以在打包時(shí)通過 plugin 給 html 文件注入一個(gè)版本號(hào)。

          云端版本號(hào)

          云端版本號(hào)的選擇則有很多方式了,數(shù)據(jù)庫、cdn 等等都可以滿足需求。不過考慮到實(shí)現(xiàn)成本和泳道的情況,想了一下兩個(gè)思路一個(gè)是打包的同時(shí)生成一個(gè) version.json 文件,配一個(gè)路由去訪問;另一個(gè)是直接訪問對(duì)應(yīng)的 html 代碼,解析出注入的版本號(hào),二者各自有適合的場景。

          微前端的適配

          我們現(xiàn)在的大多數(shù)項(xiàng)目都包含了主應(yīng)用和子應(yīng)用,那其實(shí)不管是子應(yīng)用的更新還是主應(yīng)用的更新都應(yīng)該有相關(guān)的提示,而且相互獨(dú)立,但同時(shí)又需要保證彈窗不同時(shí)出現(xiàn)。

          想要沿用之前的方案其實(shí)只需要解決三個(gè)問題。

          1. 主子應(yīng)用的本地版本號(hào)標(biāo)識(shí)需要有區(qū)分,因?yàn)?html 文件只有一個(gè),需要能在 html 文件中區(qū)分出哪個(gè)應(yīng)用的版本是什么,這個(gè)我們只需在 plugin 中注入標(biāo)識(shí)即可解決。
          2. 云端版本號(hào)請(qǐng)求時(shí)也要請(qǐng)求對(duì)應(yīng)的云端版本號(hào),這個(gè)目前采用的方案是主應(yīng)用去請(qǐng)求唯一的 version.json 文件,因?yàn)橹鲬?yīng)用路由是唯一的,子應(yīng)用則去請(qǐng)求最新的 html 資源文件,解析出云端版本號(hào)。
          3. 不重復(fù)彈窗我們只需要在展示彈窗前,多加一個(gè)是否已經(jīng)有彈窗展示的判斷即可了。

          具體實(shí)現(xiàn)

          版本號(hào)的寫入和讀取

          監(jiān)聽時(shí)機(jī)和頻控邏輯

          正如前文提到的,本身版本發(fā)布不是一個(gè)高頻事件,但是監(jiān)聽事件的頻次有時(shí)候可能過高了,不希望頻繁的去進(jìn)行觸發(fā)條件判斷。同時(shí)如果出現(xiàn)一天內(nèi)多次發(fā)布的場景,也不希望這個(gè)彈窗對(duì)于用戶有過多的打擾,所以需要去添加一個(gè)頻控邏輯。

          具體代碼

          plugin

          /* eslint-disable */
          import { CoraWebpackPlugin, WebpackCompiler } from '@ies/eden-web-build';
          const fs = require('fs');
          const path = require('path');
          const cheerio = require('cheerio');
          
          interface IVersion {
            name?: string; // 編譯完的文件夾名稱
            subName?: string; // 子應(yīng)用的名稱,主應(yīng)用可以不傳
          }
          
          export class VersionPlugin implements CoraWebpackPlugin {
            readonly name = 'versionPlugin'; // 插件必須要有一個(gè)名字,這個(gè)名字不能和已有插件沖突
            private _version: number;
            private _name: string;
            private _subName: string;
            constructor(params: IVersion) {
              this._version = new Date().getTime();
              this._name = params?.name || 'build';
              this._subName = params?.subName || ''
            }
            apply(compiler: WebpackCompiler): void {
              compiler.hooks.afterCompile.tap('versionPlugin', () => {
                try {
                  const filePath = path.resolve(`./${this._name}/template/version.json`);
                  fs.writeFile(filePath, JSON.stringify({ version: this._version }), (err: any) => {
                    if (err) {
                      console.log('@@@err', err);
                    }
                  });
                  const htmlPath = path.resolve(`./${this._name}/template/index.html`);
                  const data = fs.readFileSync(htmlPath);
                  const $ = cheerio.load(data);
                  $('body').append(`<div id="${this._subName}versionTag" style="display: none">${this._version}</div>`);
                  fs.writeFile(htmlPath, $.html(), (err: any) => {
                    if (err) {
                      console.log('@@@htmlerr', err);
                    }
                  });
                } catch (err) {
                  console.log(err);
                }
              });
            }
          }
          

          彈窗組件

          import React, { useEffect } from 'react';
          
          import { Modal } from '@ecom/auxo';
          import axios from 'axios';
          import moment from 'moment';
          
          export interface IProps {
            isSub?: boolean; // 是否為子應(yīng)用
            subName?: string; // 子應(yīng)用名稱
            resourceUrl?: string; // 子應(yīng)用的資源url
          }
          
          export type IType = 'visibilitychange' | 'popstate' | 'init';
          
          export default React.memo<IProps>(props => {
            const { isSub = false, subName = '', resourceUrl = '' } = props || {};
          
            const cb = (latestVersion: number | undefined, currentVersion: number | undefined, type: IType) => {
              try {
                // 版本落后,提示可以刷新頁面
                if (latestVersion && currentVersion && latestVersion > currentVersion) {
                  // 提醒過了就設(shè)置一個(gè)更新提示過期時(shí)間,一天內(nèi)不需要再提示了,彈窗過期時(shí)間暫時(shí)全局只需要一個(gè)!!
                  localStorage.setItem(`versionUpdateExpireTime`, moment().endOf('day').format('x'));
                  if (!document.getElementById('versionModalTitle')) {
                    Modal.confirm({
                      title: <div id="versionModalTitle">版本更新提示</div>,
                      content:
                        '您已經(jīng)長時(shí)間未使用此頁面,在此期間平臺(tái)有過更新,如您此時(shí)在頁面中沒有填寫相關(guān)信息等操作,請(qǐng)點(diǎn)擊刷新頁面使用最新版本!',
                      okText: <div data-text={`前端版本升級(jí)引導(dǎo)-立即更新 ${type}`}>刷新頁面</div>,
                      cancelText: <div data-text={`前端版本升級(jí)引導(dǎo)-我知道了 ${type}`}>我知道了</div>,
                      onCancel: () => {
                        console.log('fe-version-watcher INFO: 未更新~');
                      },
                      onOk: () => {
                        location.reload();
                      },
                    });
                  }
                }
                // 不管版本是否落后,半小時(shí)內(nèi)都不需要去重新請(qǐng)求判斷
                localStorage.setItem(`versionInfoExpireTime`, String(new Date().getTime() + 1000 * 60 * 30));
              } catch {}
            };
          
            const formatVersion = (text?: string) => (text ? Number(text) : undefined);
          
            useEffect(() => {
              try {
                const fn = function (type: IType) {
                  if (document.visibilityState === 'visible') {
                    /**
                     * @desc 為了防止打擾,版本更新每個(gè)應(yīng)用一天只提示一次 所以過期時(shí)間設(shè)為當(dāng)天23:59:59,沒過期則直接return
                     */
                    if (Number(localStorage.getItem(`versionUpdateExpireTime`) || 0) >= new Date().getTime()) {
                      return;
                    }
                    /**
                     * @desc 不需要每次切換頁面都去判斷資源,每次從服務(wù)器獲取到的版本信息,給半個(gè)小時(shí)的緩存時(shí)間,需要區(qū)分子應(yīng)用
                     */
                    if (Number(localStorage.getItem(`versionInfoExpireTime`) || 0) > new Date().getTime()) {
                      return;
                    }
          
                    if (!isSub) {
                      /**
                       * @desc 主應(yīng)用使用version.json文件來獲取最新的版本號(hào)
                       */
                      const dom = document.getElementById('versionTag');
                      const currentVersion = formatVersion(dom?.innerText);
                      axios.get(`/version?timestamp=${new Date().getTime()}`).then(res => {
                        const latestVersion = res?.data?.version;
                        cb(latestVersion, currentVersion, type);
                      });
                    } else {
                      /**
                       * @desc 子應(yīng)用使用最新html中的innerText來獲取最新版本號(hào)
                       */
                      if (resourceUrl) {
                        const dom = document.getElementById(`${subName}versionTag`);
                        const currentVersion = dom?.innerText ? Number(dom?.innerText) : undefined;
                        axios.get(resourceUrl).then(res => {
                          /** ignore_security_alert */
                          try {
                            const html = res.data;
                            const doc = new DOMParser().parseFromString(html, 'text/html');
                            const latestVersion = formatVersion(doc.getElementById(`${subName}versionTag`)?.innerText);
                            cb(latestVersion, currentVersion, type);
                          } catch {}
                        });
                      }
                    }
                  }
                };
                const visibleFn = () => {
                  fn('visibilitychange');
                };
                const routerFn = () => {
                  fn('popstate');
                };
                if (isSub) {
                  // 子應(yīng)用可能會(huì)有緩存,初始化的時(shí)候先判斷一次
                  fn('init');
                }
                document.addEventListener('visibilitychange', visibleFn);
                window.addEventListener('popstate', routerFn);
                return () => {
                  document.removeEventListener('visibilitychange', visibleFn);
                  window.removeEventListener('popstate', routerFn);
                };
              } catch {}
            }, []);
          
            return <div />;
          });
          

          如何接入

          主應(yīng)用版本

          1. 安裝依賴
          npm i @ecom/fe-version-watcher-plugin # 安裝plugin 
          npm i @ecom/logistics-supply-chain-fe-version-watcher # 安裝引導(dǎo)彈窗
          
          1. 引入 versionPlugin,自動(dòng)生成 version.json + html 文件中自動(dòng)注入
          import { VersionPlugin } from '@ecom/fe-version-watcher-plugin';
          
          // 有些項(xiàng)目打包后template文件夾下的名字不是build而是build_cn
          // 可以根據(jù)自己項(xiàng)目的實(shí)際情況傳入{name: build_cn}
          
          {
              ...,
              plugins: [
                  ...,
                  [VersionPlugin, {}],
              ]
           }
          
          1. 引入版本引導(dǎo)彈窗
          import { FeVersionWatcher } from '@ecom/logistics-supply-chain-fe-version-watcher';
          
          <FeVersionWatcher />
          
          1. goofy 新增路由配置,/version 指向 version.json 文件 (或者其它方式可以使得/version 的路由指向該 version.json 文件)

          預(yù)告

          采用 version.json 的方案,引入 FersionWatcher 組件就不再需要任何參數(shù),目前主應(yīng)用只支持這種模式。未來也將參考子應(yīng)用,主應(yīng)用支持讀取 html 中版本標(biāo)識(shí)的能力,將配置路由的工作改成組件 props 傳入資源 url,開發(fā)者可以根據(jù)實(shí)際情況自行選擇。

          子應(yīng)用版本

          1. 安裝依賴
          npm i @ecom/fe-version-watcher-plugin # 安裝plugin
          npm i @ecom/logistics-supply-chain-fe-version-watcher # 安裝引導(dǎo)彈窗
          
          1. 引入 versionPlugin, html 文件中自動(dòng)注入版本號(hào),需要子應(yīng)用標(biāo)識(shí)參數(shù)(必填)
          import { VersionPlugin } from '@ecom/fe-version-watcher-plugin';
          
          // 有些項(xiàng)目打包后template文件夾下的名字不是build而是build_cn
          // 可以根據(jù)自己項(xiàng)目的實(shí)際情況傳入{name: build_cn}
          
          {
              ...,
              plugins: [
                  ...,
                  [VersionPlugin, {subName: 'general-supplier', name: 'build_cn'}],
              ]
           }
          
          1. 引入版本引導(dǎo)彈窗(subName 和 plugin 中保持一致,resourceUrl 為配置的子應(yīng)用路由)
          import { FeVersionWatcher } from '@ecom/logistics-supply-chain-fe-version-watcher';
          
          // subName需要和plugin的參數(shù)保持一致,resourceUrl為子應(yīng)用資源的路徑(子引用goofy上配置的路由)
          <FeVersionWatcher isSub subName="general-supplier" resourceUrl="/webApp/general-supplier" />
          

          resourceUrl一般就是goofy上配置的路由設(shè)置,,如果不同平臺(tái)有區(qū)分,可以動(dòng)態(tài)傳入。

          如何調(diào)試/效果展示

          發(fā)布成功后,可以根據(jù)如下步驟測試:

          1. 刪除 localstorage 中相關(guān)的 value
          2. 修改 html 中的 version,改成一個(gè)比較小的數(shù)值即可
          3. 切換路由,或者隱藏/打開頁面,出現(xiàn)彈窗

          收益統(tǒng)計(jì)

          同樣我們截取了 4 次該平臺(tái) 2-3 點(diǎn)發(fā)布的版本情況,可以看到老版本用戶的 uv 占比有著明顯的下降。

          上線至今共計(jì)提示 10 萬+用戶,幫助約 5 萬人次及時(shí)更新了前端代碼。


          作者:費(fèi)昀鋒

          來源:微信公眾號(hào):字節(jié)前端 ByteFE

          出處:https://mp.weixin.qq.com/s/PT0PZ3S1Cvh2nltcIKwa3g

          生javascript實(shí)現(xiàn)帶動(dòng)畫的提示型彈窗,常用于網(wǎng)站彈層的彈窗也有很多,一般用插件比較多,所以今天就來寫一寫該功能,如有錯(cuò)誤之處請(qǐng)指出!

          彈出跟消失都有放大縮小動(dòng)畫在里面!

          實(shí)現(xiàn)方法:

          html:

          可以自己輸入內(nèi)容,再點(diǎn)擊彈出即可看到彈窗效果

          css:

          javascript:


          主站蜘蛛池模板: 激情综合丝袜美女一区二区 | 色窝窝无码一区二区三区成人网站 | 中文字幕一区日韩在线视频| 四虎成人精品一区二区免费网站| 亚洲码一区二区三区| 91视频一区二区三区| 亚洲Av永久无码精品一区二区| 国产乱人伦精品一区二区在线观看 | 久久久久成人精品一区二区| 2021国产精品一区二区在线| 亚洲AV网一区二区三区| 国产情侣一区二区三区| AV鲁丝一区鲁丝二区鲁丝三区| 国产一区二区精品久久岳√ | 精品少妇一区二区三区在线| 国产成人久久精品区一区二区| 亚洲av永久无码一区二区三区| 国产精品亚洲综合一区| 亚洲欧美日韩一区二区三区| 亚洲成AV人片一区二区密柚| 国产精品美女一区二区三区| 久久一区不卡中文字幕| 亚洲AV无码一区二三区 | 亚洲色精品三区二区一区| 伊人久久大香线蕉av一区| 一区二区三区内射美女毛片| 无码日韩精品一区二区三区免费| av无码免费一区二区三区| 亚洲欧洲∨国产一区二区三区| 八戒久久精品一区二区三区| 竹菊影视欧美日韩一区二区三区四区五区 | 成人区人妻精品一区二区三区| 亚拍精品一区二区三区| 91久久精品国产免费一区 | 亚洲欧洲一区二区| 色婷婷一区二区三区四区成人网 | 手机看片一区二区| 精品国产亚洲一区二区三区 | 乱子伦一区二区三区| 精品无人区一区二区三区在线 | 国产午夜三级一区二区三|