React从零开始(4)——表单和列表

表单是前端开发中必不可少的组件,React作为前端框架,如果不能处理表单,就会被亿万的前端工程师吐槽的。然而React对于表单的处理,还是有一些细节上的东西需要关注,接下来我们详细的描述在React中如何使用表单组件。

为了让页面效果美观一点,在页面中引入bootstrap的css

npm install bootstrap --save

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

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

我们操作使用react,开发中最多的内容就是操作state中的数据,那么进行表单开发,就是要将表单中的数据与state中的数据关联起来,也就是说,当用户改变表单中的数据时,state中的数据也会相应的发生修改,当state中的数据发生了修改,form中的数据也会进行相应的变化。这种变化,以Angularjs的双向绑定最为著名,然而,react并没有使用双向绑定,而是使用了单向数据流。

单向数据流

在这里描述单向数据流,并不采用一些比较正规的说法,我所说的是在开发中的直观感受。在前端开发过程中,数据最终展示在页面中,需要经过一个渲染过程,即改变浏览器页面中的DOM结构或者DOM中的内容,从而浏览器进行了解析渲染,如果要开发人员手动写原生的JS代码操作DOM,在开发复杂应用时,那将是一个极其痛苦的过程。单向数据流的作用就是,当内存中的数据发生变化时,在页面的相应位置上,会自动的渲染这些数据,这就意味着开发人员不再写DOM操作的代码。

所谓单向数据流,意味着数据从一个地方流向另一个地方,即从浏览器内存页面DOM树

单向数据流

这就是react的强大之处,同时也是其短板之处,从内存到DOM,可以自动渲染,但是从DOM到内存,就需要开发人员手动处理。

创建表单

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;

此时的表单中,其内部数据的状态由其自身维持,当用户在表单中进行输入时,表单的数据状态发生了变化,但是state中的状态仍然保持原状态,React只对表单组件进行了渲染,但并未控制其后续输入的变化,我们称此时的表单组件为非受控组件

让React渲染表单组件,组件中的值由React赋予,并控制其因用户输入所带来的变化,即让表单组件成为受控组件

  1. 表单组件的value值由React进行初始化
<input type="text" className="form-control" id="name" value={this.state.name} name="name" placeholder="用户名" onChange={this.handleChange}/>
  1. 监听组件change事件,将其变化的值修改保存到state中
handleChange = (event) =>{
    this.setState({
        [event.target.name]:event.target.value
    });
}

对于text,textarea,上述的方式均可,radio由于是单选,所以仍旧可以按照text的方式进行处理,但是对于checkbox,就需要做特殊的处理了

    <div className="form-group">
        <label className="col-sm-2 control-label">爱好</label>
        <div className="col-sm-10">
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="1"/>音乐
                </label>
            </div>
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="2"/>美术
                </label>
            </div>
            <div className="checkbox">
                <label>
                    <input type="checkbox" name="hobby" value="3"/>体操
                </label>
            </div>
        </div>
    </div>

checkbox组件为多选,所以,state中就需要使用数组来存储数据

  1. 使用onChange事件控制组件
  2. 修改state属性,要根据组件的checked属性来判断
    3.设置组件中的checked的值,需要根据state中的数据进行判断
  • 初始化state
    constructor(props){
        super(props);
        this.state = {
            music:false,
            draw:false,
            gymnastics:false
        };
    }
  • 为组件绑定onChange并对其checked进行判断
    <div className="form-group">
    <label className="col-sm-2 control-label">爱好</label>
    <div className="col-sm-10">
        <div className="checkbox">
            <label>
                <input type="checkbox" name="music" checked={this.state.music} onChange={this.handleChange}/>音乐
            </label>
        </div>
        <div className="checkbox">
            <label>
                <input type="checkbox" name="draw" checked={this.state.draw} onChange={this.handleChange}/>美术
            </label>
        </div>
        <div className="checkbox">
            <label>
                <input type="checkbox" name="gymnastics" checked={this.state.gymnastics} onChange={this.handleChange}/>体操
            </label>
        </div>
    </div>
</div>
  • 在onChange函数中进行数据处理
    handleChange = (event) =>{
        var temp = {
            [event.target.name]:event.target.checked
        };
        this.setState(temp);
    }

列表

现在业内流行的前端框架对于列表循环的支持,可以说是解放了广大 前端开发人员,从前的jquery疯狂拼接字符串,到后来使用一些插件,而现在,一切变得很简单
1.定义一组数组

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

2.在render函数中首先根据数组生成列表组件

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

tbodys就是一个我们需要的列表组件,然后将其添加到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>
                                {tbodys}
                              </tbody>
                        </table>
                    </div>
                </div>

            </div>
        );

此时就得到一个完美的列表

列表

返回值得结构中的组件与前面使用map函数的遍历结构是等价的,因此,我们可以直接JSX中使用map函数遍历

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>
        );
    }

写到这里呢,React从零开始系 学习的系列就要结束了

之后我要重新回归java的学习中了!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,807评论 1 18
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,140评论 25 707
  • 原文地址:CSS clear both清除浮动 DIV+CSS clear both清除产生浮动我们知道有时使用了...
    LOOK_LOOK阅读 871评论 0 3
  • 今天已经完成任务但还没来的及发给他们看,谁知道手机竟然没信号,想在宿舍用WIFI发,不巧的是停电了。这些情况的罪魁...
    承思而行阅读 179评论 0 0
  • 第一次见到她的时候,她正咬牙切齿的呵斥一个男人,恶狠狠的短悍样子把我吓呆了,我不敢呼吸,懦懦的移走,生怕被殃及。 ...
    鱼丽枝阅读 296评论 0 0