react基础小结

React是一个Facebook和Instagram用来创建用户界面的JavaScript库,用于构建“可预期的”和“声明式的”Web用户界面。 该框架的推出主要为了开发随着时间数据不断变化的大规模应用程序。 具体文档可以参考官网

React具有以下特点:
  • 1.声明式设计 −React采用声明范式,可以轻松描述应用。
  • 2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
  • 3.灵活 −React可以与已知的库或框架很好地配合。
  • 4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
  • 5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  • 6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

目录

1、构建与初始化
2、React元素
3、React组件
4、React组件生命周期
5、受控与非受控组件

1、构建与初始化

  • 方式一:如果你只是想简单尝试下 React,可以使用stackblitz。在这里,我必须推荐一下这个在线编辑器,你不需要安装任何东西,目前支持angular、react、ionic,迟点应该也会支持vue。支持github帐号登录,可以fork和share,一个专门为Web构建的更聪明、更快的包管理器。
  • 方式二:可以使用官网推荐用create-react-app的方式,是开始构建新的React单页面应用的最佳途径。它可以帮你配置开发环境,以便你可以使用最新的 JavaScript 特性,还能提供很棒的开发体验,并为生产环境优化你的应用。
// 在终端下全局安装官网推荐的create-react-app
npm install -g create-react-app
create-react-app my-app
cd my-app
npm start
  • 方式三: 可以使用像webpack或Browserify这样的构建工具,以便于编写模块代码并将其压缩,优化加载时间,这里推荐使用webpack方式。

2、React元素

react 是React库的入口点。如果你通过script标签加载React,这些高阶API可用于 React 全局。如果你使用ES6,你可以使用 import React from 'react' 。如果你使用ES5,你可以使用 var React = require('react')

  • 创建React元素有3种方式,注意:官网认为createFactor方法过时了,推荐你使用JSX或直接使用 React.createElement() 来替代它。JSX可以看做JavaScript的语法拓展(eXtension),看起来有点像XML,让我们可以在JavaScript中编写类似HTML的代码。 使用React,可以进行JSX语法到JavaScript的转换。判断一个元素是HTML元素还是React组件的原则是第一个字母是否大写,如果为大写,则认为是React组件,否则认为是HTML元素。如果我们自定义的组件首字母写成小写,那会得不到我们想要的结果。在JSX中可以通过onClick这样的方式来给一个元素添加事件处理函数,在HTML我们还可以用onclick(onclick和onClick是不同的)来添加事件

  • 第一种是React.createElement(type,[props],[...children])

var listItemElement1 = React.createElement('li', {className: 'item-1', key: 'item-1'}, 'Item-1')
var listItemElement2 = React.createElement('li', {className: 'item-2', key: 'item-2'}, 'Item-2')
var listItemElement3 = React.createElement('li', {className: 'item-3', key: 'item-3'}, 'Item-3')
var reactFragment = [listItemElement1, listItemElement2, listItemElement3];
var listOfItems = React.createElement('ul', {className: 'list-of-items'}, reactFragment);
  • 第二种是通过创建工厂函数React.createFactory(type),React.DOM.li(...) 是 React.createELement('li', ...) 的一个包装写法,但被官网认为是过时的,有可能最终会被遗弃。
var createListItemElement = React.createFactory('li');
var listItemElement1 = React.DOM.li({className: 'item-1', key: 'item-1'}, 'Item-1')
var listItemElement2 = React.DOM.li({className: 'item-2', key: 'item-2'}, 'Item-2')
var listItemElement3 = React.DOM.li({className: 'item-3', key: 'item-3'}, 'Item-3')
var reactFragment = [listItemElement1, listItemElement2, listItemElement3];
var listOfItems = React.createElement('ul', {className: 'list-of-items'}, reactFragment);
  • 第三种是使用JSX创建React元素,编写React的时候,JSX并不是必须的。每一个JSX元素都只是 React.createElement(component, props, ...children) 的语法糖。因此,任何时候你用JSX语法写的代码也可以用普通的 JavaScript 语法写出来。
var listOfItems = <ul className="list-of-items">
    <li className="item-1">Item 1</li>
    <li className="item-2">Item 2</li>
    <li className="item-3">Item 3</li>
</ul>;
//官网例子jsx写法
class Hello extends React.Component {
  render() {
    return <div>Hello {this.props.toWhat}</div>;
  }
}
//编译转成不使用JSX的代码
class Hello extends React.Component {
  render() {
    return React.createElement('div', null, `Hello ${this.props.toWhat}`);
  }
}
ReactDOM.render(
  React.createElement(Hello, {toWhat: 'World'}, null),
  document.getElementById('root')
);
  • 渲染React元素
//格式:ReactDOM.render(ReactElement, DOMElement, callback);
ReactDOM.render(
    listOfItems,
    document.getElementById('example')
)

3、React组件

  • 可以通过三种方式创建React组件,注意,组件类的第一个字母必须大写,否则会报错,比如HelloMessage不能写成helloMessage。另外,组件类只能包含一个顶层标签,否则也会报错。
  • 第一种无状态函数式组件,无状态函数式组件形式上表现为只带有一个render方法的组件类,通过函数形式或者ES6 arrow function的形式创建,并且该组件是无state状态的。只要有可能,尽量使用无状态组件。能用React.Component创建的组件的就尽量不用React.createClass形式创建组件。
function HelloComponent(props) {
    return <div> Hello {props.name} </div>;
}
ReactDOM.render(
    <HelloComponent name="world" />, 
    document.getElementById('example')
) 
  • 第二种React.createClass,它是react刚开始推荐的创建组件的方式,是用ES5的写法实现
var InputControlES5 = React.createClass({
    propTypes: {//定义传入props中的属性各种类型要求,可以接受任意值,字符串、对象、函数等等。
        initialValue: React.PropTypes.string.isRequired
    },
    defaultProps: { //用来设置组件属性的默认值
        initialValue: 'Hello World'
    },
    getInitialState: function() {//用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。
        return {
            text: this.props.initialValue || 'placeholder'
        };
    },
    handleChange: function(event) {
        this.setState({ //事件的回调函数,当用户交互导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用this.render方法,再次渲染组件。
            text: event.target.value
        });
    },
    render: function() {
        return (
            <div>
                Type something:
                <input onChange={this.handleChange} value={this.state.text} />
            </div>
        );
    }
});

ReactDOM.render(
    <InputControlES5 />, 
    document.getElementById('example')
)
  • 第三种是React.Component,它是以ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用。将上面React.createClass的形式改为React.Component形式如下:
class InputControlES6 extends React.Component {
    constructor(props) {
        super(props);  //调用super,是为了正确获取到this
        this.state = {
            text: props.initialValue || 'placeholder'
        };
        this.handleChange = this.handleChange.bind(this); // ES6 类中函数必须手动绑定
    }

    handleChange(event) {
        this.setState({
            text: event.target.value
        });
    }

    render() {
        return (
            <div>
                Type something:
                <input onChange={this.handleChange} value={this.state.text} />
            </div>
        );
    }
}

InputControlES6.propTypes = {
    initialValue: React.PropTypes.string.isRequired
};
InputControlES6.defaultProps = {
    initialValue: 'Hello Wrold'
};

ReactDOM.render(
    <InputControlES6 />, 
    document.getElementById('example')
)
React.createClass与React.Component区别
  • React.createClass 创建的组件,其每一个成员函数的this都有React自动绑定,任何时候,直接使用this.method即可,函数中的this会被正确设置
  • React.Component创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则将它作为事件处理函数被调用时不能通过this获取当前组件实例对象。
  • React.Component 有三种手动绑定方法:
    1、在构造函数中完成绑定
    2、调用时使用method.bind(this)来完成绑定
    3、使用arrow function 来绑定
  • 组件属性类型 propTypes 及其默认 props 属性 defaultProps 配置不同。
  • 组件初始状态state配置不同。React.createClass创建的组件,其状态state是通过getInitState方法方法来配置组件的相关状态。React.Component创建的组件,其状态state是在construct中像初始化组件属性一样声明。
  • Mixins的支持不同。React.createClass在创建组件时可以使用mixins属性,以数组的形式来混合类的集合。React.Component不支持Mixins,React开发者社区提供了一个全新的方式来取代Mixins,那就是Higher-Order Components(高阶组件)
//React.createClass
const Contacts = React.createClass({  
    handleClick() {
        console.log(this); // React组件实例
    },
    render() {
        return (
            <div onClick={this.handleClick}></div>
        );
    }
});
//React.Component
class Contacts extends React.Component {  
    constructor(props) {
        super(props);
    }
    handleClick() {
        console.log(this); // null
    }
    render() {
        return (
          <div onClick={this.handleClick}></div>
        );
    }
}
//React.Component绑定this方法
constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this); //构造函数中绑定
}
<div onClick={this.handleClick.bind(this)}></div> //使用bind来绑定
<div onClick={()=>this.handleClick()}></div> //使用arrow function来绑定

4、React组件生命周期

组件的生命周期分成三个状态:
  • 挂在(Mounting): 这个阶段发生在组件被创建并被插入到DOM时
  • 更新(Updating): 这个阶段发生在组件被重新渲染成虚拟DOM并决定实际DOM是否需要更新时
  • 卸载(Unmounting): 这个阶段发生在组件从DOM中被删除时
组件挂载阶段
ES5(React.createClass)
  • getInitialState()
  • componentWillMount()
  • render()
  • componentDidMount()
ES6(React.Component)
  • constructor()
  • componentWillMount()
  • render()
  • componentDidMount()
组件更新阶段
  • componentWillReceiveProps()
  • shouldComponentUpdate()
  • componentWillUpdate()
  • render()
  • componentDidUpdate()
组件卸载阶段
  • componentWillUnmount()
var Hello = React.createClass({
    getInitialState: function () {
        return {
            opacity: 1.0
        };
    },
    componentDidMount: function () {
        this.timer = setInterval(function () {
            var opacity = this.state.opacity;
            opacity -= .05;
            if (opacity < 0.1) {
                opacity = 1.0;
            }
            this.setState({
                opacity: opacity
            });
        }.bind(this), 100);
    },
    render: function () {
        return (
            <div style={{opacity: this.state.opacity}}>
                Hello {this.props.name}
            </div>
        );
    }
});
ReactDOM.render(
    <Hello name="world"/>,
    document.body
);

5、受控与非受控组件

React 通过props和state来区分组件的属性和状态。其中,props(属性)用来表示组件外部传入的属性,组件内部不能改变。而state(状态)通常表示组件内部的状态,状态是可以并且应该改变的。React通过 props和state的值来渲染组件,组件渲染完毕之后,通过响应用户操作或者异步网络请求等操作更新组件的状态来重新渲染组件。

  • 受控组件将表单数据统一存放在 state 中,交由 React 管理,我们就可以根据用户的输入及时作出响应:1、验证输入正确性(输入格式、类型等),并作出反馈 2、根据输入设置其它组件的状态,譬如输入不规范时,提交按钮处于不可用状态
class ControlledForm extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            username: ''
        }
        this.handleSubmit = this.handleSubmit.bind(this);
        this.updateUsername = this.updateUsername.bind(this);
    }

    updateUsername(e) {
        this.setState({
            username: e.target.value,
        })
    }

    handleSubmit() {}

    render () {
        return (
            <form onSubmit={this.handleSubmit}>
                <input
                    type='text'
                    value={this.state.username}
                    onChange={this.updateUsername} />
                <button type='submit'>Submit</button>
            </form>
        )
    }
}
ReactDOM.render(<ControlledForm />, document.getElementById('react-root'))
  • 非受控组件和传统的表单数据管理一样,由DOM存放表单数据,可以使用React提供的refs来获得DOM元素的引用。在需要的时候(譬如表单提交的时候)一次性获取表单的值。
class UnControlledForm extends React.Component {
    constructor(props) {
        super(props);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleSubmit(e) {
        e.preventDefault();
        console.log("Value: ", this.input.value)
    }

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

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,809评论 1 18
  • GUIDS 第一章 为什么使用React? React 一个提供了用户接口的JavaScript库。 诞生于Fac...
    jplyue阅读 3,515评论 1 11
  • 3. JSX JSX是对JavaScript语言的一个扩展语法, 用于生产React“元素”,建议在描述UI的时候...
    pixels阅读 2,804评论 0 24
  • 本笔记基于React官方文档,当前React版本号为15.4.0。 1. 安装 1.1 尝试 开始之前可以先去co...
    Awey阅读 7,647评论 14 128
  • 因为一个眼神,爱上一个人 因为一个人,爱上一座城 因为一座城,爱上整个世界 冥冥之中,仿佛早已注定 你我的相遇恰到...
    东风东风阅读 143评论 4 8