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

從零開發一款可視化搭建框架Dooringx-Lib

開發 架構
去年上線的可視化編輯器 H5-dooring 至今已有一年的時間,期間有很多熱心的網友和大佬提出了非常多寶貴的建議,我們也在一步步實現中,以下是幾個比較典型的低代碼可視化平臺需求。

[[423281]]

去年上線的可視化編輯器 H5-dooring 至今已有一年的時間,期間有很多熱心的網友和大佬提出了非常多寶貴的建議,我們也在一步步實現中,以下是幾個比較典型的低代碼可視化平臺需求:

  • 出碼能力(即源碼下載功能)
  • 組件交互(即組件支持業務中常用的鏈接跳轉,彈窗交互,自定義事件等)
  • 數據源管理(即用戶創建的不同頁面擁有共享數據的能力,不同組件之間也有共享數據的能力)
  • 組件商店(即用戶可以自主生產組件,定義組件,接入組件數據的能力)
  • 布局能力(即用戶可以選擇不同的布局方案來設計頁面)
  • 常用功能集成(頁面截圖,微信分享,debug能力)

上面的這些功需求已經在 H5-dooring 陸續實現了,在我之前的文章中也有對應的技術分享。但是為了讓更多的人能低成本的擁有自己的可視化搭建系統,我們團隊的大佬花了非常多的時間研究和沉淀,最近也開源了一款可視化搭建框架 dooringx-lib,我們可以基于它輕松制作可視化編輯器,而無需考慮內部的實現細節,接下來我就和大家分享一下這款可視化框架的使用方式和實現思路,同時也非常感謝 dooring可視化團隊 各位大佬們的辛勤付出。

可視化搭建框架基本使用和技術實現

為了讓大家更好的理解可視化搭建框架,我這里舉幾個形象的例子:

antd —— antd-pro

我們都知道 antd 是流行的前端組件庫,那么基于它上層封裝的管理后臺 antd-pro 就是它的上層應用。

GrapesJS —— craft.js

GrapesJS 是一款國外的頁面編輯器框架(詳細介紹可參考我之前的文章 這款國外開源框架, 讓你輕松構建自己的頁面編輯器) ,那么 craft.js 就是它的上層應用框架。

dooringx-lib —— dooringx

dooringx-lib 是一款可視化搭建框架,同理 dooringx 就是基于 dooringx-lib 的可視化編輯器。

之所以要介紹它們的區別,是因為之前有很多朋友對這塊概念理解的不是很清晰,在了解了可視化搭建框架 的 “內涵” 之后,我們開始今天的核心內容。

1.技術棧

在分享框架實現思路之前當然要自報家門,框架實現上我們還是采用熟悉的 React 生態,移動端組件庫采用的眾安團隊的 zarm,編輯器應用層采用的 antd,至于其他的比如拖拽,參考線,狀態管理,插件機制等都是我們團隊大佬自研的方案。如果你是 vue 或者其他技術棧為主的團隊,也可以參考實現思路,相信也會對你有一定的啟發。

2.基本使用方式

在開始深入之前我們先看看如何使用這款框架,我們只需要按照如下方式即可安裝使用:

  1. npm/yarn install dooringx-lib 

同時我們還提供了基礎的使用demo,方便大家在自己的工程中快速上手:

  1. # 克隆項目 
  2. # cnpmjs 
  3. git clone https://github.com.cnpmjs.org/H5-Dooring/dooringx.git 
  4.  
  5. or 
  6. git clone https://github.com/H5-Dooring/dooringx.git 
  7.  
  8.  
  9. # 進入項目目錄 
  10. cd dooringx 
  11.  
  12. # 安裝依賴 
  13. yarn install 
  14.  
  15. # 啟動基礎示例 
  16. yarn start:example 
  17.  
  18. # 啟動 dooringx-lib 
  19. yarn start 
  20.  
  21. # 啟動 dooringx doc 文檔 
  22. yarn start:doc 
  23.  
  24. yarn build 

demo 的 github 項目如下:

github地址: https://github.com/H5-Dooring/dooringx

在了解完使用方式之后,我們來看看基本架構和實現思路。

3.dooringx-lib基礎架構和工作機制

上圖就是我根據目前 dooringx-lib 的項目架構梳理的架構圖,基本包含了搭建化編輯框架的大部分必備模塊。為了保證框架的靈活性,我們還可以按需安裝對應的功能組件,開發自定義的組件等。如下是一個基本的導入案例:

  1. import { 
  2.     RightConfig, 
  3.     Container, 
  4.     useStoreState, 
  5.     innerContainerDragUp, 
  6.     LeftConfig, 
  7.     ContainerWrapper, 
  8.     Control, 
  9. from 'dooringx-lib'

我們將整個框架拆分成了不同的模塊,這些模塊既相互獨立又可以相互關聯。完整的工作流程如下:

由上圖可以看出,我們只需要擁有基礎的業務研發能力,就可以借助 dooringx-lib 構建一個屬于自己的搭建平臺,就好比任何程序的本質: 數據和邏輯。

4.dooringx-lib插件開發

接下來我會和大家分享 dooringx-lib 的插件開發方式和具體實現(如何導入插件,如何編寫組件,如何注冊函數等),如果大家感興趣的話也可以跟著下面的方式實踐一下。

4.1 如何導入組件

我們在上圖可以看到左側是我們的組件物料區,分為基礎組件,媒體組件,可視化組件,它們的添加會統一放在 LeftRegistMap 數組中來管理,其基本結構如下:

  1. const LeftRegistMap: LeftRegistComponentMapItem[] = [ 
  2.   { 
  3.       type: 'basic', // 組件類別 
  4.       component: 'button', // 組件名稱 
  5.       img: 'icon-anniu', // 組件icon 
  6.       displayName: '按鈕', // 組件中文名 
  7.       urlFn: () => import('./registComponents/button'),  // 注冊回調 
  8.   }, 
  9. ]; 

左側組件支持同步導入或者異步導入。

如果需要異步導入組件,則需要填寫 urlFn,需要一個返回 promise 的函數。也可以支持遠程載入組件,只要 webpack 配上即可。

如果需要同步導入組件,則需要將組件放入配置項的 initComponentCache 中,這樣在載入時便會注冊進 componentRegister 里。

  1. initComponentCache: { 
  2.   modalMask: { component: MmodalMask },   
  3. }, 

4.2 如何定制左側面板

左側面板傳入 leftRenderListCategory 即可。

  1. leftRenderListCategory: [ 
  2.   { 
  3. type: 'basic'
  4. icon: <HighlightOutlined />, 
  5. displayName: '基礎組件'
  6.   }, 
  7.   { 
  8. type: 'xxc'
  9. icon: <ContainerOutlined />, 
  10. custom: true
  11. customRender: <div>我是自定義渲染</div>, 
  12.   }, 
  13. ], 

type 是分類,左側組件顯示在哪個分類由該字段決定。icon 則是左側分類小圖標(如上圖所示)。當 custom 為 true 時,可以使用 customRender 自定義渲染。

4.3 開發一個自定義的可視化組件

組件需要導出一個由 ComponentItemFactory 生成的對象:

  1. const MButton = new ComponentItemFactory( 
  2.  'button'
  3.  '按鈕'
  4.  { 
  5. style: [ 
  6.  createPannelOptions<FormMap, 'input'>('input', { 
  7.   receive: 'text',  
  8.   label: '文字'
  9.  }), 
  10. ], 
  11. animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})], 
  12. actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})], 
  13.  }, 
  14.  { 
  15. props: { 
  16.  ... 
  17.  text:'x.dooring'// input配置項組件接收的初始值 
  18. }, 
  19.  }, 
  20.  (data, context, store, config) => { 
  21. return <ButtonTemp data={data} store={store} context={context} config={config}></ButtonTemp>; 
  22.  }, 
  23.  true 
  24. ); 
  25.  
  26. export default MButton; 

其中第一個參數為組件注冊名,第二個參數用來展示使用。

第三個參數用來配置右側面板的配置項組件。其中鍵為右側面板的分類,值為配置項組件數組。

第四個參數會配置組件的初始值,特別注意的是,制作組件必須要有初始寬度高度(非由內容撐開),否則會在適配時全選時產生問題。

這個初始值里有很多有用的屬性,比如fixed代表使用固定定位,可以結合配置項更改該值,使得組件可以fixed定位。

還有 canDrag 類似于鎖定命令,鎖定的元素不可拖拽。

初始值里的 rotate 需要個對象,value 代表旋轉角度,canRotate 代表是否可以操作旋轉。(0.7.0版本開始支持)

第五個參數是個函數,你將獲得配置項中的 receive 屬性(暫且都默認該配置為receive)傳來的配置,比如上例中 receive 的是 text,則該函數中 data 里會收到該字段。

context 一般只有 preview 和 edit,用來進行環境判斷。

config 可以拿到所有數據,用來制作事件時使用。

第六個參數 resize 是為了判斷是否能進行縮放,當為 false 時,無法進行縮放。

第七個參數 needPosition,某些組件移入畫布后會默認采取拖拽的落點,該配置項默認為 true, 就是需要拖拽的位置,為 false 時將使用組件自身 top 和 left 定位來放置。

4.4 事件注冊

注冊時機

事件可以細分為 注冊時機 和 函數,組件內可以通過 hook 的方式來實現注冊時機:

  1. useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染時機'); //注冊名必須帶id 約定! 
  2. useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '點擊執行時機'); 

useDynamicAddEventCenter 第一個參數是 render 的四個參數組成的對象。第二個參數是注冊的時機名,必須跟 id 相關,這是約定,否則多個組件可能會導致名稱沖突,并且方便查找該時機。

注冊完時機后,我們需要將時機放入對應的觸發位置上,比如這個 button 的點擊執行時機就放到 onclick 中:

  1. <Button 
  2.     onClick={() => { 
  3. eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config); 
  4.     }} 
  5.     x.dooring 
  6. </Button>  

 

其中第一個參數則為注冊的時機名,第二個為 render 函數中最后一個參數 config

函數注冊

函數由組件拋出,可以加載到事件鏈上。比如,注冊個改變文本函數,那么我可以在任意組件的時機中去調用該函數,從而觸發該組件改變文本。

函數注冊需要放入 useEffect 中,在組件卸載時需要卸載函數!否則會導致函數越來越多。

  1. useEffect(() => { 
  2. const functionCenter = eventCenter.getFunctionCenter(); 
  3. const unregist = functionCenter.register( 
  4.  `${pr.data.id}+改變文本函數`, 
  5.  async (ctx, next, config, args, _eventList, iname) => { 
  6.   const userSelect = iname.data; 
  7.   const ctxVal = changeUserValue( 
  8.    userSelect['改變文本數據源'], 
  9.    args, 
  10.    '_changeval'
  11.    config, 
  12.    ctx 
  13.   ); 
  14.   const text = ctxVal[0]; 
  15.   setText(text); 
  16.   next(); 
  17.  }, 
  18.  [ 
  19.   { 
  20.    name'改變文本數據源'
  21.    data: ['ctx''input''dataSource'], 
  22.    options: { 
  23.     receive: '_changeval'
  24.     multi: false
  25.    }, 
  26.   }, 
  27.  ] 
  28. ); 
  29. return () => { 
  30.  unregist(); 
  31. }; 
  32. }, []); 

函數中參數與配置見后面的函數開發。

4.5 右側面板開發

為了開發自定義的右側屬性面板,我們只要將開發的組件配成一個對象放入 initFormComponents 即可。為了良好的開發體驗,需要定義個 formMap 類型:

  1. export interface FormBaseType { 
  2.     receive?: string; 
  3. export interface FormInputType extends FormBaseType { 
  4.     label: string; 
  5. export interface FormActionButtonType {} 
  6. export interface FormAnimateControlType {} 
  7. export interface FormMap { 
  8.     input: FormInputType; 
  9.     actionButton: FormActionButtonType; 
  10.     animateControl: FormAnimateControlType; 

formMap 的鍵名就是 initFormComponents 鍵名,formMap 的值對應組件需要收到的值。

以 input 組件為例,FormInputType 此時有2個屬性: label, receive。

那么在開發該組件時,props 會收到:

  1. interface MInputProps { 
  2.     data: CreateOptionsRes<FormMap, 'input'>; 
  3.     current: IBlockType; 
  4.     config: UserConfig; 

也就是 data 是 formMap 類型,而 current 是當前點擊的組件,config 就不用說了。

還記得在左側組件開發中的第三個參數嗎?這樣就都關聯起來了:

  1. style: [ 
  2.     createPannelOptions<FormMap, 'input'>('input', { 
  3.         receive: 'text',   
  4.         label: '文字' 
  5.     }) 
  6. ], 

createPannelOptions 這個函數的泛型里填入對應的組件,將會給收到的配置項良好的提示。

在配置項組件里所要做的就是接收組件傳來的配置項,然后去修改 current 的屬性:

  1. function MInput(props: MInputProps) { 
  2.  const option = useMemo(() => { 
  3. return props.data?.option || {}; 
  4.  }, [props.data]); 
  5.  return ( 
  6. <Row style={{ padding: '10px 20px' }}> 
  7.  <Col span={6} style={{ lineHeight: '30px' }}> 
  8.   {(option as any)?.label || '文字'}: 
  9.  </Col> 
  10.  <Col span={18}> 
  11.             <Input 
  12.                 value={props.current.props[(option as any).receive] || ''
  13.                 onChange={(e) => { 
  14.                         const receive = (option as any).receive; 
  15.                         const clonedata = deepCopy(store.getData()); 
  16.                         const newblock = clonedata.block.map((v: IBlockType) => { 
  17.                                 if (v.id === props.current.id) { 
  18.                                         v.props[receive] = e.target.value; 
  19.                                 } 
  20.                                 return v; 
  21.                         }); 
  22.                         store.setData({ ...clonedata, block: [...newblock] }); 
  23.                 }} 
  24.             ></Input> 
  25.  </Col> 
  26. </Row> 
  27.  ); 

由于可以很輕松的拿到 store,所以可以在任意地方進行修改數據。

將組件的 value 關聯 current 的屬性,onChange 去修改 store,這樣就完成了個雙向綁定。

注意:如果你的右側組件需要用到 block 以外的屬性,可能需要去判斷是否處于彈窗模式。

4.6 自定義右鍵菜單

右鍵菜單可以進行自定義:

  1. // 自定義右鍵 
  2. const contextMenuState = config.getContextMenuState(); 
  3. const unmountContextMenu = contextMenuState.unmountContextMenu; 
  4. const commander = config.getCommanderRegister(); 
  5. const ContextMenu = () => { 
  6.  const handleclick = () => { 
  7. unmountContextMenu(); 
  8.  }; 
  9.  const forceUpdate = useState(0)[1]; 
  10.  contextMenuState.forceUpdate = () => { 
  11. forceUpdate((pre) => pre + 1); 
  12.  }; 
  13.  return ( 
  14. <div 
  15.  style={{ 
  16.             left: contextMenuState.left
  17.             top: contextMenuState.top
  18.             position: 'fixed'
  19.             background: 'rgb(24, 23, 23)'
  20.  }} 
  21.  <div 
  22.             style={{ width: '100%' }} 
  23.             onClick={() => { 
  24.                     commander.exec('redo'); 
  25.                     handleclick(); 
  26.             }} 
  27.         > 
  28.             <Button>自定義</Button> 
  29.  </div> 
  30. </div> 
  31.  ); 
  32. }; 
  33. contextMenuState.contextMenu = <ContextMenu></ContextMenu>; 

先拿到 contextMenuState,contextMenuState 上有個 unmountContextMenu 是關閉右鍵菜單方法。所以在點擊后需要調用關閉。同時上面的 left 和 top 是右鍵的位置。另外,我們還需要在組件內增加強刷,賦值給 forceUpdate,用于在組件移動時進行跟隨。

4.7 表單驗證提交思路

表單驗證提交有非常多的做法,因為數據全部是聯通的,或者直接寫個表單組件也可以。在不使用表單組件時,簡單的做法是為每個輸入組件做個驗證函數與提交函數。這樣是否驗證就取決于用戶的選取,而拋出的輸入可以讓用戶選擇放到哪,并由用戶去命名變量。

在點擊提交按鈕時,調用所有組件的驗證函數與提交函數,使其拋給上下文,再通過上下文聚合函數聚合成對象,最后可以通過發送函數發送給對應后端,從而完成整個流程。我們可以在 dooringx 中試下這個demo。

另一種方式是可以專門寫個提交按鈕,固定了參數,以及部分規則,比如規定在頁面中的所有表單都會被收集提交。

 

那么我們可以利用數據源,將所有表單輸出內容自動提交給數據源,最后的提交按鈕按數據源規定格式的key 提取,發送給后端。

后期規劃

后期我們還會在產品功能方面持續迭代優化,如果大家有好的建議, 也可以隨時和我們交流, 也歡迎在 github 上積極提 issue。

 

責任編輯:武曉燕 來源: 趣談前端
相關推薦

2023-03-08 07:45:50

可視化編程工具SpringBoot

2021-07-12 17:23:47

零設計可視化引擎

2022-02-28 08:34:42

開發可視化大屏

2021-03-09 08:32:50

開發視化大屏H5-Dooring

2023-09-26 08:01:16

2019-10-10 08:46:02

Docker可視化技術瀏覽器

2022-05-17 10:05:55

Karma可視化面板Linux

2018-09-09 23:07:17

物聯網可視化編程工具

2025-02-25 11:14:39

2022-05-24 15:03:44

開源工具可視化

2020-07-27 09:59:25

Kafka可視化CMAK

2021-04-12 08:31:53

PC-Dooring項目PC端搭建

2021-08-26 05:15:22

圖片編輯器 H5-DooringMitu-Doorin

2022-08-31 08:32:22

數據可視化項目nocode

2024-03-11 08:32:02

2023-12-26 15:14:00

2016-03-15 12:27:54

WireEdit可視化編輯工具網絡數據包編輯器

2022-07-12 09:35:59

JSON可視化工具

2022-08-15 08:02:09

Go程序函數

2023-02-20 15:09:00

可視化搭建項目開源
點贊
收藏

51CTO技術棧公眾號

91午夜交换视频| 国产精品一级片| 日韩精品一区二区三区视频 | 四虎国产精品免费久久| 国产精品sm| 一区二区三区波多野结衣在线观看 | 久久午夜福利电影| 播放一区二区| 亚洲色图都市小说| 国产精品一区二区欧美| 男女啊啊啊视频| 国产精品一区二区三区av麻| 精品在线观看视频| 亚洲香蕉在线观看| 日本网站在线看| 新版的欧美在线视频| 最新高清无码专区| 欧美激情第六页| 国产麻豆一精品一男同| 久操视频免费在线观看| 69堂免费精品视频在线播放| 亚洲欧美日韩精品久久久久| 麻豆成人av| 亚洲无码精品国产| 国内在线精品| 日本三级在线观看网站 | 少妇被狂c下部羞羞漫画| 麻豆av在线播放| 极品美女销魂一区二区三区免费| 欧美亚洲一级片| 九九热最新地址| 成人av动漫在线观看| 日韩av综合网| 亚洲另类图片色| 久久av高潮av| 成年人在线观看| 美女久久久精品| 午夜精品一区二区三区av| 精品视频在线观看一区| 国产精品xxxx喷水欧美| 91麻豆国产自产在线观看亚洲| 7777精品伊人久久久大香线蕉完整版 | 中文字幕日本不卡| 亚洲不卡中文字幕| 国产视频二区在线观看| 2021国产精品久久精品| 精品视频一区二区| 日本精品久久久久久| 欧美视频四区| 一区二区不卡| 91精品欧美久久久久久动漫| www.-级毛片线天内射视视| 手机在线精品视频| 国产乱人伦偷精品视频免下载 | 蜜臀精品一区二区| 成人h小游戏| 国产日本欧美一区二区| 国产乱码一区| 久草国产精品视频| 亚洲综合另类| 日本久久久久久久久| 无码人妻av免费一区二区三区| 亚洲永久免费| 母乳一区在线观看| 精品福利二区三区| 国产精品自在自线| 青青国产精品| 欧美精品乱码久久久久久按摩| 亚洲国产精品久久久久婷蜜芽| 污污影院在线观看| 亚洲精品国产视频| 国内精品在线观看视频| 欧美少妇精品| 91国产免费看| 欧美在线视频二区| 69久久精品| 日韩精品亚洲专区| 欧美精品亚州精品| 亚洲国产精品午夜在线观看| 69久久精品| 91成人网在线观看| 欧美精品免费在线观看| 国产成人无码精品亚洲| 亚欧成人精品| 国产精品xxxxx| 中文字幕日本视频| 看片网站欧美日韩| 91入口在线观看| 人妻少妇精品无码专区| 久久久激情视频| 亚洲精品久久久久久一区二区| 久操视频在线| 99精品视频免费全部在线| 678在线观看视频| 手机av在线免费观看| 日韩电影一区二区三区| 成人精品视频99在线观看免费 | 成人av高清在线| 国产69精品久久久久9999apgf| 国产特级aaaaaa大片| 成人h版在线观看| 国产精品久久久久久久久久久久冷| 最近中文字幕在线视频| 香蕉视频亚洲一级| 日本护士...精品国| 在线观看免费av片| 国产精品成人99一区无码 | 国产精品情侣呻吟对白视频| 手机看片日韩国产| 欧美成人精品xxx| 56国语精品自产拍在线观看| 亚洲欧洲精品一区二区三区| 99精品国产视频| 91亚洲无吗| 性欧美videohd高精| 日韩在线资源| 精品人妻一区二区三区免费看| 在线看成人短视频| 欧美成人三级视频网站| 日韩欧美中文字幕一区二区| 麻豆国产精品官网| 精品亚洲欧美日韩| 在线中文字幕-区二区三区四区| 精品毛片网大全| 无码内射中文字幕岛国片| 99国产精品免费网站| 在线播放国产一区中文字幕剧情欧美| 青青草成人免费| 日本中文字幕一区| 国产精品夜夜夜一区二区三区尤| 日本熟妇色xxxxx日本免费看| 亚洲综合欧美| 国产区一区二区| 青青青国内视频在线观看软件| 欧美视频在线一区| 日本精品在线观看视频| 亚洲影院免费| 久久久久久久久四区三区| 免费黄色福利视频| xxxx另类黑人| 色婷婷一区二区三区四区| 亚洲一区和二区| 欧美fxxxxxx另类| 成人av.网址在线网站| 亚洲一区二区色| 91麻豆精东视频| 国产日韩av网站| 成人18视频在线观看| 亚洲图片欧洲图片av| 日本少妇裸体做爰| av高清久久久| 久久国产精品网| 成人免费观看49www在线观看| 色诱亚洲精品久久久久久| 99视频免费播放| 欧美午夜精彩| 国产日韩欧美夫妻视频在线观看| 二区在线视频| 欧美日本精品一区二区三区| 亚洲色图欧美色| 成人三级做爰av| 99久久久国产| 久热国产精品视频| 午夜欧美性电影| 手机看片日韩国产| 成人精品一区二区三区电影免费| 中文字幕在线国产精品| 日日狠狠久久偷偷四色综合免费| 91成人福利在线| 国产精品探花在线播放| 韩国三级大全久久网站| 中文字幕国产亚洲| 香蕉污视频在线观看| 国产成a人亚洲精| 久久精品视频16| 国产一区网站| 91免费国产网站| 污污的网站在线看| 99成人精品| 精品magnet| 国产福利在线观看视频| 中文精品电影| 九九九九精品| 蜜桃传媒在线观看免费进入| 精品视频一区二区三区免费| 欧美做受高潮6| 国产在线乱码一区二区三区| 亚洲 日韩 国产第一区| 精品一区91| 色偷偷av一区二区三区| 性一交一乱一透一a级| 亚洲精品视频在线观看免费| 免费日韩中文字幕| 999国产精品999久久久久久| 国产精品国产三级国产aⅴ9色| 久久精品蜜桃| 一本色道久久加勒比精品| 人人爽人人爽人人片| 国产剧情av麻豆香蕉精品| 热99这里只有精品| 国产欧美一区| 国产传媒一区二区| 国产成人精选| 5278欧美一区二区三区| 国产伦精品一区二区三区照片| 视频福利在线| 欧美视频一区在线| 色欲一区二区三区精品a片| 岛国一区二区在线观看| av片在线免费| 国产一区99| 国产精品日韩高清| 国产不卡123| 日韩视频在线一区| 国产偷拍一区二区| 一本大道av伊人久久综合| 久久影院一区二区| 中文字幕一区日韩精品欧美| 久久精品网站视频| 性人久久久久| 91久久夜色精品国产网站| 天堂va在线| 亚洲免费小视频| 亚洲精品国产精品国| 欧美自拍偷拍一区| 国产99久久久| 亚洲午夜免费视频| 欧美卡一卡二卡三| 国产精品久久毛片av大全日韩| 中国人体摄影一区二区三区| 国产污视频网站| 亚洲午夜精品久久久久久久久| 亚洲色图 激情小说| 久久九九久久九九| 色欲欲www成人网站| 久久精品免费看| 欧美网站免费观看| 国模一区二区三区| 在线观看成人av电影| 思热99re视热频这里只精品| 亚洲一区二区三| 爱看av在线| 欧美激情高清视频| 91大神xh98hx在线播放| 欧美综合久久久| 最新黄色网址在线观看| 欧美性一二三区| 天堂免费在线视频| 色婷婷av一区二区| 天干夜夜爽爽日日日日| 91官网在线观看| 91九色丨porny丨肉丝| 五月天中文字幕一区二区| 欧美精品久久96人妻无码| 丁香花免费高清完整在线播放 | 国产一区精品福利| 国产精品视频播放| 色屁屁草草影院ccyycom| 亚洲黄色成人网| 亚洲 精品 综合 精品 自拍| 日韩免费看网站| 久久久久久av无码免费看大片| 综合中文字幕亚洲| 放荡的美妇在线播放| 99精品久久只有精品| 免费无码毛片一区二三区| 午夜亚洲伦理| 日本中文字幕片| 麻豆精品新av中文字幕| 在线观看av免费观看| 粉嫩av亚洲一区二区图片| 亚洲av无码一区二区三区观看| 色综合桃花网| 欧美精选在线播放| 国产视频第二页| 91精品国产综合久久婷婷香蕉| 精品久久无码中文字幕| 欧美日韩成人综合在线一区二区| 亚洲影视一区二区| 日韩欧美一区中文| 人妻妺妺窝人体色www聚色窝| 国产手机视频精品| 亚洲女同志亚洲女同女播放| 精品乱人伦小说| 黄色av中文字幕| 精品一区二区三区四区在线| 91肉色超薄丝袜脚交一区二区| 亚洲免费观看视频| 久久精品一区二区三| 婷婷丁香激情综合| 中文字幕a级片| 欧美va日韩va| 成人综合影院| 久久久伊人欧美| 欧美一二三不卡| 成人嫩草影院| 特级西西444| 中文一区在线| 色国产在线视频| 粉嫩av一区二区三区在线播放| 国产无遮挡在线观看| 亚洲v精品v日韩v欧美v专区| 91porn在线视频| 色成人在线视频| 国产ts变态重口人妖hd| 欧美少妇xxx| 一卡二卡在线观看| 亚洲国产精品国自产拍久久| 亚洲天堂精品在线观看| 唐朝av高清盛宴| 亚洲国产精品一区二区久久| 久久国产波多野结衣| 久久久久9999亚洲精品| 国产真人做爰视频免费| 香蕉久久一区二区不卡无毒影院| 午夜久久久久久久久久影院| 亚洲第一区中文99精品| 国产在线激情| 66m—66摸成人免费视频| 精品国产美女a久久9999| 国产精品一区在线观看| 91精品一区二区三区综合在线爱| 免费看又黄又无码的网站| 久久精品国产77777蜜臀| 亚洲av无码一区二区三区人| 亚洲六月丁香色婷婷综合久久| 四虎影院在线免费播放| 日本sm残虐另类| 好吊妞www.84com只有这里才有精品 | 成人午夜激情在线| 免费看黄色三级| 欧美视频免费在线| 国产强被迫伦姧在线观看无码| 精品偷拍各种wc美女嘘嘘| 免费一级黄色大片| 色妞www精品视频| 欧美拍拍视频| 一区二区国产精品视频| 亚洲影院污污.| 国语一区二区三区| 在线视频一二三区| 老牛影视一区二区三区| 国产伦精品一区二区三区妓女| 亚洲图片自拍偷拍| 午夜精品久久久久久久99老熟妇| 精品动漫一区二区三区在线观看| 三级外国片在线观看视频| 国产美女被下药99| 精品国产91| 第四色婷婷基地| gogo大胆日本视频一区| 国产一级片免费看| 欧美成人一区二区三区片免费| 黄色精品在线观看| 国产精品盗摄久久久| 欧美丝袜激情| 国产福利精品一区二区三区| 国产精品一色哟哟哟| 秋霞欧美一区二区三区视频免费| 欧美色倩网站大全免费| 麻豆视频在线免费观看| 91色在线观看| 黄色日韩在线| 日韩激情在线视频| 在线播放一级片| 亚洲国产成人精品电影| 北岛玲日韩精品一区二区三区| 国产精品美女免费| avtt综合网| 黄色一级片黄色| 国产98色在线|日韩| 日韩网红少妇无码视频香港| 欧美精品一区二区三区蜜臀| 搞黄网站在线看| 成人免费网站在线| 欧美91福利在线观看| 超碰97在线资源站| 一本一本久久a久久精品综合麻豆 一本一道波多野结衣一区二区 | 日韩二区三区四区| 四虎永久免费地址| 日韩一卡二卡三卡四卡| 亚洲第一图区| 国产精品裸体一区二区三区| 一区二区蜜桃| 久久国产精品国产精品| 亚洲欧美国产77777| 五月激情丁香婷婷| 91精品国产综合久久香蕉922| 亚洲精品小说| 精品人妻一区二区三区视频| 窝窝社区一区二区| 一区二区三区精品国产| 丁香天五香天堂综合| www成人在线| 久久精品国产亚洲| 精品无人乱码一区二区三区 | 亚洲国产999| 欧美亚洲国产视频小说| 国产一区二区三区电影在线观看| 人妻内射一区二区在线视频 |