• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    React中常見的動畫實現的幾種方式

    來源:懂視網 責編:小采 時間:2020-11-27 22:21:55
    文檔

    React中常見的動畫實現的幾種方式

    React中常見的動畫實現的幾種方式:現在,用戶對于前端頁面的要求已經不能滿足于實現功能,更要有顏值,有趣味。除了整體 UI 的美觀,在合適的地方添加合適的動畫效果往往比靜態頁面更具有表現力,達到更自然的效果。比如,一個簡單的 loading 動畫或者頁面切換效果不僅能緩解用戶的等待情緒,
    推薦度:
    導讀React中常見的動畫實現的幾種方式:現在,用戶對于前端頁面的要求已經不能滿足于實現功能,更要有顏值,有趣味。除了整體 UI 的美觀,在合適的地方添加合適的動畫效果往往比靜態頁面更具有表現力,達到更自然的效果。比如,一個簡單的 loading 動畫或者頁面切換效果不僅能緩解用戶的等待情緒,

    現在,用戶對于前端頁面的要求已經不能滿足于實現功能,更要有顏值,有趣味。除了整體 UI 的美觀,在合適的地方添加合適的動畫效果往往比靜態頁面更具有表現力,達到更自然的效果。比如,一個簡單的 loading 動畫或者頁面切換效果不僅能緩解用戶的等待情緒,甚至通過使用品牌 logo 等形式,默默達到品牌宣傳的效果。

    React 作為最近幾年比較流行的前端開發框架,提出了虛擬 DOM 概念,所有 DOM 的變化都先發生在虛擬 DOM 上,通過 DOM diff 來分析網頁的實際變化,然后反映在真實 DOM 上,從而極大地提升網頁性能。然而,在動畫實現方面,React 作為框架并不會直接給組件提供動畫效果,需要開發者自行實現,而傳統 web 動畫大多數都通過直接操作實際 DOM 元素來實現,這在 React 中顯然是不被提倡的。那么,在 React 中動畫都是如何實現的呢?

    所有動畫的本質都是連續修改 DOM 元素的一個或者多個屬性,使其產生連貫的變化效果,從而形成動畫。在 React 中實現動畫本質上與傳統 web 動畫一樣,仍然是兩種方式: 通過 css3 動畫實現和通過 js 修改元素屬性。只不過在具體實現時,要更為符合 React 的框架特性,可以概括為幾類:

    1. 基于定時器或 requestAnimationFrame(RAF) 的間隔動畫;
    2. 基于 css3 的簡單動畫;
    3. React 動畫插件 CssTransitionGroup;
    4. 結合 hook 實現復雜動畫;
    5. 其他第三方動畫庫。

    一、基于定時器或 RAF 的間隔動畫

    最早,動畫的實現都是依靠定時器 setIntervalsetTimeout 或者 requestAnimationFrame (RAF) 直接修改 DOM 元素的屬性。不熟悉 React 特性的開發者可能會習慣性地通過 ref 或者 findDOMNode() 獲取真實的 DOM 節點,直接修改其樣式。然而,通過 ref 直接獲取真實 DOM 并對其操作是是不被提倡使用,應當盡量避免這種操作。

    因此,我們需要將定時器或者 RAF 等方法與 DOM 節點屬性通過 state 聯系起來。首先,需要提取出與變化樣式相關的屬性,替換為 state ,然后在合適的生命周期函數中添加定時器或者 requestAnimationFrame 不斷修改 state ,觸發組件更新,從而實現動畫效果。

    示例

    以一個進度條為例,代碼如下所示:

    // 使用requestAnimationFrame改變state
    import React, { Component } from 'react';
    
    export default class Progress extends Component { 
     constructor(props) {
     super(props);
     this.state = {
     percent: 10
     };
     }
    
     increase = () => {
     const percent = this.state.percent;
     const targetPercent = percent >= 90 ? 100 : percent + 10;
     const speed = (targetPercent - percent) / 400;
     let start = null;
     const animate = timestamp => {
     if (!start) start = timestamp;
     const progress = timestamp - start;
     const currentProgress = Math.min(parseInt(speed * progress + percent, 10), targetPercent);
     this.setState({
     percent: currentProgress
     });
     if (currentProgress < targetPercent) {
     window.requestAnimationFrame(animate);
     }
     };
     window.requestAnimationFrame(animate);
     }
    
     decrease = () => {
     const percent = this.state.percent;
     const targetPercent = percent < 10 ? 0 : percent - 10;
     const speed = (percent - targetPercent) / 400;
     let start = null;
     const animate = timestamp => {
     if (!start) start = timestamp;
     const progress = timestamp - start;
     const currentProgress = Math.max(parseInt(percent - speed * progress, 10), targetPercent);
     this.setState({
     percent: currentProgress
     });
     if (currentProgress > targetPercent) {
     window.requestAnimationFrame(animate);
     }
     };
     window.requestAnimationFrame(animate);
     }
    
     render() {
     const { percent } = this.state;
    
     return (
     <div>
     <div className="progress">
     <div className="progress-wrapper" >
     <div className="progress-inner" style = {{width: `${percent}%`}} ></div>
     </div>
     <div className="progress-info" >{percent}%</div>
     </div>
     <div className="btns">
     <button onClick={this.decrease}>-</button>
     <button onClick={this.increase}>+</button>
     </div>
     </div>
     );
     }
    }

    在示例中,我們在 increasedecrease 函數中構建線性過渡函數 animationrequestAnimationFrame 在瀏覽器每次重繪前執行會執行過渡函數,計算當前進度條 width 屬性并更新該 state ,使得進度條重新渲染。該示例的效果如下所示:

    這種實現方式在使用 requestAnimationFrame 時性能不錯,完全使用純 js 實現,不依賴于 css,使用定時器時可能出現掉幀卡頓現象。此外,還需要開發者根據速度函數自己計算狀態,比較復雜。

    二、基于 css3 的簡單動畫

    當 css3 中的 animationtransition 出現和普及后,我們可以輕松地利用 css 實現元素樣式的變化,而不用通過人為計算實時樣式。

    示例

    我們仍以上面的進度條為例,使用 css3 實現進度條動態效果,代碼如下所示:

    import React, { Component } from 'react';
    
    export default class Progress extends Component { 
     constructor(props) {
     super(props);
     this.state = {
     percent: 10
     };
     }
    
     increase = () => {
     const percent = this.state.percent + 10;
     this.setState({
     percent: percent > 100 ? 100 : percent,
     })
     }
    
     decrease = () => {
     const percent = this.state.percent - 10;
     this.setState({
     percent: percent < 0 ? 0 : percent,
     })
     }
    
     render() {
     // 同上例, 省略
     ....
     }
    }
    .progress-inner {
     transition: width 400ms cubic-bezier(0.08, 0.82, 0.17, 1);
     // 其他樣式同上,省略
     ...
    }

    在示例中, increasedecrease 函數中不再計算 width ,而是直接設置增減后的寬度。需要注意的是,在 css 樣式中設置了 transition 屬性,該屬性在其指定的 transition-property 發生變化時自動實現樣式的動態變化效果,并且可以設置不同的速度效果的速度曲線。該示例的效果如下圖所示,可以發現,與上一個例子不同的是,右側的進度數據是直接變化為目標數字,沒有具體的變化過程,而進度條的動態效果因為不再是線性變化,效果更為生動。

    基于 css3 的實現方式具有較高的性能,代碼量少,但是只能依賴于 css 效果,對于復雜動畫也很難實現。此外,通過修改 state 實現動畫效果,只能作用于已經存在于 DOM 樹中的節點。如果想用這種方式為組件添加入場和離場動畫,需要維持至少兩個 state 來實現入場和離場動畫,其中一個 state 用于控制元素是否顯示,另一個 state 用于控制元素在動畫中的變化屬性。在這種情況下,開發者需要花費大量精力來維護組件的動畫邏輯,十分復雜繁瑣。

    三、React 動畫插件 CssTransitionGroup

    React 曾為開發者提供過動畫插件 react-addons-css-transition-group ,后交由社區維護,形成現在的 react-transition-group ,該插件可以方便地實現組件的入場和離場動畫,使用時需要開發者額外安裝。 react-transition-group 包含 CSSTransitionGroupTransitionGroup 兩個動畫插件,其中,后者是底層 api,前者是后者的進一步封裝,可以較為便捷地實現 css 動畫。

    示例

    以一個動態增加tab的為例,代碼如下:

    import React, { Component } from 'react'; 
    import { CSSTransitionGroup } from 'react-transition-group';
    
    let uid = 2; 
    export default class Tabs extends Component { 
     constructor(props) {
     super(props);
     this.state = {
     activeId: 1,
     tabData: [{
     id: 1,
     panel: '選項1'
     }, {
     id: 2,
     panel: '選項2'
     }]
     };
     }
    
     addTab = () => {
     // 添加tab代碼
     ...
     }
    
     deleteTab = (id) => {
     // 刪除tab代碼
     ...
     }
    
     render() {
     const { tabData, activeId } = this.state;
    
     const renderTabs = () => {
     return tabData.map((item, index) => {
     return (
     <div
     className={`tab-item${item.id === activeId ? ' tab-item-active' : ''}`}
     key={`tab${item.id}`}
     >
     {item.panel}
     <span className="btns btn-delete" onClick={() => this.deleteTab(item.id)}>✕</span>
     </div>
     );
     })
     }
    
     return (
     <div>
     <div className="tabs" >
     <CSSTransitionGroup
     transitionName="tabs-wrap"
     transitionEnterTimeout={500}
     transitionLeaveTimeout={500}
     >
     {renderTabs()}
     </CSSTransitionGroup>
     <span className="btns btn-add" onClick={this.addTab}>+</span>
     </div>
     <div className="tab-cont">
     cont
     </div>
     </div>
     );
     }
    }
    /* tab動態增加動畫 */
    .tabs-wrap-enter {
     opacity: 0.01;
    }
    
    .tabs-wrap-enter.tabs-wrap-enter-active {
     opacity: 1;
     transition: all 500ms ease-in;
    }
    
    .tabs-wrap-leave {
     opacity: 1;
    }
    
    .tabs-wrap-leave.tabs-wrap-leave-active {
     opacity: 0.01;
     transition: all 500ms ease-in;
    }

    CSSTransitionGroup 可以為其子節點添加額外的 css 類,然后通過 css 動畫達到入場和離場動畫效果。為了給每個 tab 節點添加動畫效果,需要先將它們包裹在 CSSTransitionGroup 組件中。 當設定 transitionName 屬性為 'tabs-wrapper'transitionEnterTimeout 為400毫秒后,一旦 CSSTransitionGroup 中新增節點,該新增節點會在出現時被添加上 css 類 'tabs-wrapper-enter' ,然后在下一幀時被添加上 css 類 'tabs-wrapper-enter-active' 。由于這兩個 css 類中設定了不同的透明度和 css3 transition 屬性,所以節點實現了透明度由小到大的入場效果。400毫秒后 css 類 'tabs-wrapper-enter''tabs-wrapper-enter-active' 將會同時被移除,節點完成整個入場動畫過程。離場動畫的實現類似于入場動畫,只不過被添加的 css 類名為 'tabs-wrapper-leave''tabs-wrapper-leave-active' 。該示例效果如下圖所示:

    CSSTransitionGroup 支持以下7個屬性:

    其中,入場和離場動畫是默認開啟的,使用時需要設置 transitionEnterTimeouttransitionLeaveTimeout 。值得注意的是, CSSTransitionGroup 還提供出現動畫(appear),使用時需要設置 transitionAppearTimeout 。那么,出現動畫和入場動畫有什么區別呢?當設定 transitionAppeartrue 時, CSSTransitionGroup 在 初次渲染 時,會添加一個出現階段。在該階段中, CSSTransitionGroup 的已有子節點都會被相繼添加 css 類 'tabs-wrapper-appear''tabs-wrapper-appear-active' ,實現出現動畫效果。因此, 出現動畫僅適用于 CSSTransitionGroup 在初次渲染時就存在的子節點 ,一旦 CSSTransitionGroup 完成渲染,其子節點就只可能有入場動畫(enter),不可能有出現動畫(appear)。

    此外,使用 CSSTransitionGroup 需要注意以下幾點:

    1. CSSTransitionGroup 默認在 DOM 樹中生成一個 span 標簽包裹其子節點,如果想要使用其他 html 標簽,可設定 CSSTransitionGroupcomponent 屬性;
    2. CSSTransitionGroup 的子元素必須添加 key 值才會在節點發生變化時,準確地計算出哪些節點需要添加入場動畫,哪些節點需要添加離場動畫;
    3. CSSTransitionGroup 的動畫效果只作用于直接子節點,不作用于其孫子節點;
    4. 動畫的結束時間不以 css 中 transition-duration 為準,而是以 transitionEnterTimeouttransitionLeaveTimeoutTransitionAppearTimeout 為準,因為某些情況下 transitionend 事件不會被觸發,詳見 MDN transitionend 。

    CSSTransitionGroup 實現動畫的優點是:

    1. 簡單易用,可以方便快捷地實現元素的入場和離場動畫;
    2. 與 React 結合,性能比較好。

    CSSTransitionGroup 缺點也十分明顯:

    1. 局限于出現動畫,入場動畫和離場動畫;
    2. 由于需要制定 transitionName ,靈活性不夠;
    3. 只能依靠 css 實現簡單的動畫。

    四、結合 hook 實現復雜動畫

    在實際項目中,可能需要一些更炫酷的動畫效果,這些效果僅依賴于 css3 往往較難實現。此時,我們不妨借助一些成熟的第三方庫,如 jQuery 或 GASP,結合 React 組件中的生命周期鉤子方法 hook 函數,實現復雜動畫效果。除了 React 組件正常的生命周期外, CSSTransitionGroup 的底層 api TransitonGroup 還為其子元素額外提供了一系列特殊的生命周期 hook 函數,在這些 hook 函數中結合第三方動畫庫可以實現豐富的入場、離場動畫效果。

    TransisitonGroup 分別提供一下六個生命周期 hook 函數:

    1. componentWillAppear(callback)
    2. componentDidAppear()
    3. componentWillEnter(callback)
    4. componentDidEnter()
    5. componentWillLeave(callback)
    6. componentDidLeave()

    它們的觸發時機如圖所示:

    示例

    GASP 是一個 flash 時代發展至今的動畫庫,借鑒視頻幀的概念,特別適合做長時間的序列動畫效果。本文中,我們用 TransitonGroupreact-gsap-enhancer (一個可以將 GSAP 應用于 React 的增強庫)完成一個圖片畫廊,代碼如下:

    import React, { Component } from 'react'; 
    import { TransitionGroup } from 'react-transition-group'; 
    import GSAP from 'react-gsap-enhancer' 
    import { TimelineMax, Back, Sine } from 'gsap';
    
    class Photo extends Component { 
     constructor(props) {
     super(props);
     }
    
     componentWillEnter(callback) {
     this.addAnimation(this.enterAnim, {callback: callback})
     }
    
     componentWillLeave(callback) {
     this.addAnimation(this.leaveAnim, {callback: callback})
     }
    
     enterAnim = (utils) => {
     const { id } = this.props;
     return new TimelineMax()
     .from(utils.target, 1, {
     x: `+=${( 4 - id ) * 60}px`,
     autoAlpha: 0,
     onComplete: utils.options.callback,
     }, id * 0.7);
     }
    
     leaveAnim = (utils) => {
     const { id } = this.props;
     return new TimelineMax()
     .to(utils.target, 0.5, {
     scale: 0,
     ease: Sine.easeOut,
     onComplete: utils.options.callback,
     }, (4 - id) * 0.7);
     }
    
     render() {
     const { url } = this.props;
     return (
     <div className="photo">
     <img src={url} />
     </div>
     )
     }
    }
    
    const WrappedPhoto = GSAP()(Photo);
    
    export default class Gallery extends Component { 
     constructor(props) {
     super(props);
     this.state = {
     show: false,
     photos: [{
     id: 1,
     url: 'http://img4.imgtn.bdimg.com/it/u=1032683424,3204785822&fm=214&gp=0.jpg'
     }, {
     id: 2,
     url: 'http://imgtu.5011.net/uploads/content/20170323/7488001490262119.jpg'
     }, {
     id: 3,
     url: 'http://tupian.enterdesk.com/2014/lxy/2014/12/03/18/10.jpg'
     }, {
     id: 4,
     url: 'http://img4.imgtn.bdimg.com/it/u=360498760,1598118672&fm=27&gp=0.jpg'
     }]
     };
     }
    
     toggle = () => {
     this.setState({
     show: !this.state.show
     })
     }
    
     render() {
     const { show, photos } = this.state;
    
     const renderPhotos = () => {
     return photos.map((item, index) => {
     return <WrappedPhoto id={item.id} url={item.url} key={`photo${item.id}`} />;
     })
     }
    
     return (
     <div>
     <button onClick={this.toggle}>toggle</button>
     <TransitionGroup component="div">
     {show && renderPhotos()}
     </TransitionGroup>
     </div>
     );
     }
    }

    在該示例中,我們在子組件 PhotocomponentWillEntercomponentWillLeave 兩個 hook 函數中為每個子組件添加了入場動畫 enterAnim 和 離場動畫 LeaveAnim 。在入場動畫中,使用 TimeLineMax.from(target, duration, vars, delay) 方式建立時間軸動畫,指定了每個子組件的動畫移動距離隨 id 增大而減小,延期時間隨著 id 增大而增大,離場動畫中每個子組件的延期時間隨著 id 增大而減小,從而實現根據組件 id 不同具有不同的動畫效果。實際使用時,你可以根據需求對任一子組件添加不同的效果。該示例的效果如下圖所示:

    在使用 TransitionGroup 時,在 componentnWillAppear(callback)componentnWillEntercallback)componentnWillLeave(callback) 函數中一定要 在函數邏輯結束后調用 callback ,以保證 TransitionGroup 能正確維護子節點的狀態序列 。

    結合 hook 實現動畫可以支持各種復雜動畫,如時間序列動畫等,由于依賴第三方庫,往往動畫效果比較流暢,用戶體驗較好。但是第三方庫的引入,需要開發者額外學習對應的 api,也提升了代碼復雜度。

    五、其他第三方動畫庫

    此外,還有很多優秀的第三方動畫庫,如 react-motion ,Animated, velocity-react 等,這些動畫庫在使用時也各有千秋。

    Animated

    Animated 是一個跨平臺的動畫庫,兼容 React 和 React Native。由于在動畫過程中,我們只關心動畫的初始狀態、結束狀態和變化函數,并不關心每個時刻元素屬性的具體值,所以 Animatied 采用聲明式的動畫,通過它提供的特定方法計算 css 對象,并傳入 Animated.div 實現動畫效果。

    示例

    我們使用 Animated 實現一個圖片翻轉的效果,代碼如下。

    import React, { Component } from 'react'; 
    import Animated from 'animated/lib/targets/react-dom';
    
    export default class PhotoPreview extends Component { 
     constructor(props) {
     super(props);
     this.state = {
     anim: new Animated.Value(0)
     };
     }
    
     handleClick = () => {
     const { anim } = this.state;
     anim.stopAnimation(value => {
     Animated.spring(anim, {
     toValue: Math.round(value) + 1
     }).start();
     });
     }
    
     render() {
     const { anim } = this.state;
    
     const rotateDegree = anim.interpolate({
     inputRange: [0, 4],
     outputRange: ['0deg', '360deg']
     });
    
     return (
     <div>
     <button onClick={this.handleClick}>向右翻轉</button>
     <Animated.div
     style={{
     transform: [{
     rotate: rotateDegree
     }]
     }}
     className="preivew-wrapper"
     >
     <img
     alt="img"
     src="http://img4.imgtn.bdimg.com/it/u=1032683424,3204785822&fm=214&gp=0.jpg"
     />
     </Animated.div>
     </div>
     );
     }
    }

    在該示例中,我們希望實現每點擊一次按鈕,圖片向右旋轉90°。在組件初始化時新建了一個初始值為 0 的 Animated 對象 this.state.anim ,在 render 函數中通過插值函數 interpolate 根據 Animated 對象的當前值計算得到對應的旋轉角度 rotateDegree 。我們假設每點擊一次按鈕, Animated 對象的值加 1,相應地圖像轉動90°,所以,設置 interpolate 函數的輸入區間為[0, 4],輸出區間為['0deg', '360deg']進行線性插值。如果 Animated 對象當前值為 2,對應的旋轉角度就是 180deg。在組件渲染結構中,需要使用 Animated.div 包裹動畫節點,并將變化的元素屬性封裝為 css 對象作為 stlye 傳入 Animated.div 中。在點擊事件中,考慮到按鈕可以多次連續點擊,我們首先使用 stopAnimation 停止當前動畫,并獲取 Animated 對象的當前值 value ,隨后使用 Animated.spring 函數開啟一次彈簧動畫過程,從而實現一個流暢的動畫效果。由于每次轉動停止時,我們希望圖片的翻轉角度都是90°的整數倍,所以需要對 Animated.spring 的終止值進行取整。最終我們實現了如下效果:

    使用時需要注意一下幾點:

    1. Animated 對象的值和其插值結果只能作用于 Animated.div 節點;
    2. interpolate 默認會根據輸入區間和輸出區間進行線性插值,如果輸入值超出輸入區間不受影響,插值結果默認會根據輸出區間向外延展插值,可以通過設置 extrapolate 屬性限制插值結果區間。

    Animated 在動畫過程中不直接修改組件 state ,而是通過其新建對象的組件和方法直接修改元素的屬性,不會重復觸發 render 函數,是 React Native 中非常穩定的動畫庫。但是在 React 中存在低版本瀏覽器兼容問題,且具有一定學習成本。

    結語

    當我們在 React 中實現動畫時,首先要考量動畫的難易程度和使用場景,對于簡單動畫,優先使用 css3 實現,其次是基于 js 的時間間隔動畫。如果是元素入場動畫和離場動畫,則建議結合 CSSTransitionGroup 或者 TransitionGroup 實現。當要實現的動畫效果較為復雜時,不妨嘗試一些優秀的第三方庫,打開精彩的動效大門。

    Ps. 本文所有示例代碼可訪問 github 查看

    參考資料:

    react-transition-group

    react-gsap-enhancer

    A Comparison of Animation Technologies

    React Animations in Depth

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    React中常見的動畫實現的幾種方式

    React中常見的動畫實現的幾種方式:現在,用戶對于前端頁面的要求已經不能滿足于實現功能,更要有顏值,有趣味。除了整體 UI 的美觀,在合適的地方添加合適的動畫效果往往比靜態頁面更具有表現力,達到更自然的效果。比如,一個簡單的 loading 動畫或者頁面切換效果不僅能緩解用戶的等待情緒,
    推薦度:
    標簽: 動畫 實現 方式
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产美女久久精品香蕉69| 亚洲精品tv久久久久久久久| 久久亚洲精品成人av无码网站| 四虎成人精品无码| 国产精品亚洲专区在线观看| 亚洲午夜久久久精品影院| 九色精品视频在线观看| 无码人妻精品一区二区三区在线| 99热门精品一区二区三区无码| 四虎影视国产精品永久在线| 老司机精品影院91| 国产精品一久久香蕉国产线看观看| 丰满人妻熟妇乱又仑精品| 国产精品日韩欧美久久综合 | 久久国产欧美日韩精品| 国产精品人人做人人爽| 久久精品国产亚洲AV无码麻豆| 亚洲国产精品人久久| 少妇人妻偷人精品免费视频| 国产精品成人精品久久久| 精品亚洲A∨无码一区二区三区| 国产成人高清精品一区二区三区| 亚洲av午夜福利精品一区| 国产精品被窝福利一区| 国产精品亚洲成在人线| 亚洲?V乱码久久精品蜜桃| 一区二区精品在线| 2022国产精品自产拍在线观看 | 中文字幕亚洲精品| 无码精品日韩中文字幕| 精品国产91久久久久久久a | 欧美激情精品久久久久久久| 国产日韩一区在线精品欧美玲| 在线观看自拍少妇精品| 黑巨人与欧美精品一区 | 无码人妻精品一区二| 精品国产91久久久久久久a| Xx性欧美肥妇精品久久久久久| 国产精品乱码高清在线观看| 亚洲国产精品一区二区三区久久| 欧美精品xxxxbbbb|