一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - 編程技術 - 基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

2021-08-09 00:09趣談前端徐小夕 編程技術

熟悉我的朋友可能會知道,我一向是不寫熱點的。為什么不寫呢?是因為我不關注熱點嗎?其實也不是。有些事件我還是很關注的,也確實有不少想法和觀點。但我一直奉行一個原則,就是:要做有生命力的內容。

前言

熟悉我的朋友可能會知道,我一向是不寫熱點的。為什么不寫呢?是因為我不關注熱點嗎?其實也不是。有些事件我還是很關注的,也確實有不少想法和觀點。但我一直奉行一個原則,就是:要做有生命力的內容。

這篇文章是一篇應用性極強的文章,我們通過一個實際的應用場景,去解決某一類的問題,提供一種或者幾種解決方案,來探索技術的魅力。接下來筆者主要分析表單定制平臺的實現思路和技術方案,來實現一個類似于金數據或者問卷星一樣的表單配置平臺,大家也可以基于此方案,擴展出功能更加強大的可視化平臺。

正文

為什么要做一個這樣的平臺呢?一方面是因為筆者多年來一直服務于B端產品,對于動態表單以及配置化表單有一定的項目積累,并且深知配置化表單的價值所在。舉一個很傳統的B端表單配置化的例子:傳統2B企業在提供saas服務時,為了滿足不同企業的定制化需求,往往會給企業客戶提供定制化或者自由配置的功能,如下圖:

基于React/Vue搭建一個通用的表單管理配置平臺

對于saas系統而言,軟件即服務,在提供基礎服務的同時,同樣要滿足用戶個性化需求,所以傳統的saas軟件提供商往往會提供給客戶自由配置的空間,這種自由配置的橋梁就是通過表單,舉一個簡單的例子:

基于React/Vue搭建一個通用的表單管理配置平臺

通過這種方法就可以定制不同風格的企業產品,這里只是舉了個比較簡單的例子,往往實際項目中會更加復雜,可能會有幾十個配置項,當然這種模式是比較傳統的配置化方案,也僅僅是saas軟件提供的很小的一個服務模塊。目前主流的做法是采用可視化方案,而且國內也有非常成熟的方案,但基本的思想是一致的,只不過后者的體驗更好,操作難度更低。

筆者簡單介紹一下saas,方便大家更容易理解其模式:

saas(軟件即服務)是一種云計算產品,為用戶提供對供應商云端軟件的訪問。用戶無需在其本地設備上安裝應用。相反,應用駐留在遠程云網絡中,通過 Web 或 API 進行訪問。通過應用,用戶可以存儲和分析數據,并可進行項目協作。

類似的云計算產品也有很多,比如Paas(平臺即服務),Iaas(基礎架構即服務)等,感興趣的朋友可以學習了解一下。

以上介紹更多的是為了讓大家理解筆者設計這套平臺的基本背景,我們還可以舉個更實際的例子就是金數據或者問卷星的表單配置模式,用戶可以在管理后臺定制自己的表單,并生成一個可訪問的鏈接來向目標用戶發放問卷,填寫信息,收集信息,最后實現數據分析的目的。

本文介紹的表單定制平臺,也同樣支持表單管理,表單數據分析, 表單數據收集, 表單定制等功能, 筆者將采用比較熟悉的技術棧react以及第三方ui庫antd4.0來開發, 后端采用node + koa來設計路由接口.

設計思路

基于React/Vue搭建一個通用的表單管理配置平臺

實現效果與分析

1. 表單定制管理列表

基于React/Vue搭建一個通用的表單管理配置平臺

管理列表主要用來查看我們配置的表單模板,分析不同表單模板收集的數據,對表單模板進行編輯刪除等操作.

2. 表單定制頁面

基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

由上圖可知表單定制頁面主要用來編輯自定義表單模板,我們可以添加表單標題,表單字段等,目前提供了幾種自定義表單控件如下:

  • 文本框
  • 多行文本框
  • 下拉框
  • 單選框
  • 復選框
  • 文件上傳控件

基本涵蓋了我們所需要的所有表單業務場景.由上圖可知我們可以在任意位置插入自定義字段,同時可以編輯修改刪除表單字段.如果想象力再大一點,我們可以基于它來實現不僅僅是表單問卷型應用,還可以實現答題,發布內容等場景.(后期可支持富文本控件)

3. 草稿管理

基于React/Vue搭建一個通用的表單管理配置平臺

草稿箱設計的目的是方便使用者在配置表單的過程中不確定是否符合需求或者由于某種臨時性舉動而無法繼續配置,這個時候可以將以配置好的內容存入草稿箱,下次繼續編輯,所以筆者專門設計了草稿箱管理列表,一旦用戶存在草稿,會在管理頁面通知用戶并顯示草稿的數量.作為一個追求體驗的技術人,這一塊的設計還是相當有必要的.

4. 生成前臺表單訪問鏈接

基于React/Vue搭建一個通用的表單管理配置平臺

當我們配置好表單之后,我們點擊保存, 會生成一個前臺訪問地址,實時訪問表單信息,如下圖為點擊鏈接之后的頁面:

基于React/Vue搭建一個通用的表單管理配置平臺

我們也可以根據自己的風格,設計自己的表單錄入頁面, 具體如何實現這樣的過程, 后面我會詳細介紹.

5. 查看用戶已有數據錄入

基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

我們可以通過點擊"查看數據"來訪問收集到的表單數據,并通過可視化的工具對數據做分析比較,同時我們也可以在數據列表中刪除數據,來控制我們數據展示的純凈.

6. 表單數據分析

基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

收集到數據只有,我們會自動集成幾個可視化組件來分析表單數據,以上是筆者列出的幾個可視化組件,基于antv G2來封裝.

應用場景

以上主要介紹了自定義表單定制平臺的一些功能和交互效果, 我們可以利用該平臺做很多有意思的事情.因為表單的抽象是數據,我們拿到定制化的表單json數據之后,我們可以有不同的展現形式,比如用戶的問卷調查, 網站平臺的投票, 答題頁面, 發布動態等功能,如下圖配置:

基于React/Vue搭建一個通用的表單管理配置平臺

基于React/Vue搭建一個通用的表單管理配置平臺

以上配置可以實現類似于微信的發布朋友圈的功能, 然后我們可以通過前端的手段根據用戶發表的數據渲染成一個朋友圈列表.

如果我們再打開自己的腦洞,我們可以這樣配置,配置一個這樣的表單,表單包括一個文件上傳控件和n個文本輸入控件,如下圖:

基于React/Vue搭建一個通用的表單管理配置平臺

將這樣的表單配置到H5管理模塊,我們只需要上傳三張圖,然后填寫好對應的配文,然后利用市面上成熟的H5全屏滾動插件,就能輕松的定制各種H5活動頁面了。該方案已被筆者的很多子系統使用,效果還是非常好的。

當然基于該平臺甚至能直接配置小型的宣傳網站,還有更多想象空間,期待大家去挖掘。

代碼實現

要想開發這樣一個表單定制平臺, 核心在于如何實現表單動態配置的機制.這里筆者將其劃分為兩部分:基礎表單物料和表單編輯生成器, 如下圖所示拆分圖:

基于React/Vue搭建一個通用的表單管理配置平臺

接下來我們一步步實現以上兩個核心模塊。

1. 基礎表單物料

基礎表單物料主要是為了用戶選擇自定義表單控件使用,我們常用的表單動態渲染有map循環+條件判斷和單層map+對象法,前者如果要渲染一個動態表單,可能實現如下:

  1.     list.map((item, i) => { 
  2.         return <React.Fragment key={i}> 
  3.             { 
  4.                item.type === 'input' && <Input /> 
  5.             } 
  6.             { 
  7.                item.type === 'radio' && <Radio /> 
  8.             } 
  9.             // ... 
  10.         </React.Fragment> 
  11.     }) 

但是這樣做有個明顯的缺點就是會產生很多沒必要的判斷,如果對于復雜表單,性能往往很低,所以筆者采用后者來實現,復雜度可以降到O(n).我們先來做配置模版:

  1. // 基礎模版數據 
  2. const tpl = [ 
  3.   { 
  4.     label: '文本框'
  5.     placeholder: '請輸入內容'
  6.     type: 'text'
  7.     value: ''
  8.     index: uuid(5) 
  9.   }, 
  10.   { 
  11.     label: '單選框'
  12.     type: 'radio'
  13.     option: [{label: '男', value: 0}, {label: '女', value: 1}], 
  14.     index: uuid(5) 
  15.   }, 
  16.   { 
  17.     label: '復選框'
  18.     type: 'checkbox'
  19.     option: [{label: '男', value: 0}, {label: '女', value: 1}], 
  20.     index: uuid(5) 
  21.   }, 
  22.   { 
  23.     label: '多行文本'
  24.     placeholder: '請輸入內容'
  25.     type: 'textarea'
  26.     index: uuid(5) 
  27.   }, 
  28.   { 
  29.     label: '選擇框'
  30.     placeholder: '請選擇'
  31.     type: 'select'
  32.     option: [{label: '中國', value: 0}, {label: '俄羅斯', value: 1}], 
  33.     index: uuid(5) 
  34.   }, 
  35.   { 
  36.     label: '文件上傳'
  37.     type: 'upload'
  38.     index: uuid(5) 
  39.   } 
  40.  
  41. // 模版渲染組件 
  42. const tplMap = { 
  43.   text: { 
  44.     component: (props) => { 
  45.       const { placeholder, label } = props 
  46.       return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><Input placeholder={placeholder} /></div> 
  47.     } 
  48.   }, 
  49.   textarea: { 
  50.     component: (props) => { 
  51.       const { placeholder, label } = props 
  52.       return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><TextArea placeholder={placeholder} /></div> 
  53.     } 
  54.   }, 
  55.   radio: { 
  56.     component: (props) => { 
  57.       const { option, label } = props 
  58.       return <div className={styles.fieldOption}> 
  59.               <span className={styles.fieldLabel}>{label}:</span> 
  60.               <Radio.Group
  61.                 { 
  62.                   option && option.map((item, i) => { 
  63.                     return <Radio style={radioStyle} value={item.value} key={item.label}> 
  64.                       { item.label } 
  65.                     </Radio> 
  66.                   }) 
  67.                 } 
  68.             </Radio.Group
  69.         </div> 
  70.     } 
  71.   }, 
  72.   checkbox: { 
  73.     component: (props) => { 
  74.       const { option, label } = props 
  75.       return <div className={styles.fieldOption}> 
  76.               <span className={styles.fieldLabel}>{label}:</span> 
  77.               <Checkbox.Group
  78.                 <Row> 
  79.                   { 
  80.                     option && option.map(item => { 
  81.                       return <Col span={16} key={item.label}> 
  82.                               <Checkbox value={item.value} style={{ lineHeight: '32px' }}> 
  83.                                 { item.label } 
  84.                               </Checkbox> 
  85.                             </Col> 
  86.                     }) 
  87.                   } 
  88.                 </Row> 
  89.             </Checkbox.Group
  90.         </div> 
  91.     } 
  92.   }, 
  93.   select: { 
  94.     component: (props) => { 
  95.       const { placeholder, option, label } = props 
  96.       return <div className={styles.fieldOption}> 
  97.               <span className={styles.fieldLabel}>{label}:</span> 
  98.               <Select placeholder={placeholder} style={{width: '100%'}}> 
  99.                 { 
  100.                   option && option.map(item => { 
  101.                     return <Option value={item.value} key={item.label}>{item.label}</Option
  102.                   }) 
  103.                 } 
  104.             </Select
  105.         </div> 
  106.     } 
  107.   }, 
  108.   upload: { 
  109.     component: (props) => { 
  110.       return <div className={styles.fieldOption}> 
  111.               <span className={styles.fieldLabel}>{props.label}:</span> 
  112.               <Upload 
  113.               listType="picture-card" 
  114.               className="avatar-uploader" 
  115.               showUploadList={false
  116.               action="https://www.mocky.io/v2/5cc8019d300000980a055e76" 
  117.             > 
  118.               <div>+</div> 
  119.             </Upload> 
  120.         </div> 
  121.     } 
  122.   } 
  123.  
  124. export { 
  125.   tpl, 
  126.   tplMap 

基礎物料在下圖所示中使用:

基于React/Vue搭建一個通用的表單管理配置平臺

當我們要添加一個表單項時,我們就可以在左邊預覽操作區看到添加的項,并可以基于表單編輯生成器來編輯表單字段。

2. 表單編輯生成器

表單編輯生成器分為2部分, 第一部分是用來生成表單項的容器組件,封裝了添加,刪除,編輯操作功能,代碼如下:

  1. // 表單容器組件 
  2. const BaseFormEl = (props) => { 
  3.   const {isEdit, onEdit, onDel, onAdd} = props 
  4.   const handleEdit = (v) => { 
  5.     onEdit && onEdit(v) 
  6.   } 
  7.   return <div className={styles.formControl}> 
  8.     <div className={styles.formItem}>{ props.children }</div> 
  9.     <div className={styles.actionBar}> 
  10.       <span className={styles.actionItem} onClick={onDel}><MinusCircleOutlined /></span> 
  11.       <span className={styles.actionItem} onClick={onAdd}><PlusCircleOutlined /></span> 
  12.       <span className={styles.actionItem} onClick={handleEdit}><EditOutlined /></span> 
  13.     </div> 
  14.   </div> 

第二部分主要用來渲染操作區模版,基于BaseFormEl包裝不同類型的表單組件, 這里舉一個比較復雜的select來說明,其他表單控件類似:

  1. const formMap = { 
  2.   title: {}, 
  3.   text: {}, 
  4.   textarea: {}, 
  5.   radio: {}, 
  6.   checkbox: {}, 
  7.   select: { 
  8.     component: (props) => { 
  9.       const { onDel, onAdd, onEdit, curIndex, index, type, label, placeholder, required, message, option } = props 
  10.       return <BaseFormEl  
  11.         onDel={onDel.bind(this, index)} 
  12.         onAdd={onAdd.bind(this, index)} 
  13.         onEdit={onEdit.bind(this, {index, type, placeholder, label, option, required})} 
  14.         isEdit={curIndex === index
  15.       > 
  16.         <Form.Item name={label} label={label} rules={[{ message, required }]}> 
  17.           <Select placeholder={placeholder}> 
  18.             { 
  19.               option && option.map(item => { 
  20.                 return <Option value={item.value} key={item.label}>{item.label}</Option
  21.               }) 
  22.             } 
  23.           </Select
  24.         </Form.Item> 
  25.       </BaseFormEl> 
  26.     }, 
  27.     editAttrs: [ 
  28.       { 
  29.         title: '字段名稱'
  30.         key'label' 
  31.       }, 
  32.       { 
  33.         title: '選項'
  34.         key'option' 
  35.       }, 
  36.       { 
  37.         title: '提示文本'
  38.         key'placeholder' 
  39.       }, 
  40.       { 
  41.         title: '是否必填'
  42.         key'required' 
  43.       }, 
  44.     ] 
  45.   }, 
  46.   upload: {} 

editAttrs主要用來渲染編輯列表,說明哪些表單項可以編輯,這部分代碼比較簡單,這里直接用圖舉例:

基于React/Vue搭建一個通用的表單管理配置平臺

最后我們來渲染表單生成器組件:

  1. export default (props) => { 
  2.   const { 
  3.     formData, 
  4.     handleDelete, 
  5.     handleAdd, 
  6.     handleEdit, 
  7.     curEditRowIdx 
  8.   } = props 
  9.   return <Form name="customForm"
  10.             { 
  11.               formData && formData.map(item => { 
  12.                 let CP = formMap[item.type].component 
  13.                 return <CP {...item} key={item.index
  14.                   onDel={handleDelete}  
  15.                   onAdd={handleAdd} 
  16.                   onEdit={handleEdit} 
  17.                   curIndex={curEditRowIdx} 
  18.                 /> 
  19.               }) 
  20.             } 
  21.          </Form> 

至此,基本功能模塊已經開發完成,我們只需要將這些物料和組件導入到編輯頁面,基于業務來操作和請求即可。由于實現該案例還是有一定復雜度的,筆者沒有將所有組件都一一寫出來,希望為大家提供一個思考空間,后續筆者將會把該平臺整合到筆者的開源CMS系統中,供大家學習使用。有關nodejs部分的內容,由于筆者后期會陸續整理,如果有其他疑問,可以和筆者多交流。

最后

如果想學習更多H5游戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入我們的技術群一起學習討論,共同探索前端的邊界。

原文鏈接:https://mp.weixin.qq.com/s/HdytZUQmW4M9B1j-fWYbog

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人人免费夜夜视频观看 | 免费观看在线永久免费xx视频 | 四虎网站最新网址 | 青青久久精品国产 | 2018天天拍拍拍免费视频 | 日本大学jalapsiki | 国产另类视频一区二区三区 | 不良网站在线观看 | 国产偷窥女洗浴在线观看亚洲 | 丁香网五月天 | 国产在线观看人成激情视频 | 日韩高清在线观看 | 四虎影视在线永久免费观看 | 星星动漫无删减在线观看 | 精品一卡2卡3卡4卡5卡亚洲 | 欧美最猛性xxxxx男男 | 成人亚洲欧美日韩在线观看 | 久久精品黄AA片一区二区三区 | 红楼梦黄色小说 | 欧美视频一区二区三区四区 | 亚洲老头老太hd | 亚洲人成网站在线观看青青 | 亚洲人的天堂男人爽爽爽 | 好大好长好紧爽免费 | 艾秋麻豆果冻传媒老狼仙踪林 | 东北老妇露脸xxxxx | 国产hd老太婆 | 日本妻子迷妹网 | 秋霞717理论片在线观看 | 日本免费高清在线观看播放 | 亚洲国产精品久久精品怡红院 | 欧美一级片观看 | 国产情侣视频观看 | va在线视频 | 日本96在线精品视频免费观看 | 国内精品91最新在线观看 | 日韩精品成人在线 | 末代皇帝无删减版在线观看 | 国产亚洲精品美女 | 涩涩国产精品福利在线观看 | 青草视频在线观看免费网站 |