React-native 自定義輸入框組件InputItem

首先尊搬,根據業(yè)務和交互UI設計瓤湘,本文實現的自定義的輸入框組件InputItem需要用到React-native的View泊脐、Text、TextInput课蔬、TouchableOpacity四個原生組件和自定義的一個Icon組件闪檬。


正常

報錯

組件基本結構如下,簡略版购笆,樣式就不詳細舉出了

<View style={styles.container}>

/*label 文字*/
    <View>
          <Text>{labelText}</Text>
      <View>
    {isTips && (<TouchableOpacity>
                  <Text><Icon name=‘tips’></Text>
             </TouchableOpacity>
    )}

/*輸入框*/
    <TextInput
            style={styles.textInput}
            onBlur={this.onBlurTest}
            onChangeText={this.onInputChange}
            autoCorrect={false}
          />
</View>

/*文字錯誤提示*/
  {(this.state.isError  && (
          <View style={styles.errorMsgContainer}>
            <Text style={styles.errorMsg}>{this.props.errorMsg}</Text>
          </View>
        )}
接下來就是本人在結合需求開發(fā)的這個輸入框組件時粗悯,遇到的幾個比較關鍵點(坑)

1、輸入的值的保存
2同欠、校驗的結果顯示方式(邊輸入邊校驗還是輸入框失去焦點以后再校驗)
3样傍、校驗的觸發(fā)時機
4、父組件如何記錄铺遂、計算所有InputItem的校驗結果
5衫哥、鍵盤彈出,輸入框會被遮罩的問題

第一點:輸入值的保存

(1)一開始使用的react-native 版本是0.56襟锐,在ios上是輸入不了中文的(巨坑這個點)撤逢。目前項目升級到0.57版本可以解決。之前不升級項目版本粮坞,用了一套暴力的解決方案蚊荣,訪問鏈接:https://github.com/facebook/react-native/issues/18403 ( withHandleHandWritingTextInput)。問題基本可以解決莫杈,但是沒有滿足項目的需求互例,所以被迫升級版本。

(2)假如輸入的內容需要限定位數筝闹,且要輸入中文媳叨,位數要注意長度:用戶每打一個拼音字母,其實就占了輸入框的一位數关顷。舉個例子:假設設定輸入框位數為4糊秆,那用戶想打個 ‘想’,拼音是xiang议双,拼音位數是5痘番,這時候用戶只能打出前四位 ‘xian’,無法打出第五位 ‘g’聋伦,因為位數不夠了夫偶。

(3)由于TextInput是受控組件,并不提倡在TextInput中使用value綁定state的寫法來保存輸入的值觉增,事實也是兵拢,在react-native中使用這種寫法也會出現bug。所以逾礁,此項目中使用的是说铃,父組件props傳遞一個saveValue函數給InputItem访惜,然后在InputItem中的onChangeText中調用this.props.saveValue(value),將value傳遞給父組件腻扇,讓父組件保存對應的輸入值债热。

第二點:校驗的結果顯示方式

(1)一開始項目的需求是用戶一點輸入一邊實時校驗。這種方式其實比較簡單幼苛,只需要在onChangeText的監(jiān)聽函數中窒篱,加上自己的校驗函數regTest并且在regTest中設置自身的校驗結果state,控制errorMsg顯示與否就可以了舶沿。

(2)順便提一句墙杯,校驗所使用的正則表達式其實也是從父組件props傳遞過來的,感覺這樣可以盡量讓InputItem組件pure一點點括荡。

(3)現在項目的需求想改成高镐,輸入內容不實時檢驗,當輸入框失焦的時候才去校驗畸冲。這時候嫉髓,就可以把之前的onChangeText函數中的regTest函數抽離出來,放到onBlur函數中去邑闲。

第三點:校驗的觸發(fā)時機

這個點一看其實好像不是一個問題算行,因為觸發(fā)的時機看第二點問題,就已經很明顯了监憎,要不就是邊輸入邊觸發(fā)纱意,要不就失焦的時候觸發(fā)婶溯,很好理解鲸阔。

(1)需要考慮到一個需求情況是,輸入框的值迄委,理應是可以設置默認的值褐筛。例如,進入用戶的信息編輯頁叙身,要把InputItem的value設置成默認用戶信息渔扎。我們從開始的添加信息的時候,就已經校驗了輸入內容的合法性信轿,因此晃痴,在理想的情況下,獲取到的用戶信息和設定的默認值财忽,應該是不需要再校驗倘核。但是為了程序更加健壯,還是得假設獲取的數據是不可靠即彪,所以在獲取到數據并且設置默認值的時候紧唱,依然需要加上校驗的處理。

(2)接下來就是如何觸發(fā)設置完默認值以后進行校驗的問題了。首先漏益,能想到的是設置默認值蛹锰,其實就是數據從無到有,因此可以在InputItem 中的componentWillReceiveProps函數設置

/* 設置默認值時绰疤,初始數據為null*/
if (nextProps.value && !this.props.value) {
      this.regTest(nextProps.value);
    }

這樣基本能滿足頁面加載后同時設置了默認值铜犬,然后對默認值進行校驗的需求轻庆。

(3)然后翎苫,項目有個特別的需求,就是輸入內容可以通過掃描照片來自動填入榨了。假若煎谍,用戶一開始沒有自己輸入過信息,直接通過掃描來填入信息龙屉,其實情況與上面所說的情況是一致的呐粘,數據都是從無到有,可以觸發(fā)校驗转捕。需要考慮的情況其實是作岖,用戶掃描之前填入過內容,再去掃描結果覆蓋之前填入的信息五芝,這時候要觸發(fā)對覆蓋的掃描結果信息的校驗痘儡。

(4)這種情況還得結合第2大點--校驗的結果顯示方式來討論。
假如顯示方式是邊輸入邊校驗枢步,則可以在InputItem 中的componentWillReceiveProps函數設置

/*新輸入的(掃描結果設置)value和之前的value不同沉删,就校驗新的value,符合邊輸入邊校驗的規(guī)則*/
else if (nextProps.value !== this.props.value) {
       this.regTest(nextProps.value ? nextProps.value : '');
    }

假如顯示方式是失焦以后再校驗醉途,則會相對比較復雜一點矾瑰。我們需要考慮,什么時候去觸發(fā)校驗隘擎。(新需求殴穴,目前還在研究解決方案)

第四點:父組件如何記錄、計算所有InputItem的校驗結果

之前的實現背景是:父組件有多個輸入框货葬,輸入框值保存在父組件的state中采幌,同時,輸入框的校驗結果也需要同步到父組件震桶,在父組件記錄下來休傍,并且計算所有輸入框的狀態(tài),以便決定用戶是否可以成功點擊完成按鈕尼夺。

目前的解決方案是尊残,在父組件中設置一個變量炒瘸,對象allStatus。在用戶輸入信息寝衫,InputItem調用父組件的saveValue函數將信息set進父組件state進行保存的后顷扩,將輸入信息的校驗后的狀態(tài)也設置到變量對象allStatus中,相當于每一個輸入框慰毅,在allStatus對象中會有一個對應的輸入框檢驗屬性隘截,類型是Boolean值,記錄輸入框當前的信息的狀態(tài)是否合法汹胃。然后再用戶點擊完成按鈕的時候婶芭,遍歷allStatus對象的屬性,遇到一個屬性為true(就是有輸入框內容是錯誤的)就阻止完成按鈕的后臺請求操作着饥。

這個方案可能不是最優(yōu)解犀农,目前在考慮使用二進制數記錄計算,還在研究中宰掉。

第五點:鍵盤彈出呵哨,輸入框會被遮罩的問題

使用的是react-native-keyboard-aware-scroll-view依賴的KeyboardAwareScrollView解決項目的問題,iso和Android平臺使用方法不一樣轨奄,不一定適用你們的項目孟害,谷歌很多解決方案,多嘗試挪拟。以下是代碼:

if (Platform.OS === 'ios') {
      return (
        <KeyboardAwareScrollView style={{ flex: 1 }} showsVerticalScrollIndicator={false}>
          {this.props.children}
        </KeyboardAwareScrollView>
      );
    }

    return (
      <KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
        <ScrollView showsVerticalScrollIndicator={false}>
          {this.props.children}
        </ScrollView>
      </KeyboardAvoidingView>
    );
  }
總結:react-native還是很多坑的挨务,需要一步步去踩。這是本人入門react-native做的第一個組件玉组,做這個表單花費了很多時間谎柄,對組件的生命周期、組件間的數據狀態(tài)管理理解的不深球切,對適配不同平臺更是無所適從谷誓,導致實現出來效果并不是很好。以上所說的可能都不是最好的解決方案《执眨現在剛好新的需求過來,需要小重構一下這塊的代碼户辱,因此花點時間先把之前方案記錄下來鸵钝,重構完再對比更新。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末庐镐,一起剝皮案震驚了整個濱河市恩商,隨后出現的幾起案子,更是在濱河造成了極大的恐慌必逆,老刑警劉巖怠堪,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揽乱,死亡現場離奇詭異,居然都是意外死亡粟矿,警方通過查閱死者的電腦和手機凰棉,發(fā)現死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陌粹,“玉大人撒犀,你說我怎么就攤上這事√椭龋” “怎么了或舞?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蒙幻。 經常有香客問我映凳,道長,這世上最難降的妖魔是什么邮破? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任魏宽,我火速辦了婚禮,結果婚禮上决乎,老公的妹妹穿的比我還像新娘队询。我一直安慰自己,他們只是感情好构诚,可當我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布蚌斩。 她就那樣靜靜地躺著,像睡著了一般范嘱。 火紅的嫁衣襯著肌膚如雪送膳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天丑蛤,我揣著相機與錄音叠聋,去河邊找鬼。 笑死受裹,一個胖子當著我的面吹牛碌补,可吹牛的內容都是我干的。 我是一名探鬼主播棉饶,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼厦章,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了照藻?” 一聲冷哼從身側響起袜啃,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幸缕,沒想到半個月后群发,有當地人在樹林里發(fā)現了一具尸體晰韵,經...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年熟妓,在試婚紗的時候發(fā)現自己被綠了雪猪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡滑蚯,死狀恐怖浪蹂,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情告材,我是刑警寧澤坤次,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站斥赋,受9級特大地震影響缰猴,放射性物質發(fā)生泄漏。R本人自食惡果不足惜疤剑,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一滑绒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隘膘,春花似錦疑故、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至管钳,卻和暖如春钦铁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背才漆。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工牛曹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人醇滥。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓黎比,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腺办。 傳聞我的和親對象是個殘疾皇子焰手,可洞房花燭夜當晚...
    茶點故事閱讀 43,576評論 2 349