成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React 開發(fā)實(shí)戰(zhàn)(一)- Repeat 組件

tainzhi / 2413人閱讀

摘要:支持回調(diào)函數(shù),當(dāng)內(nèi)的表單輸入發(fā)生變化時可以即時通知其父組件。這是第一個問題,為了解決這個問題呢,需要對它的提兩個條件屬性上必須要接收一個回調(diào)函數(shù),函數(shù)接收一個對象參數(shù),參數(shù)結(jié)構(gòu)如下的值為當(dāng)前項(xiàng)產(chǎn)出的數(shù)據(jù),可能是個對象也可能是字符串或者數(shù)值。

前言

最近在寫一個面向 React 初學(xué)者的系列教程玩轉(zhuǎn) React,內(nèi)容對有 React 開發(fā)經(jīng)驗(yàn)的同學(xué)來說可能太過于基礎(chǔ)和啰嗦,不太感興趣。所以我打算同時開始另外一個系列文章《React 開發(fā)實(shí)戰(zhàn)》。該系列主要面向有 React 開發(fā)經(jīng)驗(yàn)的同學(xué),更側(cè)重 React 實(shí)戰(zhàn),每一篇文章會跟大家一起開發(fā)一個 React 組件或者一個簡單有趣的 React 應(yīng)用,這些組件或者應(yīng)用往往滿足如下特點(diǎn):

在我的實(shí)際項(xiàng)目中用到過的。

在常見的開源組件庫中沒有的。

有點(diǎn)小眾,但是在特定的業(yè)務(wù)場景下能很大地提高項(xiàng)目的開發(fā)效率。

可能還比較有趣。

如果這些組件能直接應(yīng)用到大家的實(shí)際開發(fā)中去,那再好不過了;如果不能,能給大家一點(diǎn)啟發(fā),我覺得這件事情也是很有價值的。

另外,每一篇文章后面都會附有本篇文章的完整示例和代碼。

問題描述

大家應(yīng)該都見過這種應(yīng)用場景,頁面上的某一部分,需要能夠讓用戶添加任意多項(xiàng)。

可能是表單中的一個字段,如下所示。

也可能是表單的一部分,如下所示,用戶可以在一個表單內(nèi)增加多個用戶信息,然后將用戶信息批量進(jìn)行保存。

還有更{{BANNED}}的,如下所示,一個表單內(nèi)用戶信息部分可以添加多份,每一個用戶信息中地址也可以添加多份。(Oh, My God. PM,你殺了我吧。)

還好,React 應(yīng)付這種需求,還是小菜一碟。但是在一個 web 應(yīng)用中有這么多的相似場景的話,如果我們挨個實(shí)現(xiàn)一遍,那真是太枯燥了,與搬磚無異。遇到這種情況,就需要我們把相同的功能抽象出來,做成組件,這將極大地提升你的開發(fā)效率。

基于這個場景,我們今天就開發(fā)一個能讓其 children 重復(fù)任意多份的組件,我們就稱之為 Repeat 吧。

你期望 Repeat 組件該怎么用

在開發(fā)一個組件的時候,不要著急寫代碼,先想想你要把這個組件做成什么樣子,例如這個 Repeat 組件,我希望有如下特性:

Repeat 組件提供默認(rèn)的,添加、移除按鈕。

點(diǎn)擊添加,將 React 的 children 復(fù)制一份,點(diǎn)擊移除將某一項(xiàng)移除。

當(dāng)只有一項(xiàng)時不能移除。

Repeat 支持 onChange 回調(diào)函數(shù),當(dāng) Repeat 內(nèi)的表單輸入發(fā)生變化時可以即時通知其父組件。

然后在代碼中我期望可以這樣來用 Repeat 這個組件:

class App extends React.Component {
    handleChange(items) {
        console.info(items);
    }
    render() {
         this.handleChange(items)}>
            
        
    }
}

OK,就是這么簡單,這樣 Input 組件就可以重復(fù)加添多份了。基于這個構(gòu)想,我們來實(shí)現(xiàn) Repeat 這個組件。

開始實(shí)現(xiàn) Repeat 組件
class Repeat extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            items: [""],
        };
    }
    handleChange(e, index) {
        const items = [...this.state.items];
        items[index] = e.target.value;
        this.setState({ items });
        this.props.onChange(items);
    }
    handleAddItem(e, index) {
        e.preventDefault();
        const items = [...this.state.items];
        items.splice(index, 0, "");
        this.setState({ items });
    }
    handleRemoveItem(e, index) {
        e.preventDefault();
        if (this.state.items.length === 1) return;
        const items = [...this.state.items];
        items.splice(index, 1);
        this.setState({ items });
    }
    render() {
        const children = React.Children.only(this.props.children);
        const elementItems = this.state.items.map((item, index) => (
            
{ React.cloneElement(children, { onChange: e => this.handleChange(e, index), value: item, }) }
)); return
{elementItems}
; } }

代碼很簡單,簡單解釋一下:

組件的 state 中持有 items 字段來保存每一個項(xiàng)的數(shù)據(jù)。

render 時先獲取到唯一的 children,然后 map 組件 state 中的 items,將每一項(xiàng)映射為 children 的一個副本。并為這個副本傳入兩個屬性,onChange 接收每一項(xiàng)的數(shù)據(jù)變化,value 傳遞每一項(xiàng)當(dāng)前應(yīng)展示的值。

另外 Repeat 為每一項(xiàng)準(zhǔn)備了一個“添加”按鈕和一個“移除”按鈕,用來在當(dāng)前項(xiàng)位置新增一項(xiàng)或者移除當(dāng)前項(xiàng)。原理就是將 this.state.items 中對應(yīng)下標(biāo)處的數(shù)組元素刪掉就好了。

到此,Repeat 是不是大致有模有樣了呢。需要提醒大家的是,React.cloneElementReact.Children.xxx 這些 api 通常只會在這種公共組件中使用,在大部分場景,盡量少用。

跟 children 有個約定

有些同學(xué)可能已經(jīng)發(fā)現(xiàn)了,上面例子中, Repeatchildren 是個 input,那如果是一個其他的組件不就完蛋了嘛。

這是第一個問題,為了解決這個問題呢,Repeat 需要對它的 children 提兩個條件:

屬性上必須要接收一個 onChange 回調(diào)函數(shù),函數(shù)接收一個對象參數(shù),參數(shù)結(jié)構(gòu)如下:

{
    target: {
        value: "xxxx"
    }
}

value 的值為當(dāng)前項(xiàng)產(chǎn)出的數(shù)據(jù),可能是個對象也可能是字符串或者數(shù)值。沒錯,我就是為了兼容 input event 的數(shù)據(jù)結(jié)構(gòu)。你當(dāng)然可以用任何你喜歡的且方便處理的數(shù)據(jù)結(jié)構(gòu)。

children 組件需要接收一個 value 屬性,以展示其擁有的值。也就是說 children 組件應(yīng)當(dāng)是一個受控的(controlled)組件。

這就是一個協(xié)議,你希望某個組件內(nèi)通過 Repeat 組件方便地添加多份并能獲取到一組數(shù)據(jù),那就必須要遵守這個協(xié)議。有同學(xué)可能會說為什么不搞的智能一點(diǎn)呢?嗯,這里我想分享一點(diǎn)個人經(jīng)驗(yàn):有些時候,尤其是在業(yè)務(wù)開發(fā)過程中,把公共部分抽取出來復(fù)用即可,點(diǎn)到為止,沒有必要搞得那么“強(qiáng)大”,剩下的事情讓一個很容易遵守的協(xié)議來完成,其實(shí)效率會更高,更容易讓人理解。

其實(shí)在計(jì)算機(jī)的世界中處處充滿了協(xié)議,例如你想讓 HTTP Server 返回正確的響應(yīng),你必須要遵循 http 協(xié)議來和它通信;你生產(chǎn)的顯卡能買的出去,必須要遵守相應(yīng)的協(xié)議,要能插到別人家生產(chǎn)的主板上。

扯遠(yuǎn)了!收!

對,有了上面這個約定以后,Repeat 一行代碼未加,是不是感覺功能完善了許多?嗯,就是這個目的?,F(xiàn)在我們來實(shí)現(xiàn)一下文章開始時候說的第二個場景。

聰明的你一定已經(jīng)知道該怎么做了,沒錯,只要我們實(shí)現(xiàn)一個 UserForm 組件,并讓他滿足上面的約定即可。請看代碼:

class UserForm extends React.Component {
    handleFieldChange(e) {
        const { name, value } = e.target;
        const formData = {
            ...this.props.value, 
            [name]: value,
        }
        this.props.onChange({
            target: {
                value: formData,
            }
        });
    }
    render() {
        const formData = this.props.value || {};
        return (
            
this.handleFieldChange(e)} />
this.handleFieldChange(e)} />
) } }

為了讓代碼更簡潔,我把 UserForm 這個組件實(shí)現(xiàn)為了一個支持受控的組件,但是在目前的業(yè)務(wù)場景下已經(jīng)足夠了,在實(shí)際情況下,你可以按需調(diào)整。

通過這個例子,還希望大家能體會到組件拆分的一個好處。就是,UserFormRepeat 拆分成兩個組件以后,UserForm 的復(fù)用性會更強(qiáng)??梢韵胂笠幌?,當(dāng)用戶被批量添加以后,是不是有可能在編輯單個用戶的時候,可以繼續(xù)使用這個組件。

好啦,關(guān)于第三個場景我想就沒有必要再實(shí)現(xiàn)一遍了,Repeat 嵌套多少層其實(shí)都是可以的。

更進(jìn)一步

實(shí)際上在實(shí)際應(yīng)用中,Repeat 這個組件還需要做進(jìn)一步完善,其中一個就是樣式,還有可能在不同的場景下,雖然交互都是這樣,但樣式會有所差異。另外默認(rèn)是“添加”、“移除”兩個文字按鈕,說不定實(shí)際業(yè)務(wù)場景中是兩個 +,- 的圖標(biāo)按鈕;還有可能“添加”、“移除”的位置為有所變化。

這些問題怎么處理呢?下面給大家描述下思路,具體代碼就不寫了,如果有什么疑問可以給我留言。

關(guān)于樣式,你可以給 Repeat 添加 itemClassNamebuttonsClassName 兩個屬性分別為每一項(xiàng)和按鈕區(qū)域的 css class。這樣你就可以在不同的場景下指定不同的樣式了。

關(guān)于如何將文字按鈕改為圖標(biāo)按鈕,你可以給 Repeat 添加 renderButtons 這樣一個函數(shù)屬性,如果未指定則用默認(rèn)的方式渲染按鈕,如果有則勇氣返回值渲染屬性。

最后

這是本篇文章的代碼:https://codepen.io/Sarike/pen...

好啦,文章就到這吧,如果有什么疑問可以給我留言。謝謝大家,祝大家國慶、中秋節(jié)快樂。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88797.html

相關(guān)文章

  • React 開發(fā)實(shí)戰(zhàn))- Repeat 組件

    摘要:支持回調(diào)函數(shù),當(dāng)內(nèi)的表單輸入發(fā)生變化時可以即時通知其父組件。這是第一個問題,為了解決這個問題呢,需要對它的提兩個條件屬性上必須要接收一個回調(diào)函數(shù),函數(shù)接收一個對象參數(shù),參數(shù)結(jié)構(gòu)如下的值為當(dāng)前項(xiàng)產(chǎn)出的數(shù)據(jù),可能是個對象也可能是字符串或者數(shù)值。 前言 最近在寫一個面向 React 初學(xué)者的系列教程玩轉(zhuǎn) React,內(nèi)容對有 React 開發(fā)經(jīng)驗(yàn)的同學(xué)來說可能太過于基礎(chǔ)和啰嗦,不太感興趣。所...

    NSFish 評論0 收藏0
  • 2017-09-30 前端日報(bào)

    摘要:前端日報(bào)精選劉海打理指北中的錯誤處理模式與反模式譯圖解和譯你并不知道中文裝飾器讓你的代碼更簡潔眾成翻譯第期每個程序員第一份工作前應(yīng)該知道的件事中的不變性眾成翻譯寫的一次小結(jié)掘金內(nèi)部機(jī)制探秘和文末附彩蛋和源碼前端雜談開發(fā)實(shí)戰(zhàn) 2017-09-30 前端日報(bào) 精選 iPhone X 劉海打理指北React16中的錯誤處理ES6 Promise:模式與反模式「譯」圖解 ArrayBuffer...

    darryrzhong 評論0 收藏0
  • React項(xiàng)目實(shí)戰(zhàn)react-redux-router基本原理

    摘要:組件將元素作為結(jié)果返回。是把數(shù)據(jù)從項(xiàng)目傳到的有效載荷。有以下職責(zé)維持應(yīng)用的提供方法獲取提供方法更新通過注冊監(jiān)聽器通過返回的函數(shù)注銷監(jiān)聽器。系列目錄前端大統(tǒng)一時代即將來臨項(xiàng)目實(shí)戰(zhàn)環(huán)境搭建項(xiàng)目實(shí)戰(zhàn)基本原理項(xiàng)目實(shí)戰(zhàn)登錄頁面編輯中 React相關(guān) React 是一個采用聲明式,高效而且靈活的用來構(gòu)建用戶界面的框架。 JSX 本質(zhì)上來講,JSX 只是為React.createElement(co...

    MorePainMoreGain 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<