React從零開(kāi)始(4)——表單和列表

表單是前端開(kāi)發(fā)中必不可少的組件,React作為前端框架,如果不能處理表單,就會(huì)被億萬(wàn)的前端工程師吐槽的。然而React對(duì)于表單的處理,還是有一些細(xì)節(jié)上的東西需要關(guān)注,接下來(lái)我們?cè)敿?xì)的描述在React中如何使用表單組件。

為了讓頁(yè)面效果美觀一點(diǎn),在頁(yè)面中引入bootstrap的css

npm install bootstrap --save

在react組件中引入外部css文件,直接可以使用import

import 'bootstrap/dist/css/bootstrap.css'

我們操作使用react,開(kāi)發(fā)中最多的內(nèi)容就是操作state中的數(shù)據(jù),那么進(jìn)行表單開(kāi)發(fā),就是要將表單中的數(shù)據(jù)與state中的數(shù)據(jù)關(guān)聯(lián)起來(lái),也就是說(shuō),當(dāng)用戶改變表單中的數(shù)據(jù)時(shí),state中的數(shù)據(jù)也會(huì)相應(yīng)的發(fā)生修改,當(dāng)state中的數(shù)據(jù)發(fā)生了修改,form中的數(shù)據(jù)也會(huì)進(jìn)行相應(yīng)的變化。這種變化,以Angularjs的雙向綁定最為著名,然而,react并沒(méi)有使用雙向綁定,而是使用了單向數(shù)據(jù)流。

單向數(shù)據(jù)流

在這里描述單向數(shù)據(jù)流,并不采用一些比較正規(guī)的說(shuō)法,我所說(shuō)的是在開(kāi)發(fā)中的直觀感受。在前端開(kāi)發(fā)過(guò)程中,數(shù)據(jù)最終展示在頁(yè)面中,需要經(jīng)過(guò)一個(gè)渲染過(guò)程,即改變?yōu)g覽器頁(yè)面中的DOM結(jié)構(gòu)或者DOM中的內(nèi)容,從而瀏覽器進(jìn)行了解析渲染,如果要開(kāi)發(fā)人員手動(dòng)寫(xiě)原生的JS代碼操作DOM,在開(kāi)發(fā)復(fù)雜應(yīng)用時(shí),那將是一個(gè)極其痛苦的過(guò)程。單向數(shù)據(jù)流的作用就是,當(dāng)內(nèi)存中的數(shù)據(jù)發(fā)生變化時(shí),在頁(yè)面的相應(yīng)位置上,會(huì)自動(dòng)的渲染這些數(shù)據(jù),這就意味著開(kāi)發(fā)人員不再寫(xiě)DOM操作的代碼。

所謂單向數(shù)據(jù)流,意味著數(shù)據(jù)從一個(gè)地方流向另一個(gè)地方,即從瀏覽器內(nèi)存頁(yè)面DOM樹(shù)

單向數(shù)據(jù)流

這就是react的強(qiáng)大之處,同時(shí)也是其短板之處,從內(nèi)存到DOM,可以自動(dòng)渲染,但是從DOM到內(nèi)存,就需要開(kāi)發(fā)人員手動(dòng)處理。

創(chuàng)建表單

import React from 'react';
import 'bootstrap/dist/css/bootstrap.css'

class App extends React.Component{


    constructor(props){
        super(props);
        this.state = {
            name:''
        };
    }
    render(){
        return (
            <div className="container" style={{marginTop:'20px'}}>
                <div className="row">
                    <div className="col-md-5">
                        <form className="form-horizontal">
                            <div className="form-group">
                                <label className="col-sm-2 control-label">用戶名</label>
                                <div className="col-sm-10">
                                    <input type="email" className="form-control" id="name" name="name" placeholder="用戶名" />
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

此時(shí)的表單中,其內(nèi)部數(shù)據(jù)的狀態(tài)由其自身維持,當(dāng)用戶在表單中進(jìn)行輸入時(shí),表單的數(shù)據(jù)狀態(tài)發(fā)生了變化,但是state中的狀態(tài)仍然保持原狀態(tài),React只對(duì)表單組件進(jìn)行了渲染,但并未控制其后續(xù)輸入的變化,我們稱此時(shí)的表單組件為非受控組件。

讓React渲染表單組件,組件中的值由React賦予,并控制其因用戶輸入所帶來(lái)的變化,即讓表單組件成為受控組件

  1. 表單組件的value值由React進(jìn)行初始化
<input type="text" className="form-control" id="name" value={this.state.name} name="name" placeholder="用戶名" onChange={this.handleChange}/>
  1. 監(jiān)聽(tīng)組件change事件,將其變化的值修改保存到state中
handleChange = (event) =>{
    this.setState({
        [event.target.name]:event.target.value
    });
}

對(duì)于text,textarea,上述的方式均可,radio由于是單選,所以仍舊可以按照text的方式進(jìn)行處理,但是對(duì)于checkbox,就需要做特殊的處理了

    <div className="form-group">
        <label className="col-sm-2 control-label">愛(ài)好</label>
        <div className="col-sm-10">
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="1"/>音樂(lè)
                </label>
            </div>
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="2"/>美術(shù)
                </label>
            </div>
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="3"/>體操
                </label>
            </div>
        </div>
    </div>

checkbox組件為多選,所以,state中就需要使用數(shù)組來(lái)存儲(chǔ)數(shù)據(jù)

  1. 使用onChange事件控制組件
  2. 修改state屬性,要根據(jù)組件的checked屬性來(lái)判斷
    3.設(shè)置組件中的checked的值,需要根據(jù)state中的數(shù)據(jù)進(jìn)行判斷
  • 初始化state
    constructor(props){
        super(props);
        this.state = {
            music:false,
            draw:false,
            gymnastics:false
        };
    }
  • 為組件綁定onChange并對(duì)其checked進(jìn)行判斷
    <div className="form-group">
    <label className="col-sm-2 control-label">愛(ài)好</label>
    <div className="col-sm-10">
        <div className="checkbox">
            <label>
                <input type="checkbox" name="music" checked={this.state.music} onChange={this.handleChange}/>音樂(lè)
            </label>
        </div>
        <div className="checkbox">
            <label>
                <input type="checkbox" name="draw" checked={this.state.draw} onChange={this.handleChange}/>美術(shù)
            </label>
        </div>
        <div className="checkbox">
            <label>
                <input type="checkbox" name="gymnastics" checked={this.state.gymnastics} onChange={this.handleChange}/>體操
            </label>
        </div>
    </div>
</div>
  • 在onChange函數(shù)中進(jìn)行數(shù)據(jù)處理
    handleChange = (event) =>{
        var temp = {
            [event.target.name]:event.target.checked
        };
        this.setState(temp);
    }

列表

現(xiàn)在業(yè)內(nèi)流行的前端框架對(duì)于列表循環(huán)的支持,可以說(shuō)是解放了廣大 前端開(kāi)發(fā)人員,從前的jquery瘋狂拼接字符串,到后來(lái)使用一些插件,而現(xiàn)在,一切變得很簡(jiǎn)單
1.定義一組數(shù)組

const users = [{
    id:1,
    name:'張三',
    age:10
},{
    id:2,
    name:'李四',
    age:10
},{
    id:3,
    name:'王五',
    age:10
},{
    id:4,
    name:'趙六',
    age:10
}];

2.在render函數(shù)中首先根據(jù)數(shù)組生成列表組件

const tbodys = users.map((user)=>{
            return (
                <tr key={user.id}>
                    <td>{user.id}</td>
                    <td>{user.name}</td>
                    <td>{user.age}</td>
                </tr>
            )
   });

tbodys就是一個(gè)我們需要的列表組件,然后將其添加到render函數(shù)中返回的結(jié)構(gòu)中

return (
            <div className="container" style={{marginTop:'30px'}}>
                <div className="row">
                    <div className="col-md-8 col-md-offset-2">
                        <table className="table table-bordered">
                            <thead>
                                <tr>
                                  <th>id</th>
                                  <th>名稱</th>
                                  <th>年齡</th>
                                </tr>
                              </thead>
                              <tbody>
                                {tbodys}
                              </tbody>
                        </table>
                    </div>
                </div>

            </div>
        );

此時(shí)就得到一個(gè)完美的列表

列表

返回值得結(jié)構(gòu)中的組件與前面使用map函數(shù)的遍歷結(jié)構(gòu)是等價(jià)的,因此,我們可以直接JSX中使用map函數(shù)遍歷

render() {
        return (
            <div className="container" style={{marginTop:'30px'}}>
                <div className="row">
                    <div className="col-md-8 col-md-offset-2">
                        <table className="table table-bordered">
                            <thead>
                                <tr>
                                  <th>id</th>
                                  <th>名稱</th>
                                  <th>年齡</th>
                                </tr>
                              </thead>
                              <tbody>
                                {

                                    users.map((user)=>{
                                        return (
                                            <tr key={user.id}>
                                                <td>{user.id}</td>
                                                <td>{user.name}</td>
                                                <td>{user.age}</td>
                                            </tr>
                                        )
                                    })
                                }
                              </tbody>
                        </table>
                    </div>
                </div>

            </div>
        );
    }

寫(xiě)到這里呢,React從零開(kāi)始系 學(xué)習(xí)的系列就要結(jié)束了

之后我要重新回歸java的學(xué)習(xí)中了!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原教程內(nèi)容詳見(jiàn)精益 React 學(xué)習(xí)指南,這只是我在學(xué)習(xí)過(guò)程中的一些閱讀筆記,個(gè)人覺(jué)得該教程講解深入淺出,比目前大...
    leonaxiong閱讀 2,944評(píng)論 1 18
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,063評(píng)論 25 709
  • 原文地址:CSS clear both清除浮動(dòng) DIV+CSS clear both清除產(chǎn)生浮動(dòng)我們知道有時(shí)使用了...
    LOOK_LOOK閱讀 905評(píng)論 0 3
  • 今天已經(jīng)完成任務(wù)但還沒(méi)來(lái)的及發(fā)給他們看,誰(shuí)知道手機(jī)竟然沒(méi)信號(hào),想在宿舍用WIFI發(fā),不巧的是停電了。這些情況的罪魁...
    承思而行閱讀 221評(píng)論 0 0
  • 第一次見(jiàn)到她的時(shí)候,她正咬牙切齒的呵斥一個(gè)男人,惡狠狠的短悍樣子把我嚇呆了,我不敢呼吸,懦懦的移走,生怕被殃及。 ...
    魚(yú)麗枝閱讀 375評(píng)論 0 0

友情鏈接更多精彩內(nèi)容