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

跨端組件實踐 - 移動時代的前端

移動開發
本文為百度前端研發部資深工程師王集鵠在2014 Qcon北京大會上所做的分享,文章分析了移動前端所面臨的變化和問題,并且提出了跨端組件的解決方案,能夠解決跨平臺的前端UI適配問題。

背景

***不變的就是變化

從業十多年,互聯網的變化非常大:最初使用的電腦只有 8M 內存、32M 硬盤,現在口袋里裝的手機已經是 2G 內存、16G 閃存,網絡也從 56K 變成了 1.5M+。這個時代的人是幸福的……

這個期間也見證了 Web 時代的繁榮,從 C/S 走到 B/S。

現在無論是郵件、購物還是游戲、社交、工作等等,在電腦上都能找到滿意的 Web 應用或站點。

可是這種景象在移動時代并沒有看到。

現場小調查:請問你在手機上和 PC 上用什么方式刷微博?

  • 大部分的人不會在 PC 上用客戶端刷微博
  • 大部分的人不會在手機上用瀏覽器刷微博

結論符合預期,先從變化上分析問題

移動互聯網發生了什么變化?

屏幕更小

  • 顯示區更寶貴,廣告區更難擺放
  • 頁面布局更講究,內容主次更為重要

隨身攜帶

  • 24 小時待機
  • 根據地理位置提供更精準的服務

觸摸操作

  • 雙手很難并行
  • 虛擬鍵盤沒有物理鍵盤便捷

更豐富的內置設備

  • 前后置攝像頭 / 閃關燈
  • 麥克風 / 揚聲器
  • 振動器,靜音狀態也可以知道有消息到達
  • 電子指南針 / 陀螺儀
  • 藍牙 / WiFi / NFC

離線使用場景

  • 在沒有信號
  • 資費不足

沒有持久能源

  • 電池需要充電
  • 計算能力和待機時間沖突

設備碎片化 * 特別是 Android 各種屏幕尺寸、各種 ROM

移動互聯網的變化帶來了新的機遇和挑戰

機遇

移動市場高速增長

艾瑞咨詢數據顯示,2013 年中國移動互聯網市場規模達到 1059.8 億元,同比增速 81.2%, 預計到 2017 年,市場規模將增長約 4.5 倍,接近 6000 億。移動互聯正在深刻影響人們的日常生活,移動互聯網市場進入高速發展通道。【查看來源】

挑戰

HTML5 / CSS3 技術在移動端受限

What stops developers from using HTML5?【查看來源】

性能測試

為什么開發者不選擇 HTML5 構建移動應用? 前三個原因是:

  • 性能問題,流暢度與 Native 差距較大
  • 硬件接口缺失,不能控制藍牙、閃關燈、振動、WiFi、NFC 等等
  • 難以集成本地元素,不能使用桌面圖標、訂閱推送等

這是我們用主流的機型做的性能測試

性能測試

不難看出 Native 和 Web 的性能依舊差距很大,包括主流韓國和國產機型。

人眼刷新率平均是 24 幀 / 秒,低于這個值用戶就會感覺到跳幀。

當然這些問題在 PC 時代也碰到過!那時是怎么解決的?

影響前端的技術

通過瀏覽器擴展本地能力

  • 使用 ActiveX / NPAPI 技術
  • 最經典的插件就是 Flash,雖然它已經淡出了移動時代

JavaScript Engine 進化

  • V8 出現后,JavaScript 的性能提升了數倍
  • 結合高性能的引擎 NodeJS 也使 JavaScript 在后端獲得了新生

HTML5 / CSS3

  • 擴展了本地能力,如地理定位、錄音錄像、本地存儲等

但這些影響在移動端是有限的

移動時代前端的現狀

Flash 不能使用

Adobe 將停止開發移動版 Flash

NPAPI 即將退役

Google 今年開始屏蔽 NPAPI 插件【查看來源】

瀏覽器插件可以擴展本地能力的同時,也會帶來穩定性和安全性的問題。

怎么解決性能瓶頸和本地能力缺失的問題?

JS Binding,通過 JavaScript 直接調用 Native API

JS Translate,通過編譯器將 JavaScript 翻譯成 Native 語言

  • 如號稱上帝語言的 haXe 可以翻譯成 Java、JavaScript、C++、PHP 的語言

Native App,直接使用 Native 技術,從頭再來

  • 廣義的前端就是要面向用戶界面和交互
  • 前端技術也有向全端和全棧的發展趨勢

選擇手游創業的 @大城小胖 近期做了一個教學視頻,專門介紹 JSBinding 大家可以參考:When iOS loves JS

以上技術可以解決問題,但不能發揮 Web 自然跨端、迭代方便(不同等待漫長的上架時間)的優勢

我們還得尋找一些適合自己的方案。

Hybrid 混合應用方案

本地服務,網頁通過 HTTP / WebSocket 與本地服務通信,使用本地能力

本地服務

  • 在 Android 里寫一個不難,參考 NanoHttpd DIY 一個移動版的 HTTP 服務
    • 優勢:能夠無縫兼容所有瀏覽器
    • 劣勢:通信容易被嗅探和偽造;很難利用 UI 組件

加殼,這是最常用的技術

加殼

  • 有較成熟的框架可以使用,如:Cordova
  • 通過使用和擴展插件,獲得本地能力

Google 也有投入 Cordova 的項目 Chrome apps on Android and iOS

本地服務和加殼方式,都能訪問本地能力。但后者本地能力在同一個進程里調度,安全性和便利性相對要高。

回到主題,什么是跨端組件?

自動響應端能力的組件

跨端組件示意

  • 受到響應式網頁設計理念的啟發,界面布局可以根據運行環境自動響應和調整,那么本地能力也可以這樣
  • 如在普通瀏覽器里使用 HTML5 / CSS3 構造組件,在提供本地能力的環境里使用 Native View 構造組件。
  • 在提供本地能力的環境里,界面會更流暢;在沒有本地能力的環境里應用是完整的。

跨端組件解決的問題:

  • 滿足 UI 需要局部流暢的需求
  • 滿足運行在各種環境的需求

特點

  • 同一套 API
  • 更好地使用運行環境提供的能力

PC 時代也有這樣的組件,如:Raphaël 一款矢量圖組件,在具 VML 的環境里使用 VML,其他環境里使用 SVG,并保持同一套 API。發散一想:jQueryWebUploader(適配 Flash 和 HTML5)也都是自動響應各種運行環境。

成本總是伴隨著收益,解決老問題就會帶來新的問題

當頁面發生滾動時,Native View 怎么和網頁元素一起滾動?還有 Reflow 時怎么調整 Native View 的位置?

UI 融合的問題

滾動的問題在 Android 中處理比較方便。因為 WebView 繼承至:ViewGroup / AbsoluteLayout,我們只需要將 WebView 作為 Native View 的容器就可以搞定這個問題。

Reflow 發生的頻率不高,就用了定時器這種簡單粗暴的方法。

#p#

跨端組件研發的步驟

確定需求

哪些組件適合做跨端組件?

計算量大,需要流暢

  • 圖冊瀏覽
  • 地圖
  • 多媒體播放器
  • 3D渲染
  • 圖像識別,二維碼識別、手勢識別

減少操作步驟,省去授權

  • 錄像、錄音

HTML5能力增強

  • 地理定位增強,結合 WiFi
  • Canvas 性能增強(參考:FastCanvas

開發環境

天朝的網絡大家知道的,主要找一些代理和鏡像

設計 API

發現很多前端團隊都開始使用和關注 Web Components

在跨端組件的落地上,我們也選擇這種方式來提供 API,原因是:

  • 降低學習成本,保留原生 Web 組件的使用方式
  • 降低業務代碼維護工作

目前移動端原生還不支持這個標準,還得選用框架適配,如:Polymer

跨端組件 HTML5 示例代碼:

  1. <body> 
  2.     <div id="mapBox"> 
  3.         <light-map width="350" height="400" center="116.404,39.915" zoom="11"></light-map> 
  4.     </div> 
  5. </body> 

將組件的HTML部分放到需要顯示的位置,然后就和普通的Element一樣使用:

  • var lightMap = document.querySelector('light-map'); 可以通過 DOM 樹操作
  • lightMap.addEventLister() 添加事件
  • lightMap.setAttribute()、lightMap.getAttribute() 設置屬性

組件開發

Cordova Plugin 開發

plugin.xml 配置需要的權限、JavaScript 命名空間、文件對應的工程目錄等待。細節請參考官方文檔

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" 
  3.       id="com.baidu.light.flashlight" 
  4.       version="0.2.7"> 
  5.     <name>Flashlight</name> 
  6.     <description>Cordova Flashlight Plugin</description> 
  7.     <license>Apache 2.0</license> 
  8.     <keywords>cordova,battery</keywords> 
  9.     <repo>https://github.com/zswang/light-flashlight.git</repo> 
  10.     <issue>https://github.com/zswang/light-flashlight/issue</issue> 
  11.  
  12.     <js-module src="www/flashlight.js" name="flashlight"> 
  13.         <clobbers target="light.flashlight" /> 
  14.     </js-module> 
  15.     <!-- android --> 
  16.     <platform name="android"> 
  17.         <config-file target="res/xml/config.xml" parent="/*"> 
  18.             <feature name="Flashlight" > 
  19.                 <param name="android-package" value="com.baidu.light.flashlight.Flashlight"/> 
  20.             </feature> 
  21.         </config-file> 
  22.  
  23.         <config-file target="AndroidManifest.xml" parent="/*"> 
  24.             <uses-permission android:name="android.permission.CAMERA" /> 
  25.             <uses-permission android:name="android.permission.FLASHLIGHT" /> 
  26.         </config-file> 
  27.  
  28.         <source-file src="src/android/Flashlight.java" target-dir="src/com/baidu/light/flashlight" /> 
  29.     </platform> 
  30. </plugin> 

我就自己寫一個閃光燈插件 實現非常簡單,供大家參考

  • JavaScript 關鍵部分
    1. var cordova = require('cordova'), 
    2.     exec = require('cordova/exec'); 
    3.  
    4. var flashlight = flashlight || {}; 
    5.  
    6. function torch(successCallback, errorCallback) { 
    7.     exec(successCallback, errorCallback, 'Flashlight''torch', []); // 調用 Native 的提供的方法,指定回調、Native 對應的類名和動作 
    8. }; 
    9.  
    10. flashlight.torch = torch; 
    11. module.exports = flashlight; 
  • Android 關鍵部分
    1. public class Flashlight extends CordovaPlugin { 
    2.     private Camera mCamera; 
    3.     public boolean execute(String action, JSONArray args, 
    4.             CallbackContext callbackContext) throws JSONException { 
    5.         if (mCamera == null) { 
    6.             mCamera = Camera.open(); 
    7.         } 
    8.         if ("torch".equals(action)) { // 打開手電的動作 
    9.             Parameters parameters = mCamera.getParameters(); 
    10.             parameters.setFlashMode(Parameters.FLASH_MODE_TORCH); 
    11.             mCamera.setParameters(parameters);  
    12.             callbackContext.success(null); // 回調 JavaScript 
    13.         } else { 
    14.             return false
    15.         } 
    16.         return true
    17.     } 

百度地圖 提供了 Android、JS、iOS 三個版本,正好適合用來做地圖跨端組件

  • 地圖跨度組件 Cordova Plugin JavaScript 部分
    1. var cordova = require('cordova'), 
    2.     exec = require('cordova/exec'); 
    3.  
    4. var baidumap = baidumap || {}; 
    5.  
    6. /** 
    7.  * 初始化 
    8.  * @param{Object} options 配置項,顯示位置 
    9.  * @param{Function} callback 回調 
    10.  */ 
    11. function init(options, callback) { 
    12.     exec(callback, function() { 
    13.     }, 'BaiduMap''init', [options]); 
    14. }; 
    15.  
    16. baidumap.init = init; 
    17.  
    18. module.exports = baidumap; 
  • 地圖跨度組件 Cordova Plugin Android 部分
    1. public class BaiduMap extends CordovaPlugin { 
    2.     private CallbackContext mCallbackContext = null
    3.  
    4.     @SuppressWarnings("unchecked"
    5.     public boolean execute(String action, JSONArray args, 
    6.             CallbackContext callbackContext) throws JSONException { 
    7.         if ("init".equals(action)) { 
    8.             if (args == null) { 
    9.                 return false
    10.             } 
    11.  
    12.             JSONObject params = args.optJSONObject(0); 
    13.             JSONArray center = params.optJSONArray("center"); 
    14.             // Native View 在頁面中的顯示區域 
    15.             int left = params.optInt("left"); 
    16.             int top = params.optInt("top"); 
    17.             int width = params.optInt("width"); 
    18.             int height = params.optInt("height"); 
    19.             String guid = params.optString("id"); 
    20.             int zoom = params.optInt("zoom"); 
    21.             createMap(guid, left, top, width, height, 
    22.                     (float) center.optDouble(0), (float) center.optDouble(1), 
    23.                     zoom); 
    24.             mCallbackContext = callbackContext; 
    25.  
    26.         } 
    27.         return true
    28.     } 
    29.  
    30.     private static Handler mHandler = new Handler(Looper.getMainLooper()); 
    31.     private static Hashtable<String, MapView> mMaps = new Hashtable<String, MapView>(); 
    32.  
    33.     public void initialize(CordovaInterface cordova, CordovaWebView webView) { 
    34.         super.initialize(cordova, webView); 
    35.         // 初始化百度地圖 Android 版本 
    36.         BMapManager baiduMapManager = new BMapManager(webView.getContext() 
    37.                 .getApplicationContext()); 
    38.         baiduMapManager.init(new MKGeneralListener() { 
    39.             @Override 
    40.             public void onGetNetworkState(int state) { 
    41.             } 
    42.  
    43.             @Override 
    44.             public void onGetPermissionState(int state) { 
    45.             } 
    46.         }); 
    47.     } 
    48.  
    49.     public void createMap(String guid, int left, int top, int width, 
    50.             int height, float lng, float lat, int zoom) { 
    51.         mHandler.post(new Runnable() { // 注意 JavaScript 調用 Native 會在子線程,如果操作 UI 需放到 主線程中 
    52.             private String mGuid; 
    53.             private int mLeft; 
    54.             private int mTop; 
    55.             private int mWidth; 
    56.             private int mHeight; 
    57.             private float mLng; 
    58.             private float mLat; 
    59.             private int mZoom; 
    60.  
    61.             public Runnable config(String guid, int left, int top, int width, 
    62.                     int height, float lng, float lat, int zoom) { 
    63.                 mGuid = guid; 
    64.                 mLeft = left; 
    65.                 mTop = top; 
    66.                 mHeight = height; 
    67.                 mWidth = width; 
    68.                 mLng = lng; 
    69.                 mLat = lat; 
    70.                 mZoom = zoom; 
    71.                 return this
    72.             } 
    73.  
    74.             @SuppressWarnings("deprecation"
    75.             @Override 
    76.             public void run() { 
    77.                 MapView mapView = new MapView(BaiduMap.this.webView 
    78.                         .getContext()); 
    79.                 MapController mapController = mapView.getController(); 
    80.                 GeoPoint point = new GeoPoint((int) (mLat * 1E6), 
    81.                         (int) (mLng * 1E6)); 
    82.                 mapController.setCenter(point); 
    83.                 mapController.setZoom(mZoom); 
    84.  
    85.                 float scale = BaiduMap.this.webView.getScale(); 
    86.  
    87.                 LayoutParams params = new LayoutParams((int) (mWidth * scale), 
    88.                         (int) (mHeight * scale), (int) (mLeft * scale), 
    89.                         (int) (mTop * scale)); 
    90.                 mapView.setLayoutParams(params); 
    91.                 BaiduMap.this.webView.addView(mapView); // 大家注意這一句,將 Native View 添加在 WebView 上,自然就響應頁面滾動 
    92.  
    93.                 mMaps.put(mGuid, mapView); 
    94.             } 
    95.  
    96.         }.config(guid, left, top, width, height, lng, lat, zoom)); 
    97.     } 
  • Web Component,注意適配 runtime 環境
    1. void function() { 
    2.     var instances = {}; 
    3.     var guid = 0; 
    4.  
    5.     var LightMapPrototype = Object.create(HTMLDivElement.prototype); 
    6.     LightMapPrototype.createdCallback = function() { 
    7.         var self = this
    8.         var div = document.createElement('div'); 
    9.         var zoom = 11; 
    10.         var center = [ 116.404, 39.915 ]; 
    11.         this.setZoom = function(value) { 
    12.             zoom = value; 
    13.             map.setZoom(zoom); 
    14.         }; 
    15.         this.setCenter = function(value) { 
    16.             center = String(value).split(','); 
    17.             map.setCenter(new BMap.Point(center[0], center[1])); 
    18.         }; 
    19.  
    20.         div.style.width = (this.getAttribute('width') || '300') + 'px'
    21.         div.style.height = (this.getAttribute('height') || '300') + 'px'
    22.         this.appendChild(div); 
    23.  
    24.         // 判斷當前的運行環境 
    25.         var runtime = (typeof cordova != 'undefined'
    26.                 && (typeof light != 'undefined'// 有可能插件沒有安裝或者當前版本不支持 
    27.                 && (typeof light.map != 'undefined') ? 'cordova' : 'browser'
    28.  
    29.         var map; 
    30.         switch (runtime) { 
    31.         case 'cordova'
    32.             var obj = div.getBoundingClientRect() 
    33.             light.map.init({ 
    34.                 guid : guid, 
    35.                 center : center, 
    36.                 zoom : zoom, 
    37.                 left : obj.left + window.pageXOffset, 
    38.                 top : obj.top + window.pageYOffset, 
    39.                 width : Math.round(obj.width), 
    40.                 height : Math.round(obj.height) 
    41.             }); 
    42.  
    43.             instances[guid] = this
    44.             guid++; 
    45.             break
    46.         case 'browser'
    47.             map = new BMap.Map(div); // 創建Map實例 
    48.             map.enableScrollWheelZoom(); // 啟用滾輪放大縮小 
    49.             map.addControl(new BMap.ScaleControl()); // 添加比例尺控件 
    50.             map.addControl(new BMap.OverviewMapControl()); // 添加縮略地圖控件 
    51.             map.centerAndZoom(new BMap.Point(center[0], center[1]), zoom); // 初始化地圖,設置中心點坐標和地圖級別 
    52.  
    53.             map.addEventListener('moveend'function() { 
    54.                 var value = map.getCenter(); 
    55.                 center = [ value.lng, value.lat ]; 
    56.                 self.setAttribute('center', center); 
    57.                 var e = document.createEvent('Event'); 
    58.                 e.initEvent('moveend'truetrue); 
    59.                 self.dispatchEvent(e); 
    60.             }); 
    61.             map.addEventListener('zoomend'function() { 
    62.                 var value = map.getZoom(); 
    63.                 zoom = value; 
    64.                 self.setAttribute('zoom', zoom); 
    65.                 var e = document.createEvent('Event'); 
    66.                 e.initEvent('zoomend'truetrue); 
    67.                 self.dispatchEvent(e); 
    68.             }); 
    69.  
    70.             break
    71.         } 
    72.         this.map = map; 
    73.     }; 
    74.     LightMapPrototype.attributeChangedCallback = function(attributeName, 
    75.             oldValue, newValue) { 
    76.         var self = this
    77.         switch (attributeName) { 
    78.         case 'center'
    79.             self.setCenter(newValue); 
    80.             break
    81.         case 'zoom'
    82.             self.setZoom(newValue); 
    83.             break
    84.         default
    85.             return false
    86.         } 
    87.         return true
    88.     }; 
    89.     document.registerElement = document.registerElement || document.register; 
    90.     function init() { 
    91.         var LightMap = document.registerElement('light-map', { 
    92.             prototype : LightMapPrototype 
    93.         }); 
    94.     } 
    95.     if (typeof cordova != 'undefined') { 
    96.         document.addEventListener('deviceready', init, false); // 等待設備初始化完成 
    97.     } else { 
    98.         init(); 
    99.     } 
    100. }(); 

調試

Ripple

  • 這是一款能在瀏覽器里模擬移動設備的調試工具,包括模擬 GPS、陀螺儀 等本地能力

Weinre

  • 能夠在 Chrome 開發者工具里,遠程調試的工具
  • 優勢:適用各種設備和瀏覽器
  • 不足:加載之前的狀態不能獲知、不能斷點調試

Remote Debug

  • iOS 6 和 Android 4.4 開始,可以原生適用 Remote Debug
  • Android 4.4 不僅能打斷點,而且還能映射 Web UI (Chrome dev 版本才支持)。

另外大家在移動端還用過啥 NB 的調試工具,歡迎留言推薦

安全考慮

用戶主動操作才開啟重要功能

  • 類似 Flash 里訪問剪貼板,需要用戶主動 Click 才可以訪問
  • 相比彈出個小黃條讓用戶授權,這種設計體驗要好很多

明確提示狀態

  • 如:錄音和錄像時,有明確的狀態顯示

參考資料

責任編輯:徐川 來源: 百度fex
相關推薦

2022-08-03 09:58:03

跨端框架實踐

2019-10-25 10:42:51

框架Web開發

2023-06-06 16:01:00

Web優化

2012-03-19 21:25:47

2021-05-27 05:22:28

前端引擎平臺

2016-08-27 22:02:11

前端跨端全棧

2015-05-13 10:09:39

移動跨平臺開發

2017-05-25 09:45:35

2020-08-13 15:36:14

移動端跨平臺小程序

2022-05-25 11:24:25

CalendarNutUI移動端

2018-05-22 10:30:37

深度學習蘑菇街移動端

2014-12-10 14:34:40

2021-09-14 08:38:57

組件開源前端

2025-01-26 08:35:01

First UI移動端開發

2017-07-06 08:07:18

智能移動應用開發

2012-10-09 10:58:56

IBMdw

2013-08-22 10:12:55

開放平臺云平臺移動互聯網

2016-11-29 13:03:46

微信客戶端跨平臺組件

2012-08-13 17:01:16

Web 3.0移動互聯

2022-01-17 11:41:50

前端Vite組件
點贊
收藏

51CTO技術棧公眾號

91高清免费观看| 在线观看免费污视频| 免费成人av电影| 日日夜夜精品视频天天综合网| 中文字幕国产精品久久| 国产xxx在线观看| 国产高清不卡| 亚洲欧美另类久久久精品2019| 国产精品一区二区三区不卡| 午夜精品久久久久久久蜜桃| 综合日韩在线| 亚洲欧美日韩中文在线| 婷婷激情综合五月天| 神马久久午夜| 亚洲三级电影网站| 日本欧洲国产一区二区| 精品国产亚洲AV| 免费国产亚洲视频| 97久久久久久| 69av视频在线| 日韩精品一区二区久久| 日韩国产高清污视频在线观看| 日本精品一区在线| 色婷婷综合久久久中字幕精品久久| 亚洲免费色视频| 亚洲欧美一区二区原创| 日韩欧美在线番号| 成人av在线影院| 亚洲a级在线观看| 中文字幕人妻互换av久久| 99精品国产福利在线观看免费| 久久天天躁狠狠躁夜夜av| 法国空姐电影在线观看| 老司机在线精品视频| 日韩一区二区三区高清免费看看| 亚洲xxxx2d动漫1| 亚洲优女在线| 福利一区视频在线观看| 日韩极品视频在线观看 | 日韩一级免费观看| 青青青在线播放| 精品极品在线| 一区二区高清视频在线观看| 亚洲国产一区二区三区在线播| 欧日韩在线视频| 国产精品一二三| 国产精品老牛影院在线观看| 草久久免费视频| 在线观看亚洲| 欧美二区在线播放| 四虎影院中文字幕| 欧美日中文字幕| 亚洲欧美国内爽妇网| 国产精品扒开腿做爽爽爽a片唱戏| 国产极品一区| 亚洲成精国产精品女| 日韩精品一区二区免费| 性欧美ⅴideo另类hd| 亚洲婷婷综合色高清在线| 午夜精品福利一区二区| 国产小视频免费在线网址| 91丝袜国产在线播放| 国产在线观看一区| 无码精品视频一区二区三区 | 精品av在线播放| 国产精品久久久久久久久电影网| 粗大黑人巨茎大战欧美成人| 国产精品美女www爽爽爽| 亚洲国产精品视频一区| 香蕉视频在线看| 国产精品电影院| 日本三日本三级少妇三级66| av在线导航| 一区二区三区精品在线| 日韩在线观看a| av资源网在线播放| 亚洲自拍偷拍综合| 国产日韩av网站| 色戒汤唯在线| 91福利国产精品| 亚洲综合婷婷久久| www.欧美| 欧美成人三级电影在线| 日韩精品一区二区三区高清免费| 免费看久久久| 在线播放亚洲激情| 永久免费看片直接| 亚洲小说欧美另类社区| 欧美亚洲国产日韩2020| 午夜一级黄色片| 精品一区二区在线视频| 99久久久久国产精品免费| 手机看片1024国产| 91视频免费播放| 一区二区在线不卡| 亚洲91av| 欧美午夜电影在线| 午夜免费看视频| 日韩中文字幕一区二区高清99| 精品国产污网站| 91网站免费视频| 欧美第一精品| 久久免费国产精品1| 中文字幕黄色片| 国产一区二区久久| 久久另类ts人妖一区二区| 在线免费观看黄色av| 亚洲另类在线制服丝袜| 国产亚洲欧美在线视频| 成人免费在线观看视频| 日韩美女视频一区二区在线观看| 日本xxx在线播放| 99国产精品免费视频观看| 欧美激情亚洲综合一区| 亚洲天堂网在线观看视频| 成人一区二区在线观看| 性欧美大战久久久久久久免费观看| 成码无人av片在线观看网站| 日韩欧美国产高清91| 三日本三级少妇三级99| 深爱激情综合网| 欧美激情久久久久| 一级黄色片在线播放| 99久久精品免费| 日韩 欧美 视频| 青青青国产精品| 日韩精品亚洲元码| 懂色av懂色av粉嫩av| 日韩一区精品字幕| 国内精品视频免费| 在线观看h网| 欧美色成人综合| 亚洲一区二区三区蜜桃| 亚洲国产专区校园欧美| 91亚洲精品在线| av免费在线一区二区三区| 一区二区三区蜜桃网| 肉色超薄丝袜脚交| 日韩伦理一区| 国产99久久精品一区二区| 天天操天天舔天天干| 亚洲欧美日韩国产综合在线| 欧美伦理片在线看| 青青草原在线亚洲| 韩国福利视频一区| 亚洲精品一区二区三区区别| 亚洲欧美区自拍先锋| 欧美一级视频在线| 婷婷综合久久| 国产深夜精品福利| 久久伊伊香蕉| 精品久久久中文| 毛茸茸free性熟hd| 亚洲五月婷婷| 国产98在线|日韩| 手机在线免费观看av| 欧美一级一区二区| 极品久久久久久| 国产一区999| 国产又粗又长又爽视频| 久久爱www.| 欧美日本在线视频中文字字幕| 国产特级黄色片| 中文字幕不卡三区| 天天操,天天操| 四季av一区二区凹凸精品| 国产精品视频1区| 在线观看免费版| 在线播放日韩导航| 18岁成人毛片| 成人毛片视频在线观看| 给我免费播放片在线观看| 精品福利网址导航| 欧美亚洲成人精品| 91美女视频在线| 欧美日韩大陆在线| 乱老熟女一区二区三区| 国产一区二区三区精品欧美日韩一区二区三区 | 六月婷婷色综合| 人人妻人人澡人人爽精品欧美一区| 91福利精品在线观看| 视频一区视频二区国产精品| 国产色视频在线| 精品国产乱码久久久久久虫虫漫画 | 少妇愉情理伦三级| 国产综合成人久久大片91| 97av中文字幕| 校花撩起jk露出白色内裤国产精品 | 国产免费久久| 成人福利视频网| 午夜小视频福利在线观看| 日韩高清有码在线| 一级黄色片网站| 亚洲综合免费观看高清在线观看| 三级男人添奶爽爽爽视频| 丝袜美腿一区二区三区| 男女啪啪的视频| 日韩av资源网| 国产精品久久久久久久久久久新郎| 免费黄色在线| 日韩av综合中文字幕| 中文字幕在线播放av| 亚洲最大成人综合| 日韩一区二区a片免费观看| 九一九一国产精品| 欧美激情 国产精品| 精品久久久中文字幕| 国产视频在线观看一区| 福利精品在线| 91av在线免费观看视频| 免费黄网在线观看| 精品一区二区三区三区| 国产深喉视频一区二区| 在线免费观看成人短视频| 欧美精品99久久久| 国产女主播在线一区二区| 26uuu国产| 日本不卡视频在线| 日韩av在线第一页| 欧美日韩亚洲一区二区三区在线| 麻豆视频成人| 亚洲国产中文在线| 欧美性感美女h网站在线观看免费| 国产不卡在线一区| 91制片厂毛片| 91在线一区| 国产精品福利片| 日本小视频在线免费观看| 精品亚洲一区二区三区| 国产视频在线一区| 欧美午夜视频网站| 一区视频免费观看| 中文字幕制服丝袜一区二区三区| 亚洲国语精品自产拍在线观看| 久久久久久不卡| 一区二区日韩av| 99热6这里只有精品| 久久九九久久九九| 亚洲成人av免费在线观看| 高清av一区二区| 亚洲五月激情网| 视频一区视频二区中文| 日韩a级在线观看| 欧美喷水视频| 亚洲第一综合网站| 欧美成人自拍| 亚洲欧洲精品一区二区| 欧美精品久久久久久 | 欧美天堂一区| 国产大片精品免费永久看nba| 美足av综合网| 欧美成人精品在线| 久久综合网导航| 亚洲欧美制服综合另类| 婷婷亚洲一区二区三区| 亚洲国产福利在线| 熟妇人妻av无码一区二区三区| 欧美一级在线观看| 精品女同一区二区三区| 日韩午夜av电影| 国产高清在线免费| 日韩欧美国产午夜精品| 精品人妻一区二区三区浪潮在线 | 中文字幕中文字幕99| 伊人春色之综合网| 蜜桃91精品入口| 欧美人妖在线| 亚洲欧美精品| 91成人精品视频| 91传媒免费视频| 亚洲午夜一区| 久久免费视频3| 久久久精品午夜少妇| 久久精品午夜福利| 免费欧美在线视频| 国产一级片自拍| 国产一区二区女| 日韩大尺度视频| 9i在线看片成人免费| 精品久久久久久中文字幕人妻最新| 91视视频在线观看入口直接观看www| 免费成人深夜夜行p站| 国产亚洲自拍一区| www中文在线| 一区二区不卡在线播放| 国产成人免费观看视频| 大桥未久av一区二区三区| av片免费观看| 欧美人妖巨大在线| 亚洲精品.www| 亚洲欧美日韩久久久久久 | 国产婷婷97碰碰久久人人蜜臀 | 夜夜躁日日躁狠狠久久88av| 色网站免费在线观看| 欧美激情日韩图片| 欧美电影免费观看网站| 国产在线精品播放| 欧美黄色一级| 九九九九久久久久| 日韩成人三级| 99在线免费视频观看| 久久性天堂网| 深爱五月综合网| 91网站在线观看视频| 少妇视频一区二区| 综合中文字幕亚洲| 欧美日韩一二三四区| 欧美一区二区三区男人的天堂| 天堂在线视频网站| 日韩在线视频二区| 涩涩视频网站在线观看| 91精品国产综合久久香蕉| 欧美在线导航| 在线一区高清| 在线成人欧美| 五月天婷婷亚洲| 久久综合久久99| 免费人成年激情视频在线观看| 欧美日韩中文字幕| 国产chinasex对白videos麻豆| 亚洲欧美视频在线| 1024在线看片你懂得| 国产日韩欧美在线观看| 偷拍一区二区| 日本黄色片一级片| 精一区二区三区| 女人又爽又黄免费女仆| 亚洲愉拍自拍另类高清精品| 波多野结衣电车痴汉| 亚洲丁香久久久| 中文字幕在线观看网站| 国产精品扒开腿做| 久本草在线中文字幕亚洲| 国产大尺度在线观看| 日韩 欧美一区二区三区| 国产又粗又长又爽| 亚洲精品日韩综合观看成人91| 一级淫片免费看| 亚洲欧美制服第一页| 国产网站在线| 国产精品视频福利| 亚洲综合色站| 天天干天天色天天干| 日本一区二区三区久久久久久久久不| 国产真实夫妇交换视频| 精品人伦一区二区色婷婷| 国产黄色在线观看| 成人黄色在线免费| 天天影视欧美综合在线观看| www.欧美日本| 国产欧美日韩另类一区| 久久精品视频1| 日韩精品欧美激情| 日本免费久久| 欧洲精品国产| 日本特黄久久久高潮| 免费网站在线高清观看| 91官网在线免费观看| 黄色在线网站| 国产精品久久久亚洲| 一道本一区二区三区| 日本免费不卡一区二区| 91亚洲精品久久久蜜桃| 亚洲伊人成人网| 国产一级揄自揄精品视频| 欧美三区四区| 翔田千里亚洲一二三区| 久久国产三级精品| 日韩人妻无码精品综合区| 欧美视频在线免费| 黄色美女网站在线观看| 国产精品xxx视频| 久久大综合网| www.日本久久| 亚洲国产精品久久一线不卡| 女人18毛片水真多18精品| 欧美巨大黑人极品精男| 色播一区二区| 精品人妻少妇一区二区| 久久亚区不卡日本| 亚洲专区第一页| 精品中文字幕在线2019| 高潮久久久久久久久久久久久久| 免费看欧美黑人毛片| 国产偷国产偷精品高清尤物| 一起草av在线| 欧美日韩国产第一页| 秋霞影院一区二区三区| 可以免费在线看黄的网站| 中文字幕永久在线不卡| 亚洲高清在线观看视频| 国产精品美女久久| 亚洲综合五月| 天堂www中文在线资源| 日韩欧美主播在线| 免费观看在线黄色网| 国产精品免费观看高清| 视频在线在亚洲| 日本熟妇成熟毛茸茸| 国产亚洲视频在线|