概况:

通过本篇文章你可以对react的重点有个整体的认识。 关于react是什么,优点,解决什么问题等,网上一大推就不啰嗦了。

了解虚拟DOM的实现,参考这篇文章

[虚拟DOM]
(https://www.zhihu.com/question/29504639)

简单讲,其实就是用一个轻量级的dom结构(用js模拟实现),来模拟重量级的dom结构,通过比对轻量级结构后,在操作重量级dom结构提高性能,从而到达性能优化的目的。

生命周期:

快速学习react 先了解它的重中之重----生命周期, 一个组件在不同时期会调用不同时期的函数接口也就是对应的生命周期函数

装载时期的函数

getDefaultProps(是设置默认props)getInitialState(废弃,设置默认State) 依次执行以下函数

• constructor

• componentWillMount

• render

• componentDidMount

更新时期的函数

如果组件的数据有变化了(porp,state), 依次执行以下函数

• componentWillReceiveProps

• shouldComponentUpdate

• componentWillUpdate

• render

• componentDidUpdate

卸载时期的函数

销毁组件

•componentWillUnmount

1. import React,{ Component } from 'react';
2. class Demo extends Component {
3. constructor(props) {
4. // 构造函数,要创造一个组件类的实例,会调用对应的构造函数,
5. //一个react组件需要构造函数,往往为了两个目的.
6. //1:初始化state.2.绑定成员函数this环境。
7. // 无状态的函数就不需要构造函数,
8. super(props)
9. console.log("---初始化组件---")
10. this.state = {
11. test:'想要显示一段不一样的文字'
12. //定义state,存放页面的数据,通过this.setState()方法修改
13. //.this.setState()函数所做的事情,首先是改变this.state的值,然后驱动组件经历更新过程,这样才有机会让this.state里新的值出现在界面上。
14. }
15. }
16. componentWillMount () {
17. console.log("---组件挂载前---最先执行的函数")
18. }
19. componentDidMount () {
20. console.log("---组件挂载后---")
21. }
22. componentWillReceiveProps (nextProps) {
23. console.log("---父组件重新渲染---")
24. 值得注意的是,更新时期的componentWillReceiveProps函数,
25. 只要父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的Props有没有改变,都会触发子组件的componentWillReceiveProps函数,但是自身的this.setState方法触发的更新过程不会调用这个函数。
26. }
27. shouldComponentUpdate (nextProps,nextState) {
28. console.log("---组件接受到重绘状态---")
29. 它决定了一个组件什么时候不渲染。
30. 在更新过程中shouldComponemtUpdata 返回 false那就立刻停止更新。
31. this.setState函数后会执行shouldComponemtUpdata 然后在决定我要不要更新。
32. 相反 shouldComponemtUpdata 函数返回 TRUE,接下来就会依次调用
33. componentWillUpdata,render,componetDidUpdata函数,它把render像夹心面包似得夹在了中间。
34. }
35. componentWillUpdate (nextProps,nextState) {
36. console.log("---组件将要更新---")
37. }
38. componentDidUpdate (prevProps,prevState) {
39. console.log("---组件更新完毕---")
40. }
41. render () {
42. console.log("---组件渲染---")
43. return (
44. <div>{this.state.test}</div>
45. )
46. }
47. componentWillUnmount () {
48. console.log("---组件销毁---")
49. }
50. }
51. export default Demo;

componentWillMount 和componentDidMount的区别:componentWillMount 可以在服务器调用,也可以在浏览器调用但是componentDidMount只能在浏览器被调用,因为装载是一个组件放到DOM树上的过程,那么真正的装载是不可能在服务器上完成的,服务器的渲染并不会产生DOM树。所以我们可以利用这一点。在componentDidMount被调用时候,组件已经被装载到DOM树上了,可放心的去操作渲染出来的任何DOM。

编写组件:

组件间的传递通过props进行传递,看下面例子

   

 import React from 'react';

// 一级父组件

class Level1 extends React.Component{

   render(){

       return  <Level2 color='red'/>

   }

}

// 二级子组件

class Level2 extends React.Component{

   render(){

       return  <Level3 color={this.props.color}/>

   }

}

// 三级孙子组件

class Level3 extends React.Component{

   render(){

       return  <div color={{color: this.props.color}}/>

   }

}

也可以这样创建

  1. import React from 'react';
    
    const Level1 = React.createClass({  
    
     render() {
    
       return (
    
         <div></div>
    
       );
    
     }
    
    });
    
    export default Level1 ;  
React.createClass和extends Component的区别:

Component{}是ES6的写法,会自动继承Component里面的属性 createClass({})是React的ES5写法,会生成一个React Component 语法区别

• propType 和 getDefaultProps

• 状态的区别

• this区别

• Mixins

参考这篇文章

[React.createClass和extends Component的区别]
(https://segmentfault.com/a/1190000005863630)

如果你的组件是无状态的,纯输出组件也可以直接写成函数如下

  1. function Pure(props){
    
      return(
    
          <div>{props.xxxx}</div>
    
      )
    
    }

react 组件必须一级一级传递 ,如果想要越级传递,1直接到5,那么需要用到redux

redux

redux之前最好了解下flux,但是redux更加优秀。 react和redux事实上是两个独立的东西,如果你两者单独使用推荐react-redux库,我们从redux 使用方法开始,循序渐进过渡到react-redux,这个库可以让我们简化代码的书写

在redux框架下,一个react组件是这样运行的

读取Store的状态,用于初始化组件的状态,同时监听Store的状态改变,当Store状态发生改变时候,就需要更新组件的状态,从而驱动渲染。当需要更新store状态时,就要派发action对象。 根据当前props,和state,渲染用户界面。

项目结构

actions--->用户行为 components--->组件 containers--->容器 reducer--->一个纯函数返回新的state状态 store--> store里面负责分发action行为 index.html ---> 模板文件 webpack---> 打包配置文件

actions:

• 是一个行为的抽象

• 是普通JS对象

• 一般由方法生成

• 必须有一个type 我要添加一本书这个行为可以如下:

  1. const addTodo = (text) =>{
    
       retrun {
    
          type:'Add',
    
          id: nextTodoId++,
    
          text,
    
       }
    
    }

reducer:

• 是响应的抽象

• 是纯方法

• 传入旧的状态和action

• 返回新的状态

签名函数:reducer(state, action) state 是当前状态,action是接受到的action, 注意不能改变参数state和action

  1. const todo = (state, action) =>{
    
       switch (action.type){
    
       case "Add_Book":
    
        return
    
         {
    
             text: action.text,
    
        }
    
    }

用一个例子串起来:

设计一个具有加减功能的项目:

Actions.js:

export const increment = (counterCaption) => {

 return {

   type: increment,

   counterCaption: counterCaption

 };

};

export const decrement = (counterCaption) => {

 return {

   type: decrement,

   counterCaption,//es6写法等同于counterCaption: counterCaption

 };

};

Reducer.js:

export default (state, action) => {

 const {counterCaption} = action;//等同于const counterCaption= action.counterCaption;

 switch (action.type) {

   case increment:

     return {...state, [counterCaption]: state[counterCaption] + 1};

   case decrement:

     return {...state, [counterCaption]: state[counterCaption] - 1};

   default:

     return state

 }

}

//return {...state, [counterCaption]: state[counterCaption] - 1};等同于

//const newState = Object.assign({},state);

//newState[counterCaption]--;

//return newState;

Store.js:

import {createStore} from 'redux';

import reducer from './Reducer.js';

const initValues = {

 'First': 0,

 'Second': 10,

 'Third': 20

};

const store = createStore(reducer, initValues);

export default store;

//createStore是redux库提供的函数第一个参数是更新状态的reducer,第二参数是初始值

views(容器):

import React, { Component } from 'react';

import Counter from './Counter.js';

class ControlPanel extends Component {

 render() {

   return (

     <div>

       <Counter caption="First" />

       <Counter caption="Second" />

       <Counter caption="Third" />

     </div>

   );

 }

}

export default ControlPanel;

Counter.js(组件):

import React, { Component, PropTypes } from 'react';

import store from '../Store.js';

import * as Actions from '../Actions.js';

const buttonStyle = {

 margin: '10px'

};

class Counter extends Component {

 render() {

   const {caption, onIncrement, onDecrement, value} = this.props;

   return (

     <div>

       <button style={buttonStyle} onClick={onIncrement}>+</button>

       <button style={buttonStyle} onClick={onDecrement}>-</button>

       <span>{caption} count: {value}</span>

     </div>

   );

 }

}

//以下是对参数类型的定义,开启eslint需要写一下代码。

Counter.propTypes = {

 caption: PropTypes.string.isRequired,//表示caption是string类型,必填

 onIncrement: PropTypes.func.isRequired,

 onDecrement: PropTypes.func.isRequired,

 value: PropTypes.number.isRequired

};

class CounterContainer extends Component {

 constructor(props) {

   super(props);

   this.onIncrement = this.onIncrement.bind(this);

   this.onDecrement = this.onDecrement.bind(this);

   this.onChange = this.onChange.bind(this);

   this.getOwnState = this.getOwnState.bind(this);

   this.state = this.getOwnState();

 }

 getOwnState() {

   return {

     value: store.getState()[this.props.caption]

   };

 }

 onIncrement() {

   store.dispatch(Actions.increment(this.props.caption));

 }

 onDecrement() {

   store.dispatch(Actions.decrement(this.props.caption));

 }

 onChange() {

  //为了保持Store上的状态和this.state的同步

   this.setState(this.getOwnState());

 }

 shouldComponentUpdate(nextProps, nextState) {

   return (nextProps.caption !== this.props.caption) ||

     (nextState.value !== this.state.value);

 }

 componentDidMount() {

  //为了保持Store上的状态和this.state的同步

   store.subscribe(this.onChange);

 }

 componentWillUnmount() {

   //为了保持Store上的状态和this.state的同步

   store.unsubscribe(this.onChange);

 }

 render() {

//Counter 在上面

   return <Counter caption={this.props.caption}

     onIncrement={this.onIncrement}

     onDecrement={this.onDecrement}

     value={this.state.value} />

 }

}

CounterContainer.propTypes = {

 caption: PropTypes.string.isRequired

};

export default CounterContainer;

通常我们会把容器放在container文件夹下,把组件放在component下 

ControlPanel 根本就没有使用store,如果仅仅为了传递prop给组件counter就要求支持state prop,显然不合理,其中react提供了Context的功能可以解决这个问题;

Context:

我们增加Provider.js,代码如下:

import {PropTypes, Component} from 'react';

class Provider extends Component {

 getChildContext() {

   return {

     store: this.props.store

   };

 }

 render() {

   return this.props.children; //Provider包裹的子元素输出出来

 }

}

Provider.contextTypes = {

 store: PropTypes.object

}

export default Provider;

index.js 文件引入Provider

import React from 'react';

import ReactDOM from 'react-dom';

import ControlPanel from './views/ControlPanel';

import store from './Store.js';

import Provider from './Provider.js';

ReactDOM.render(

 <Provider store={store}>

   <ControlPanel />

 </Provider>,

 document.getElementById('root')

);

最后我们在修改ControlPanel中的Counter组件, 

React-Redux:

如果理解上面的例子之后你会发现有些复用的部分可以提取出来,各个组件关心自己的部分就行了,react-redux库就是解决这个事情的,让你开发爽到飞起

react-redux 规定,所有的 UI 组件都由用户提供,容器组件则是由 React-Redux 自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。

首先我们先了解一下重要的函数connect,React-Redux 提供connect方法,用于从 UI 组件生成容器组件,就是将这两种组件连起来。 connect方法的完整 API

import { connect } from 'react-redux'

const VisibleTodoList = connect(

 mapStateToProps,

 mapDispatchToProps

)(TodoList)

connect方法接受两个参数:mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

此时index.js文件变成:

import React from 'react';

import ReactDOM from 'react-dom';

import {Provider} from 'react-redux';

import ControlPanel from './views/ControlPanel';

import store from './Store.js';

ReactDOM.render(

 <Provider store={store}>

   <ControlPanel/>

 </Provider>,

 document.getElementById('root')

);

//Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了

Counter.js文件变成

import React, { PropTypes } from 'react';

import * as Actions from '../Actions.js';

import {connect} from 'react-redux';

const buttonStyle = {

 margin: '10px'

};

function Counter({caption, onIncrement, onDecrement, value}) {

 return (

   <div>

     <button style={buttonStyle} onClick={onIncrement}>+</button>

     <button style={buttonStyle} onClick={onDecrement}>-</button>

     <span>{caption} count: {value}</span>

   </div>

 );

}

Counter.propTypes = {

 caption: PropTypes.string.isRequired,

 onIncrement: PropTypes.func.isRequired,

 onDecrement: PropTypes.func.isRequired,

 value: PropTypes.number.isRequired

};

function mapStateToProps(state, ownProps) {

 return {

   value: state[ownProps.caption]

 }

}

function mapDispatchToProps(dispatch, ownProps) {

 return {

   onIncrement: () => {

     dispatch(Actions.increment(ownProps.caption));

   },

   onDecrement: () => {

     dispatch(Actions.decrement(ownProps.caption));

   }

 }

}

export default connect(mapStateToProps, mapDispatchToProps)(Counter);

connect函数实际上是个高阶函数,了解可以参考这边文章

[Higher-Order Components](https://reactjs.org/docs/higher-order-comonents.html)

关于react 路由可以参考这边文章

[路由](http://www.ruanyifeng.com/blog/2016/05/react_router.html?utm_source=tool.lu)

快速了解react的更多相关文章

  1. 使用create-react-app 快速构建 React 开发环境以及react-router 4.x路由配置

    create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. create-react-app 自动创建的项目是基于 Webpack + E ...

  2. 使用脚手架快速搭建React项目

    create-react-app是Facebook官方推出的脚手架,基本可以零配置搭建基于webpack的React开发环境步骤: 打开控制台 进入你想要创建项目的目录文件下面 依次执行以下命令 np ...

  3. Reactjs-generator-cli 一款基于Ink构建用于快速搭建React应用的CLI scaffolding工具

    Reactjs-generator-cli 一款基于Ink构建用于快速搭建React应用的CLI scaffolding工具 A simple CLI for scaffolding React.js ...

  4. vulcanjs 开源工具方便快速开发react graphql meteor 应用

    vulcan 开源工具方便快速开发react graphql meteor 应用 操作环境mac os 安装 meteor 安装(此安装有点慢,可以通过正确上网解决) curl https://ins ...

  5. 利用 Create React Native App 快速创建 React Native 应用

    本文介绍的 Create-React-Native-App 是非常 Awesome 的工具,而其背后的 Expo 整个平台也让笔者感觉非常的不错.笔者目前公司是采用 APICloud 进行移动应用开发 ...

  6. 【React】使用 create-react-app 快速构建 React 开发环境

    create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. create-react-app 自动创建的项目是基于 Webpack + E ...

  7. 快速入门react

    安装react npm install creat-react-app -g这里直接安装react的一个脚手架,里面包含了要用到的许多东西,帮助快速入门react 创建新项目 create-react ...

  8. 使用 dva + antd 快速开发react应用

    使用 dva + antd 快速开发react应用 版本说明: 注意:dva的版本是0.9.2 $ node -v v10.2.1 $ npm -v $ dva -v dva-cli version ...

  9. 快速构建 React 开发环境

    使用 create-react-app 快速构建 React 开发环境 create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境. cre ...

随机推荐

  1. Visual Studio 2017 Enterprise 发布 15.4 版本,离线安装包百度网盘下载。

    Visual Studio 2017 于2017年10月13日发布 15.4 版本.该版本包含多项生产力改进,支持 .NET Standard 2.0 ,并且可以开启 Xamarin Live Pla ...

  2. 让互联网更快:新一代QUIC协议在腾讯的技术实践分享

    本文来自腾讯资深研发工程师罗成在InfoQ的技术分享. 1.前言 如果:你的 App,在不需要任何修改的情况下就能提升 15% 以上的访问速度,特别是弱网络的时候能够提升 20% 以上的访问速度. 如 ...

  3. SpringMvc Ant通配符的使用

    @RequestMapping使用通配符来对地址进行映射 Ant 的3风格 – ? 匹配文件名中的一个字符 – *  匹配文件名中的任意字符 – ** ** 匹配多重路径 例如:RequestMapp ...

  4. 如何使用 libqr 库生成二维码?

    使用 libqr 库只需 4 步即可生成二维码 1.初始化 QRCode 结构体 QRCode *qrInit(int version, int mode, int eclevel, int mask ...

  5. 为什么java局部变量没有初始化就会报错,而成员变量没有初始化就不会报错?

    代码如下 1.局部变量,报错!!! public void test(){ int i; System.out.println(i); } 2.成员变量,输出0 int i; @Test public ...

  6. ElasticSearch AggregationBuilders java api常用聚会查询

    以球员信息为例,player索引的player type包含5个字段,姓名,年龄,薪水,球队,场上位置.index的mapping为: "mappings": { "pl ...

  7. IS-IS 路由协议 总结

    第一章 is-is的协议概述 1. 发展史 Is-is最早是iso为osi模型中CLNP而设计的协议,后来根据发展需要,也支持了TCP/IP协议,因此,is-is叫做integrated is-is或 ...

  8. SAS︱数据索引、数据集常用操作(set、where、merge、append)

    代码部分大多来源于姚志勇老师的<SAS编程与数据挖掘商业案例>. 每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ ------------ ...

  9. [Err] 1136 - Column count doesn't match value count at row 1

    1 错误描述 [Err] 1136 - Column count doesn't match value count at row 1 Procedure execution failed 1136 ...

  10. 利用Eclipse中的Maven构建Web项目(二)

    利用Eclipse中的Maven构建Web项目 1.新建源文件夹,Java Resources鼠标右键,"New-->Source Folder" 2.新建src/main/ ...