React从零开始(2)——一个详细的范例

范例说明

接下来我们要通过一个简单的案例,详细的学习React的内容


1-1

如上图所示,两个按钮,点击加号按钮,数字加一,点击减号按钮,数字减一

代码结构

使用create-react-app创建一个工程,将其中的代码结构删减到最简单的模式

1-2

修改index.js

index.js中的代码就很简单了,只要引入App组件,执行渲染即可

import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App'

ReactDOM.render(<App/>, document.getElementById('root'));

组件的基本内容

App.js中的内容才是我们要真正实现的逻辑,我们将使用ES6的方式创建一个React的组件,步骤如下

  1. 引入react
import React from 'react'

2.创建组件,并让组件继承React.Component,同时实现render函数

class App extends React.Component{

    render(){
        return (
            <div>

            </div>
        )
    }
}

3.为组件指定默认输出

export default App

完整代码如下:

import React from 'react';

class App extends React.Component{

    render(){
        return (
            <div>

            </div>
        )
    }
}

export default App;
  • React.Component是react的一个抽象基类,单独引用它毫无意义,我们通常用其来实现子类,实现子类的时候必须要实现其render函数
  • render函数的所用是返回组件的内容,而渲染的过程是有 react框架来完成的,在return()中只能有一个顶级的标签元素
  • export default指定了当前组件输出的默认模块

功能实现

范例中的内容可分为四个部分

1.加号按钮
2.减号按钮
3.简单文本
4.鼠标点击按钮变化的数字

其中按钮和文本都非常简单,但是数字需要鼠标点击进行改变的,假如我们没有学习过任何的前端框架,我们就要使用document对象,获取页面的内容,然后将其装换为数字,再对数字进行计划,然后将计算结果写入页面。而使用react来实现,我们需要知道,react的核心目标 组件化,组件中可变换的内容称之为状态

组件中的数据来源有两种,内部声明外部传入,分别用state和prop进行区别和表示,在es6组件中,可以通过constructor构造函数中接收外部传来的prop和声明内部使用的状态数据,在本文的范例中,我们需要用到一个在鼠标点击后不断变化的数字

constructor(props){
    super(props);
    this.state = {
        count:0
    }
}

我们已经声明了内部状态,并接收了外部传入的数组,下面我实现页面的展示内容,即实现render函数中的内容

    render(){
        return (
            <div>
                <button>+</button>
                <button>+</button>
                <span>当前点击次数</span>
                <span>{this.state.count}</span>
            </div>
        )
    }
1-3

渲染效果如图1-3所示

内容美化

从页面效果来看,各个元素紧靠在一起,不太好看,我们通过简单的css对其进行美化,要达到的目标是:

  • 整个内容增加上边距和左边距
  • 按钮、文本、数字相互之间有一定的间距

在react中,使用css的方式与传统的方式有不同的地方

  • 引入外部样式文件
    新建style/App.css
.box{
    margin-left: 50px;
    margin-top: 50px;
}
.box *{
    margin:auto 5px;
}

在App.js引入这个css文件

import '../style/App.css'

在这里要值得注意的是,在react中,class属性要写成className,因为class是 JavaScript 的保留字

    render(){
        return (
            <div className="box">
                <button>+</button>
                <button>-</button>
                <span>当前点击次数</span>
                <span>{this.state.count}</span>
            </div>
        )
    }
1-4
  • 使用JavaScript对象来声明样式
    render(){
        const style={
            marginLeft:'50px',
            marginTop:'50px'
        }
        const item = {
            margin:'auto 5px'
        }
        return (
            <div style={style}>
                <button style={item}>+</button>
                <button style={item}>-</button>
                <span style={item}>当前点击次数</span>
                <span style={item}>{this.state.count}</span>
            </div>
        )
    }

运行效果与图1-4一样

使用对象声明样式时,要使用camelCase,也就是驼峰式命名法

  • 将样式对象直接写到html中
    render(){
        return (
            <div style={{marginLeft:'50px',marginTop:'50px'}}>
                <button style={{margin:'auto 5px'}}>+</button>
                <button style={{margin:'auto 5px'}}>-</button>
                <span style={{margin:'auto 5px'}}>当前点击次数</span>
                <span style={{margin:'auto 5px'}}>{this.state.count}</span>
            </div>
        )
    }

可以看到,style属性中的内容使用了两层大括号,其中外层的大括号是React表达式,内层的大括号是JavaScript对象

上述三种css的书写方式的效果是一样的,在后续的范例中,为了让代码简单直观,采用引入外部css文件的方式

按钮事件

接下来为两个按钮增加点击事件,react中的点击事件为onClick,它与html中的onclick有一些区别,在这里不进行详细描述。我们为加号按钮增加事件处理函数increment,为减号增加事件处理函数decrement。在increment,让state中的count的值加1,在decrement中,让state中count的值减1

注意点:

事件函数绑定this
修改state的方式

import React from 'react';
import '../style/App.css'

class App extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            count:0
        }
        this.increment = this.increment.bind(this);
        this.decrement = this.decrement.bind(this);
    }

    increment(){
        this.setState({count:this.state.count+1})
    }

    decrement(){
        this.setState({count:this.state.count-1})
    }

    render(){
        return (
            <div className="box">
                <button onClick={this.increment}>+</button>
                <button onClick={this.decrement}>-</button>
                <span>当前点击次数</span>
                <span>{this.state.count}</span>
            </div>
        )
    }
}

export default App;

  • 修改state中的数据,要调用setState函数来进行设置
  • 定义普通的的函数来处理事件,需要在构造函数中与this进行绑定,否则在函数内部,thisundefined

此时我们在页面点击按钮,就能看到效果了

让绑定this的方式完美一些

在上面的代码中,我们可以看到,事件处理函数要在构造函数中调用bind函数来绑定this,在这里我们只有两个函数,在复杂引用中可能有更多的函数,要是每一个函数都要这么绑定一次,对于有强迫症或者洁癖的开发人员来说是一件非常闹心且痛苦的事情。因此我们要使用更加简洁的方式

请看代码

import React from 'react';
import '../style/App.css'

class App extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            count:0
        }

    }

    increment  = () => {
        this.setState({count:this.state.count+1})
    }

    decrement = () => {
        this.setState({count:this.state.count-1})
    }

    render(){
        return (
            <div className="box">
                <button onClick={this.increment}>+</button>
                <button onClick={this.decrement}>-</button>
                <span>当前点击次数</span>
                <span>{this.state.count}</span>
            </div>
        )
    }
}

export default App;

点击按钮效果完全一样,整个世界都干净了!

从外部传入数据

在前面我们说到,props是用来从外部传递数据的,那么它是如何传递的呢?

在index.js中我们为App标签添加属性name

ReactDOM.render(<App name="当前点击次数"/>, document.getElementById('root'));

然后修改App.js中的render函数

    render(){
        return (
            <div className="box">
                <button onClick={this.increment}>+</button>
                <button onClick={this.decrement}>-</button>
                <span>{this.props.name}</span>
                <span>{this.state.count}</span>
            </div>
        )
    }

运行效果与之前是一样的!

到这里呢,这个简单而又覆盖到react的大部分内容的范例就说完了!上手试试,其实很简单的!

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

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,771评论 1 18
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,598评论 25 707
  • 项目地址 从头开始建立一个React App - 项目基本配置 npm init 生成 package.json ...
    瘦人假噜噜阅读 89,129评论 33 78
  • 励志小故事:乐观者与悲观者 父亲欲对一对孪生兄弟作性格改造,因为其中一个过分乐观,而另一个则过分悲观。一天,他买了...
    艺趣书苑阅读 1,786评论 0 1
  • 最美不过四月天,恰逢天清气朗,邀上几位好友孩子们驱车前来感受龙井水库风釆。湖水一波万顷,却也不曾见识过如此静谧秀丽...
    小房子梅子姐姐阅读 1,461评论 0 2