踩坑日記:關于antd表單封裝回傳值至父組件的問題

gogogo.jpg

寫在前面(說幾句廢話)

ant design是一套非常優(yōu)秀的組件庫惨篱,其中有react版本和vue版本砸讳,二者除了語法 上的差異界牡,使用思想基本大同小異,其中ant design 的Form組件又是使用頻率非常高的組件常遂,但往往挽荠,我們在做一些復雜功能的時候,通常需要對其進行二次封裝漠另,于是我就遇到了這樣的問題
“React和Vue都是作為單向數(shù)據(jù)流的框架跃赚,我們通常是使用‘父傳子,子調父’的形式來做組件通信的纬傲,對我封裝的表單組件叹括,怎么才能將子組件的值暴露在父組件中供父組件的Form方法捕獲,并同意操作值或者校驗呢汁雷?摔竿?”
這個問題困擾了我很久,以至于很長一段時間我都是通過回調函數(shù)的形式來和父組件通信的继低,即,父組件傳一個操作Form的方法到子組件柴底,子組件在完成特定的事件后,調用這個方法狐树。但這樣用起來鸿脓,我們還得多傳一個回調函數(shù),并且在表單統(tǒng)一校驗和取值方面也不行在塔,但是沒辦法拨黔,于是,他像一根刺一樣埋在了我心里贺待,我總感覺不能和原組件使用方法相同的封裝用起來很鬧心零截。
一個偶然的機會,我發(fā)現(xiàn)瞻润,原來我沒有深刻體會到官方文檔中的這句話

form.PNG

當年的我還是一個小白绍撞,面對復雜的開發(fā)得院,我對這句話的認識只是固定在了現(xiàn)有組件的上面,包括他的value非洲,defaultevalue等,而忽略了他對于自定義組件封裝的重要作用楼誓,真是這句話,真正解決了子組件像父組件回傳值的問題。我們不再使用callback的形式了帕识!好,下面開始進入正題肮疗。
為盡可能解決大家遇到的問題伪货,這邊文章,我將分別使用React和Vue來實現(xiàn)一些功能碱呼,供大家參考

Antd中表單封裝回傳值至父組件

本文不管是antd4.x還是3.x還是ant design vue都適用巍举,這里我使用的是react版本的3.x。
對于上面官網(wǎng)的那句話懊悯,現(xiàn)在應該有一個更明確的理解炭分,要想我們的組件可以搭配Form組件使用,并和原生組件用法相同捧毛,我們的組件需要遵循以下幾點

  • 提供受控屬性 value 或其它與 valuePropName的值同名的屬性呀忧。
  • 提供 onChange 事件或 trigger 的值同名的事件
  • 支持 ref:
    • React@16.3.0 之前只有 Class 組件支持。
    • React@16.3.0 及之后可以通過forwardRef添加 ref 支持
    • Vue中始終都支持ref

下面我們來實踐以下如何遵循上面的幾條規(guī)定

自定義Input組件(React版本)

這里先用react版來做第一個實驗胰坟,我將組件做了下面的封裝和使用

父組件中

import React from 'react'
import CustomInput from './components/CustomInput '

const FormItem = Form.Item;
const Parent= props => {
    const { getFieldDecorator } = props.form
    const getValue = () => {
        props.form.validateFields((err, val) => {
            if(!err) {
                console.log(val)
            }
        })
    }
    const setValue = () => {
        props.form.setFieldsValue({title: '909090'})
    }
    return (
        <>
            <Button onClick={getValue}>獲取表單</Button>
            <Button onClick={setValue}>給表單賦值</Button>
            <Form>
                <FormItem label="標題">
                    {getFieldDecorator('title', {
                    })(<CustomInput />)}
                </FormItem>
            </Form>
        </>
    )
}
export default Form.create()(Parent)

父組件就是一個常規(guī)的對Antd表單項的使用泞辐,主要內(nèi)容是對自定義表單的取值和校驗以及對其設值咐吼。下面是子組件封裝方法

import React from 'react'
import { Input } from 'antd'

const PriceInput = (props, ref) => {
    const inputChange = e => {
        const { onChange } = props
        onChange(e.target.value)
    }
    return (<Input ref={ref} value={props.value} onChange={inputChange}/>)
}
export default React.forwardRef(PriceInput)

我們沒有做太復雜的封裝,主要目的是為了演示如何遵循正確的規(guī)則去配合Form組件的使用厢塘。上面的組件有以下幾點特點

  • 有value屬性受控

  • 提供 onChange 事件,這里是最重要的一點俗冻,可以看到代碼中有Input組件自帶的onChange事件迄薄,有從props中取的onChange事件,那么規(guī)則中的onChange事件指的是哪一個呢讥蔽?答案是props中的onChange冶伞,這一步很管家

  • 支持ref,因為class組件本身支持ref這里我特意用函數(shù)組件做實例响禽,看其如何用

這次我們再來對上面那所謂的規(guī)律做總結

通過getFieldDecorator包裝后,組件自帶value屬性芋类,或者指定的valuePropName屬性,我們可以通過這個特點 來設置組件的值胖喳,達到父組件驅動父組件的目的

通過getFieldDecorator包裝后贮竟,組件自帶onChange屬性咕别,我們可以通過調用這個方法,將值回傳給父組件這是相當關鍵的一步顷级,也是我一直忽略了的一點

自定義Upload組件(Vue版本)

上面我們用react版本的antd演示了如何做正確的做表單項封裝弓颈,對于需要遵循的規(guī)定删掀,也是用了比較常規(guī)的value和onChange,下面我們來使用vue版本來演示更復雜的使用方式披泪,思想和上面的簡單實例一樣。

首先是父組件

<a-form :form="form">
  <a-form-item label="自定義上傳組件">
   <myCom v-decorator="['uploadCom', {trigger: 'uploadDone', valuePropName: 'fileList'}]"/>
  </a-form-item>
</a-form>

父組件中控硼,我們設置了triggervaluePropName卡乾,即規(guī)則中的第一條和第二條。二者都是自定義字段幔妨。其中trigger是我們回傳值的時候要調用的方法误堡,valuePropName是我們要注入到子組件中的屬性。
看子組件封裝

<template>
  <a-upload
    name="file"
    :multiple="true"
    action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
    :headers="headers"
    @change="handleChange"
    :fileList="fileList"
  >
    <a-button> <a-icon type="upload" /> Click to Upload </a-button>
  </a-upload>
</template>
<script>
export default {
  data () {
    return {
      headers: {
        authorization: 'authorization-text'
      }
    }
  },
  props: {
    fileList: Array
  },
  methods: {
    handleChange (info) {
      this.$listeners.uploadDone(info.fileList)
      if (info.file.status !== 'uploading') {
        console.log(info.file, info.fileList)
      }
      if (info.file.status === 'done') {
        this.$message.success(`${info.file.name} file uploaded successfully`)
      } else if (info.file.status === 'error') {
        this.$message.error(`${info.file.name} file upload failed.`)
      }
    }
  }
}
</script>

上面為官網(wǎng)完整demo陪踩,大家在實際項目中可根據(jù)情況封裝更復雜的組件悉抵,集中上面的代碼關鍵點在以下

  • props: {
      fileList: Array // 因為通過v-decorator包裝后會自動注入valuePropName屬性
    }
    
    
  • handleChange (info) {
      this.$listeners.uploadDone(info.fileList) // 這里我是本地基跑,所以將該方法放在了一開始,可根據(jù)需求決定放在哪里媳否,一般是放到文件上傳完成后
    

我們通過this.$listeners.uploadDone來將值回傳,從而保證父組件可以通過Form方法獲取值力图。說實話我也是找了半天才從this.$listeners里找到uploadDone,其中uploadDone是我們在父組件自定義的trigger,這里為了講解我故意設置了一下掺逼,不設置的話,取默認的onChange即可赘那。

關于自定義校驗

通過上面正確的封裝后氯质,我們已經(jīng)可以通過Form來獲取組件暴露的值了,這樣我們在做一些自定義檢驗的時候拱礁,就可以使用validator做自定義校驗了

總結

通過上面的封裝,我們就可以正常的像用原生antd組件那樣使用自定義的組件了吴超,不管你是react用戶還是vue用戶鸯乃,思想都是一樣,一定要記住上面的三條規(guī)范飒责,同時頁要反思赘娄,文檔要深刻理解哦好了,去試試吧本人已親測有效

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宏蛉,一起剝皮案震驚了整個濱河市遣臼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拾并,老刑警劉巖揍堰,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異嗅义,居然都是意外死亡屏歹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門蝙眶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褪那,你說我怎么就攤上這事幽纷。” “怎么了博敬?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵友浸,是天一觀的道長。 經(jīng)常有香客問我偏窝,道長收恢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任祭往,我火速辦了婚禮伦意,結果婚禮上,老公的妹妹穿的比我還像新娘硼补。我一直安慰自己默赂,他們只是感情好,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布括勺。 她就那樣靜靜地躺著缆八,像睡著了一般。 火紅的嫁衣襯著肌膚如雪疾捍。 梳的紋絲不亂的頭發(fā)上奈辰,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天,我揣著相機與錄音乱豆,去河邊找鬼奖恰。 笑死,一個胖子當著我的面吹牛宛裕,可吹牛的內(nèi)容都是我干的瑟啃。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼揩尸,長吁一口氣:“原來是場噩夢啊……” “哼蛹屿!你這毒婦竟也來了?” 一聲冷哼從身側響起岩榆,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤错负,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后勇边,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犹撒,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年粒褒,在試婚紗的時候發(fā)現(xiàn)自己被綠了识颊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡奕坟,死狀恐怖祥款,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情执赡,我是刑警寧澤镰踏,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站沙合,受9級特大地震影響奠伪,放射性物質發(fā)生泄漏。R本人自食惡果不足惜首懈,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一绊率、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧究履,春花似錦滤否、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炊甲。三九已至,卻和暖如春欲芹,著一層夾襖步出監(jiān)牢的瞬間卿啡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工菱父, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留颈娜,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓浙宜,卻偏偏與公主長得像官辽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子粟瞬,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容