概况:

通过本篇文章你可以对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. B2B2C商品模块数据库设计

    kentzhu: 在电子商务里,一般会提到这样几个词:商品.单品.SPU.SKU 简单理解一下,SPU是标准化产品单元,区分品种:SKU是库存量单位,区分单品:商品特指与商家有关的商品,可对应多个SK ...

  2. 【天坑】ASP.net WebAPI跨域调用问题

    最近在做一个项目,前端是VUE,后端是WebAPI,业务也就是一些实体的增删改查.在项目开始的时候我就预计到有跨域的问题,所以也找了一下资料,在Web.Config里面加上了配置信息: <htt ...

  3. 从 PHP 到 Java

    * { color: #3e3e3e } body { font-family: "Helvetica Neue", Helvetica, "Hiragino Sans ...

  4. VNCServer,SSH Secure Shell Client,window远程控制linux

    1.VNC远程连接linux图形化桌面 2.SSH Secure Shell Client连接linux终端 3.设置FTP与linux传输文件 1.VNC远程连接linux图形化桌面 在centos ...

  5. hive:框架理解

    1. 什么是hive  •Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能. •本质是将HQL转换为MapReduce程序  2. 为什么 ...

  6. 3_Longest Substring Without Repeating Characters -- LeetCode

    C++解法一: class Solution { public: int lengthOfLongestSubstring(string s) { ] = {},left = , res = ; ; ...

  7. ClientToScreen 和ScreenToClient 用法

    ClientToScreen( )是把窗口坐标转换为屏幕坐标 ScreenToClient( )是把屏幕坐标转换为窗口坐标 屏幕坐标是相对于屏幕左上角的,而窗口坐标是相对于窗口用户区左上角的 VC下, ...

  8. echarts中地图提示"TypeError:i is undefined"

    1.错误描述 2.错误原因 刚开始地图的数据源是由静态数据提供,后来修改成从数据库中获取,请求数据的方法成功后调用地图方法,但是初始化时未调用数据请求方法,导致地图核心js报错 3.解决办法 初始化时 ...

  9. Java代码输出是“father”还是“child”(二)

    1.实例 /** * 以下代码输出的结果是 */ package com.you.model; /** * @author YouHaidong * 输出的结果 */ public class Fat ...

  10. 如何登录mysql? cmd怎么连接mysql数据库||从MYSQL客户端登录MYSQL

    1 2 3 4 5 6 7 分步阅读 Mysql开源数据库,任何人都可以下载安装使用.那么安装好的mysql如何登陆连接mysql数据库呢?本经验咗嚛介绍几种常见的方法 工具/原料   mysql 连 ...