自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于React/Vue搭建一個(gè)通用的表單管理配置平臺(tái)

開(kāi)發(fā) 前端
由于實(shí)現(xiàn)該案例還是有一定復(fù)雜度的,筆者沒(méi)有將所有組件都一一寫(xiě)出來(lái),希望為大家提供一個(gè)思考空間,后續(xù)筆者將會(huì)把該平臺(tái)整合到筆者的開(kāi)源CMS系統(tǒng)中,供大家學(xué)習(xí)使用。有關(guān)nodejs部分的內(nèi)容,由于筆者后期會(huì)陸續(xù)整理,如果有其他疑問(wèn),可以和筆者多交流。

前言

熟悉我的朋友可能會(huì)知道,我一向是不寫(xiě)熱點(diǎn)的。為什么不寫(xiě)呢?是因?yàn)槲也魂P(guān)注熱點(diǎn)嗎?其實(shí)也不是。有些事件我還是很關(guān)注的,也確實(shí)有不少想法和觀(guān)點(diǎn)。但我一直奉行一個(gè)原則,就是:要做有生命力的內(nèi)容。

這篇文章是一篇應(yīng)用性極強(qiáng)的文章,我們通過(guò)一個(gè)實(shí)際的應(yīng)用場(chǎng)景,去解決某一類(lèi)的問(wèn)題,提供一種或者幾種解決方案,來(lái)探索技術(shù)的魅力。接下來(lái)筆者主要分析表單定制平臺(tái)的實(shí)現(xiàn)思路和技術(shù)方案,來(lái)實(shí)現(xiàn)一個(gè)類(lèi)似于金數(shù)據(jù)或者問(wèn)卷星一樣的表單配置平臺(tái),大家也可以基于此方案,擴(kuò)展出功能更加強(qiáng)大的可視化平臺(tái)。

為什么要做一個(gè)這樣的平臺(tái)呢?一方面是因?yàn)楣P者多年來(lái)一直服務(wù)于B端產(chǎn)品,對(duì)于動(dòng)態(tài)表單以及配置化表單有一定的項(xiàng)目積累,并且深知配置化表單的價(jià)值所在。舉一個(gè)很傳統(tǒng)的B端表單配置化的例子:傳統(tǒng)2B企業(yè)在提供saas服務(wù)時(shí),為了滿(mǎn)足不同企業(yè)的定制化需求,往往會(huì)給企業(yè)客戶(hù)提供定制化或者自由配置的功能,如下圖:

圖片圖片

對(duì)于saas系統(tǒng)而言,軟件即服務(wù),在提供基礎(chǔ)服務(wù)的同時(shí),同樣要滿(mǎn)足用戶(hù)個(gè)性化需求,所以傳統(tǒng)的saas軟件提供商往往會(huì)提供給客戶(hù)自由配置的空間,這種自由配置的橋梁就是通過(guò)表單,舉一個(gè)簡(jiǎn)單的例子:

圖片圖片

通過(guò)這種方法就可以定制不同風(fēng)格的企業(yè)產(chǎn)品,這里只是舉了個(gè)比較簡(jiǎn)單的例子,往往實(shí)際項(xiàng)目中會(huì)更加復(fù)雜,可能會(huì)有幾十個(gè)配置項(xiàng),當(dāng)然這種模式是比較傳統(tǒng)的配置化方案,也僅僅是saas軟件提供的很小的一個(gè)服務(wù)模塊。目前主流的做法是采用可視化方案,而且國(guó)內(nèi)也有非常成熟的方案,但基本的思想是一致的,只不過(guò)后者的體驗(yàn)更好,操作難度更低。

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

saas(軟件即服務(wù))是一種云計(jì)算產(chǎn)品,為用戶(hù)提供對(duì)供應(yīng)商云端軟件的訪(fǎng)問(wèn)。用戶(hù)無(wú)需在其本地設(shè)備上安裝應(yīng)用。相反,應(yīng)用駐留在遠(yuǎn)程云網(wǎng)絡(luò)中,通過(guò) Web 或 API 進(jìn)行訪(fǎng)問(wèn)。通過(guò)應(yīng)用,用戶(hù)可以存儲(chǔ)和分析數(shù)據(jù),并可進(jìn)行項(xiàng)目協(xié)作。

類(lèi)似的云計(jì)算產(chǎn)品也有很多,比如Paas(平臺(tái)即服務(wù)),Iaas(基礎(chǔ)架構(gòu)即服務(wù))等,感興趣的朋友可以學(xué)習(xí)了解一下。

以上介紹更多的是為了讓大家理解筆者設(shè)計(jì)這套平臺(tái)的基本背景,我們還可以舉個(gè)更實(shí)際的例子就是金數(shù)據(jù)或者問(wèn)卷星的表單配置模式,用戶(hù)可以在管理后臺(tái)定制自己的表單,并生成一個(gè)可訪(fǎng)問(wèn)的鏈接來(lái)向目標(biāo)用戶(hù)發(fā)放問(wèn)卷,填寫(xiě)信息,收集信息,最后實(shí)現(xiàn)數(shù)據(jù)分析的目的。

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

設(shè)計(jì)思路

圖片圖片

實(shí)現(xiàn)效果與分析

1. 表單定制管理列表

圖片圖片

管理列表主要用來(lái)查看我們配置的表單模板,分析不同表單模板收集的數(shù)據(jù),對(duì)表單模板進(jìn)行編輯刪除等操作.

2. 表單定制頁(yè)面

圖片圖片

圖片圖片

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

  • 文本框
  • 多行文本框
  • 下拉框
  • 單選框
  • 復(fù)選框
  • 文件上傳控件

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

3. 草稿管理

圖片圖片

草稿箱設(shè)計(jì)的目的是方便使用者在配置表單的過(guò)程中不確定是否符合需求或者由于某種臨時(shí)性舉動(dòng)而無(wú)法繼續(xù)配置,這個(gè)時(shí)候可以將以配置好的內(nèi)容存入草稿箱,下次繼續(xù)編輯,所以筆者專(zhuān)門(mén)設(shè)計(jì)了草稿箱管理列表,一旦用戶(hù)存在草稿,會(huì)在管理頁(yè)面通知用戶(hù)并顯示草稿的數(shù)量.作為一個(gè)追求體驗(yàn)的技術(shù)人,這一塊的設(shè)計(jì)還是相當(dāng)有必要的.

4. 生成前臺(tái)表單訪(fǎng)問(wèn)鏈接

圖片圖片

當(dāng)我們配置好表單之后,我們點(diǎn)擊保存, 會(huì)生成一個(gè)前臺(tái)訪(fǎng)問(wèn)地址,實(shí)時(shí)訪(fǎng)問(wèn)表單信息,如下圖為點(diǎn)擊鏈接之后的頁(yè)面:

圖片圖片

我們也可以根據(jù)自己的風(fēng)格,設(shè)計(jì)自己的表單錄入頁(yè)面, 具體如何實(shí)現(xiàn)這樣的過(guò)程, 后面我會(huì)詳細(xì)介紹.

5. 查看用戶(hù)已有數(shù)據(jù)錄入

圖片圖片

圖片圖片

我們可以通過(guò)點(diǎn)擊"查看數(shù)據(jù)"來(lái)訪(fǎng)問(wèn)收集到的表單數(shù)據(jù),并通過(guò)可視化的工具對(duì)數(shù)據(jù)做分析比較,同時(shí)我們也可以在數(shù)據(jù)列表中刪除數(shù)據(jù),來(lái)控制我們數(shù)據(jù)展示的純凈.


6. 表單數(shù)據(jù)分析

圖片圖片

圖片圖片

圖片圖片

收集到數(shù)據(jù)只有,我們會(huì)自動(dòng)集成幾個(gè)可視化組件來(lái)分析表單數(shù)據(jù),以上是筆者列出的幾個(gè)可視化組件,基于antv G2來(lái)封裝.

應(yīng)用場(chǎng)景

以上主要介紹了自定義表單定制平臺(tái)的一些功能和交互效果, 我們可以利用該平臺(tái)做很多有意思的事情.因?yàn)楸韱蔚某橄笫菙?shù)據(jù),我們拿到定制化的表單json數(shù)據(jù)之后,我們可以有不同的展現(xiàn)形式,比如用戶(hù)的問(wèn)卷調(diào)查網(wǎng)站平臺(tái)的投票答題頁(yè)面發(fā)布動(dòng)態(tài)等功能,如下圖配置:

圖片圖片

圖片圖片

以上配置可以實(shí)現(xiàn)類(lèi)似于微信的發(fā)布朋友圈的功能, 然后我們可以通過(guò)前端的手段根據(jù)用戶(hù)發(fā)表的數(shù)據(jù)渲染成一個(gè)朋友圈列表.


如果我們?cè)俅蜷_(kāi)自己的腦洞,我們可以這樣配置,配置一個(gè)這樣的表單,表單包括一個(gè)文件上傳控件和n個(gè)文本輸入控件,如下圖:

圖片圖片

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

當(dāng)然基于該平臺(tái)甚至能直接配置小型的宣傳網(wǎng)站,還有更多想象空間,期待大家去挖掘。

代碼實(shí)現(xiàn)

要想開(kāi)發(fā)這樣一個(gè)表單定制平臺(tái), 核心在于如何實(shí)現(xiàn)表單動(dòng)態(tài)配置的機(jī)制.這里筆者將其劃分為兩部分:基礎(chǔ)表單物料表單編輯生成器, 如下圖所示拆分圖:

圖片圖片

接下來(lái)我們一步步實(shí)現(xiàn)以上兩個(gè)核心模塊。


1. 基礎(chǔ)表單物料

基礎(chǔ)表單物料主要是為了用戶(hù)選擇自定義表單控件使用,我們常用的表單動(dòng)態(tài)渲染有map循環(huán)+條件判斷和單層map+對(duì)象法,前者如果要渲染一個(gè)動(dòng)態(tài)表單,可能實(shí)現(xiàn)如下:

{
    list.map((item, i) => {
        return <React.Fragment key={i}>
            {
               item.type === 'input' && <Input />
            }
            {
               item.type === 'radio' && <Radio />
            }
            // ...
        </React.Fragment>
    })
}

但是這樣做有個(gè)明顯的缺點(diǎn)就是會(huì)產(chǎn)生很多沒(méi)必要的判斷,如果對(duì)于復(fù)雜表單,性能往往很低,所以筆者采用后者來(lái)實(shí)現(xiàn),復(fù)雜度可以降到O(n).我們先來(lái)做配置模版:

// 基礎(chǔ)模版數(shù)據(jù)
const tpl = [
  {
    label: '文本框',
    placeholder: '請(qǐng)輸入內(nèi)容',
    type: 'text',
    value: '',
    index: uuid(5)
  },
  {
    label: '單選框',
    type: 'radio',
    option: [{label: '男', value: 0}, {label: '女', value: 1}],
    index: uuid(5)
  },
  {
    label: '復(fù)選框',
    type: 'checkbox',
    option: [{label: '男', value: 0}, {label: '女', value: 1}],
    index: uuid(5)
  },
  {
    label: '多行文本',
    placeholder: '請(qǐng)輸入內(nèi)容',
    type: 'textarea',
    index: uuid(5)
  },
  {
    label: '選擇框',
    placeholder: '請(qǐng)選擇',
    type: 'select',
    option: [{label: '中國(guó)', value: 0}, {label: '俄羅斯', value: 1}],
    index: uuid(5)
  },
  {
    label: '文件上傳',
    type: 'upload',
    index: uuid(5)
  }
]

// 模版渲染組件
const tplMap = {
  text: {
    component: (props) => {
      const { placeholder, label } = props
      return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><Input placeholder={placeholder} /></div>
    }
  },
  textarea: {
    component: (props) => {
      const { placeholder, label } = props
      return <div className={styles.fieldOption}><span className={styles.fieldLabel}>{label}:</span><TextArea placeholder={placeholder} /></div>
    }
  },
  radio: {
    component: (props) => {
      const { option, label } = props
      return <div className={styles.fieldOption}>
              <span className={styles.fieldLabel}>{label}:</span>
              <Radio.Group>
                {
                  option && option.map((item, i) => {
                    return <Radio style={radioStyle} value={item.value} key={item.label}>
                      { item.label }
                    </Radio>
                  })
                }
            </Radio.Group>
        </div>
    }
  },
  checkbox: {
    component: (props) => {
      const { option, label } = props
      return <div className={styles.fieldOption}>
              <span className={styles.fieldLabel}>{label}:</span>
              <Checkbox.Group>
                <Row>
                  {
                    option && option.map(item => {
                      return <Col span={16} key={item.label}>
                              <Checkbox value={item.value} style={{ lineHeight: '32px' }}>
                                { item.label }
                              </Checkbox>
                            </Col>
                    })
                  }
                </Row>
            </Checkbox.Group>
        </div>
    }
  },
  select: {
    component: (props) => {
      const { placeholder, option, label } = props
      return <div className={styles.fieldOption}>
              <span className={styles.fieldLabel}>{label}:</span>
              <Select placeholder={placeholder} style={{width: '100%'}}>
                {
                  option && option.map(item => {
                    return <Option value={item.value} key={item.label}>{item.label}</Option>
                  })
                }
            </Select>
        </div>
    }
  },
  upload: {
    component: (props) => {
      return <div className={styles.fieldOption}>
              <span className={styles.fieldLabel}>{props.label}:</span>
              <Upload
              listType="picture-card"
              className="avatar-uploader"
              showUploadList={false}
              actinotallow="https://www.mocky.io/v2/5cc8019d300000980a055e76"
            >
              <div>+</div>
            </Upload>
        </div>
    }
  }
}

export {
  tpl,
  tplMap
}

基礎(chǔ)物料在下圖所示中使用:

圖片圖片

當(dāng)我們要添加一個(gè)表單項(xiàng)時(shí),我們就可以在左邊預(yù)覽操作區(qū)看到添加的項(xiàng),并可以基于表單編輯生成器來(lái)編輯表單字段。


2. 表單編輯生成器

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

// 表單容器組件
const BaseFormEl = (props) => {
  const {isEdit, onEdit, onDel, onAdd} = props
  const handleEdit = (v) => {
    onEdit && onEdit(v)
  }
  return <div className={styles.formControl}>
    <div className={styles.formItem}>{ props.children }</div>
    <div className={styles.actionBar}>
      <span className={styles.actionItem} onClick={onDel}><MinusCircleOutlined /></span>
      <span className={styles.actionItem} onClick={onAdd}><PlusCircleOutlined /></span>
      <span className={styles.actionItem} onClick={handleEdit}><EditOutlined /></span>
    </div>
  </div>
}

第二部分主要用來(lái)渲染操作區(qū)模版,基于BaseFormEl包裝不同類(lèi)型的表單組件, 這里舉一個(gè)比較復(fù)雜的select來(lái)說(shuō)明,其他表單控件類(lèi)似:

const formMap = {
  title: {},
  text: {},
  textarea: {},
  radio: {},
  checkbox: {},
  select: {
    component: (props) => {
      const { onDel, onAdd, onEdit, curIndex, index, type, label, placeholder, required, message, option } = props
      return <BaseFormEl 
        onDel={onDel.bind(this, index)}
        onAdd={onAdd.bind(this, index)}
        onEdit={onEdit.bind(this, {index, type, placeholder, label, option, required})}
        isEdit={curIndex === index}
      >
        <Form.Item name={label} label={label} rules={[{ message, required }]}>
          <Select placeholder={placeholder}>
            {
              option && option.map(item => {
                return <Option value={item.value} key={item.label}>{item.label}</Option>
              })
            }
          </Select>
        </Form.Item>
      </BaseFormEl>
    },
    editAttrs: [
      {
        title: '字段名稱(chēng)',
        key: 'label'
      },
      {
        title: '選項(xiàng)',
        key: 'option'
      },
      {
        title: '提示文本',
        key: 'placeholder'
      },
      {
        title: '是否必填',
        key: 'required'
      },
    ]
  },
  upload: {}
}

editAttrs主要用來(lái)渲染編輯列表,說(shuō)明哪些表單項(xiàng)可以編輯,這部分代碼比較簡(jiǎn)單,這里直接用圖舉例:

圖片圖片

最后我們來(lái)渲染表單生成器組件:

export default (props) => {
  const {
    formData,
    handleDelete,
    handleAdd,
    handleEdit,
    curEditRowIdx
  } = props
  return <Form name="customForm">
            {
              formData && formData.map(item => {
                let CP = formMap[item.type].component
                return <CP {...item} key={item.index}
                  onDel={handleDelete} 
                  onAdd={handleAdd}
                  onEdit={handleEdit}
                  curIndex={curEditRowIdx}
                />
              })
            }
         </Form>
}

至此,基本功能模塊已經(jīng)開(kāi)發(fā)完成,我們只需要將這些物料和組件導(dǎo)入到編輯頁(yè)面,基于業(yè)務(wù)來(lái)操作和請(qǐng)求即可。由于實(shí)現(xiàn)該案例還是有一定復(fù)雜度的,筆者沒(méi)有將所有組件都一一寫(xiě)出來(lái),希望為大家提供一個(gè)思考空間,后續(xù)筆者將會(huì)把該平臺(tái)整合到筆者的開(kāi)源CMS系統(tǒng)中,供大家學(xué)習(xí)使用。有關(guān)nodejs部分的內(nèi)容,由于筆者后期會(huì)陸續(xù)整理,如果有其他疑問(wèn),可以和筆者多交流。

責(zé)任編輯:武曉燕 來(lái)源: 趣談前端
相關(guān)推薦

2021-08-08 21:17:18

管理配置平臺(tái)

2023-01-18 07:49:42

2024-07-22 07:05:00

nodejs爬蟲(chóng)管理平臺(tái)爬蟲(chóng)框架

2023-03-06 10:42:45

2013-06-18 09:51:52

PomeloPomelo平臺(tái)搭建平臺(tái)

2024-12-09 00:00:03

Vue3項(xiàng)目表單

2010-03-08 17:20:56

搭建私有云

2009-07-24 11:29:33

WinForm表單窗體

2023-09-14 08:46:50

ReactVue

2021-04-25 08:58:00

Go拍照云盤(pán)

2021-04-26 18:48:48

微應(yīng)用React

2017-04-25 16:12:49

2021-03-31 08:01:24

React Portareactcss3

2022-04-25 10:49:12

RuoYi-Vue管理系統(tǒng)

2023-07-14 07:23:21

ReactuseEffect

2018-01-02 16:08:00

AndroidiOSReact Nativ

2010-03-02 13:35:59

Fedora apac

2023-10-20 09:49:46

AI技術(shù)

2023-04-28 09:30:40

vuereact

2017-02-06 10:30:13

iOS表單正確姿勢(shì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)