React从入门到实战- 企业级实战项目-宜居二

2019年最新 React从入门到实战(带 React 企业级实战项目-宜居)

(React-Redux基础知识&)

React-Redux基础知识&

41.Redux 回顾组件传递及Redux介绍

(Redux 回顾组件传递及Redux介绍&)

Redux 回顾组件传递及Redux介绍&

React从入门到实战- 企业级实战项目-宜居二_第1张图片

父传子

React从入门到实战- 企业级实战项目-宜居二_第2张图片

React从入门到实战- 企业级实战项目-宜居二_第3张图片

子传父

React从入门到实战- 企业级实战项目-宜居二_第4张图片

接收数据

React从入门到实战- 企业级实战项目-宜居二_第5张图片

默认什么都没有点击传值

React从入门到实战- 企业级实战项目-宜居二_第6张图片

React从入门到实战- 企业级实战项目-宜居二_第7张图片

普通情况只能组件间传递数据,redux子组件把数据传递给仓库,store负责把数据分发各个组件

React从入门到实战- 企业级实战项目-宜居二_第8张图片

把数据提交到公共的stroe仓库中

React从入门到实战- 企业级实战项目-宜居二_第9张图片

组件间通信

src\components\coms\Parent.jsx

import React from "react"
import Child from "./Child"

export default class Parent extends React.Component{

    state = {
        value:""
    }

    clickHandle = (data) =>{
        this.setState({
            value:data
        })
    }

    render(){
        return(
            
Parent:{ this.state.value }
) } }

src\components\coms\Child.jsx

import React from "react"

export default class Child extends React.Component{

    clickHandle = (e) =>{
        this.props.onMyEvent("父标题");
    }
    
    render(){
        return(
            
Child:{ this.props.title }
) } }

App.js

import React from 'react';
import Parent from "./components/coms/Parent"
import { connect } from "react-redux"
// import { increment,decrement } from "./actions/counter"
import * as counterActions from "./actions/counter"
import { bindActionCreators } from "redux"
import User from "./components/user"

class App extends React.Component {
    render(){
        return (
            
{/* */}

{ this.props.counter }

{/* */} {/* */}

); } } const mapStateToProps = (state) =>{ console.log(state); return{ counter:state.counter } } // const mapDispatchToProps = (dispatch) =>{ // return { // increment: () => { dispatch(increment()) }, // decrement: () => { dispatch(decrement()) } // } // } const mapDispatchToProps = (dispatch) =>{ return{ counterActions:bindActionCreators(counterActions,dispatch) } } // 先后顺序不能颠倒 export default connect(mapStateToProps,mapDispatchToProps)(App)

index.js

createStore

React从入门到实战- 企业级实战项目-宜居二_第10张图片

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"

// 异步和同步
// 定时器  网络请求


// 中间件
// const logger = store  => next => action =>{
//     console.log("dispatch->",action);
//     let result = next(action); // 加载下一个中间件
//     console.log("next state->",store.getState());
//     return result;
// }

// const error = store => next => action => {
//     try{
//         next(action)
//     }catch(e){
//         console.log("error->",e);
//     }
// }

// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))

// const render = () => {
//     ReactDOM.render(
//          store.dispatch({ type: "INCREMENT" })}
//             onDecrement={() => store.dispatch({ type: "DECREMENT" })}
//             value={store.getState()}
//         />,
//         document.getElementById('root'));

// }
// render();
// store.subscribe(render)




ReactDOM.render(
    
        
    
    ,
    document.getElementById('root'));

42.BootStrap CDN加载

(BootStrap CDN加载&)

BootStrap CDN加载&

CDN加载

引入CDN

编写视图

React从入门到实战- 企业级实战项目-宜居二_第11张图片

React从入门到实战- 企业级实战项目-宜居二_第12张图片

react-redux-demo\public\index.html



  
    
    
    
    
    
    
    
    
    
    
    React App
  
  
    
    

43.Redux 引入Redux

(Redux 引入Redux&)

Redux 引入Redux&

Redux应用的是单一的stroe

React从入门到实战- 企业级实战项目-宜居二_第13张图片

Reducer存在stroe中改变状态的方案

React从入门到实战- 企业级实战项目-宜居二_第14张图片

Reducer写法,state往仓库中存的状态,默认state为0,action.type不同的状态改变state

React从入门到实战- 企业级实战项目-宜居二_第15张图片

Store.dispatch触发来更新state的

React从入门到实战- 企业级实战项目-宜居二_第16张图片

reducer点击触发action.type,在App接收触发两个事件,action动作要对应到reducer一样的字符。

React从入门到实战- 企业级实战项目-宜居二_第17张图片

React从入门到实战- 企业级实战项目-宜居二_第18张图片

监听数据的变化,store.getState读取到数据

subscribe监听数据变化

React从入门到实战- 企业级实战项目-宜居二_第19张图片

React从入门到实战- 企业级实战项目-宜居二_第20张图片

渲染到页面上

React从入门到实战- 企业级实战项目-宜居二_第21张图片

React从入门到实战- 企业级实战项目-宜居二_第22张图片

要重新渲染,首先要render()以后每次监听数据变化要重新渲染render

重新渲染render

React从入门到实战- 企业级实战项目-宜居二_第23张图片

src\reducers\counter.js

reducer

import * as actions from "../constants"

const counter = ( state = 0,action ) => {
    switch(action.type){
        case actions.INCREMENT:
            // throw new Error("error reducer")
            return state + action.num;
        case actions.DECREMENT:
            return state - action.num;
        default:
            return state;
    }
}

export default counter

src\constants\index.js

// counter
export const INCREMENT = "INCREMENT"
export const DECREMENT = "DECREMENT"

// user
export const FETCH_USER_SUCCESS = "FETCH_USER_SUCCESS"
export const FETCH_USER_REQUEST = "FETCH_USER_REQUEST";
export const FETCH_USER_FAILURE = "FETCH_USER_FAILURE";

44.Redux 引入React-Redux与mapStateToProps读取数据

(Redux 引入React-Redux与mapStateToProps读取数据&)

Redux 引入React-Redux与mapStateToProps读取数据&

组件通过Mouse触发到Provider身上形成多个Actions动作,触发store当中的reducer,reducer就会发生改变,有多少个action就会对应多少store和reducer

React从入门到实战- 企业级实战项目-宜居二_第24张图片

Provider用来包裹的关联上redux和react,不要任何的操作了,单纯应用App,需要store对象

React从入门到实战- 企业级实战项目-宜居二_第25张图片

通过Provider本身额外的操作,store是刚刚创建的store,通过provider关联react和redux

react-redux

React从入门到实战- 企业级实战项目-宜居二_第26张图片

组件中读取数据

通过connect把App组件与redux连接起来。

按钮操作的两个事件,外面没有传递操作事件了。

mapStateToProps对象读取数据的方案,通过state参数,counter中能读到数据,放到connect()中。Connect连接组件与redux,读取数据

mapStateToProps读取数据

React从入门到实战- 企业级实战项目-宜居二_第27张图片

State本身就是counter的值

读取数据要从props中读到数据

45.Redux dispatch与mapDispatchToProps修改数据方案

(Redux dispatch与mapDispatchToProps修改数据方案&)

Redux dispatch与mapDispatchToProps修改数据方案&

操作和修改数据通过dispatch,要单独创建action操作,要提取action操作方便后期维护

React从入门到实战- 企业级实战项目-宜居二_第28张图片

Return type值

React从入门到实战- 企业级实战项目-宜居二_第29张图片

引入action的操作对象

mapDispatchToProps用来分发事件的,dispatch触发事件的

注意Connect的顺序不能颠倒

dispatch触发action

React从入门到实战- 企业级实战项目-宜居二_第30张图片

Props中有了increment

通过dispatch触发increment()函数,需要props

React从入门到实战- 企业级实战项目-宜居二_第31张图片

没有dispatch可以触发函数,props中有increment函数

React从入门到实战- 企业级实战项目-宜居二_第32张图片

src\actions\counter.js

import * as actions from "../constants"
// export function increment(num){
//     return{
//         type:actions.INCREMENT,
//         num
//     }
// }

export function increment(num){
    return dispatch => {
        setTimeout(() =>{
            dispatch({
                type:actions.INCREMENT,
                num
            })
        },1000)
    }
}


export function decrement(num){
    return{
        type:actions.DECREMENT,
        num
    }
}

46.Redux bindActionCreators与参数传递

(Redux bindActionCreators与参数传递&)

Redux bindActionCreators与参数传递&

Action中有很多的操作另一种方式,写起来更容易一些

mapDispatchToProps操作方法变简单了,通过bindActionCreators绑定所有的actions

React从入门到实战- 企业级实战项目-宜居二_第33张图片

操作方法简单了,操作按钮修改,通过this.props.counterActions中的increment方法操作,事件触发不是触发函数了。

React从入门到实战- 企业级实战项目-宜居二_第34张图片

方法的字符串要有reducer的action.type对应,不用写非常多的actions动作。

React从入门到实战- 企业级实战项目-宜居二_第35张图片

字符串要对应,通过常量文件夹管理。

React从入门到实战- 企业级实战项目-宜居二_第36张图片

React从入门到实战- 企业级实战项目-宜居二_第37张图片

常量字符串,action参数传递

React从入门到实战- 企业级实战项目-宜居二_第38张图片

直接引用

React从入门到实战- 企业级实战项目-宜居二_第39张图片

React从入门到实战- 企业级实战项目-宜居二_第40张图片

按照指定数字增加与减少,参数传递,参数传递给了action,操作的是actions

真正操作的是reducer,前后一样可以省略

React从入门到实战- 企业级实战项目-宜居二_第41张图片

参数传递,直接通过前台数据传递到后台actions,通过actions响应到reducers,接收数据

React从入门到实战- 企业级实战项目-宜居二_第42张图片

src\actions\counter.js

import * as actions from "../constants"
// export function increment(num){
//     return{
//         type:actions.INCREMENT,
//         num
//     }
// }

export function increment(num){
    return dispatch => {
        setTimeout(() =>{
            dispatch({
                type:actions.INCREMENT,
                num
            })
        },1000)
    }
}


export function decrement(num){
    return{
        type:actions.DECREMENT,
        num
    }
}

src\reducers\counter.js

import * as actions from "../constants"

const counter = ( state = 0,action ) => {
    switch(action.type){
        case actions.INCREMENT:
            // throw new Error("error reducer")
            return state + action.num;
        case actions.DECREMENT:
            return state - action.num;
        default:
            return state;
    }
}

export default counter

47.Redux combineReducers合并reducer

(Redux combineReducers合并reducer&)

Redux combineReducers合并reducer&

State中有很多条数据,很多数据需要共享,要合并reducer

React从入门到实战- 企业级实战项目-宜居二_第43张图片

通过combineReducers来合并reducers

React从入门到实战- 企业级实战项目-宜居二_第44张图片

外层引用关系不需要引用reducer了,直接引用rootReducers

React从入门到实战- 企业级实战项目-宜居二_第45张图片

此时相当于给counter多加了一个对象,state代表一个对象,要读取state里面的counter

React从入门到实战- 企业级实战项目-宜居二_第46张图片

新增User组件在App中引用

React从入门到实战- 企业级实战项目-宜居二_第47张图片

React从入门到实战- 企业级实战项目-宜居二_第48张图片

User数据也是共享的,为User也创建一系列的数据

React从入门到实战- 企业级实战项目-宜居二_第49张图片

React从入门到实战- 企业级实战项目-宜居二_第50张图片

State中有多条数据了

React从入门到实战- 企业级实战项目-宜居二_第51张图片

React从入门到实战- 企业级实战项目-宜居二_第52张图片

combineReducers合并reducers

src\reducers\index.js

import { combineReducers } from "redux"
import counter from "./counter"
import user from "./user"

const rootReducer = combineReducers({
    counter,
    user
})

export default rootReducer

src\reducers\user.js

import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"

const initialState = {
    user:{},
    isFetching: false,
    error: null,
}

const user = ( state = initialState,action ) => {
    switch(action.type){
        case FETCH_USER_SUCCESS:
            return {
                isFetching: false,
                error: null,
                user: action.user
            };
        case FETCH_USER_REQUEST:
            return {
                isFetching: true,
                error: null,
                user: {}
            }
        case FETCH_USER_FAILURE:
            return {
                isFetching: false,
                error: action.error,
                user: {}
            };
        default:
            return state;
    }
}

export default user

App.js

import React from 'react';
import Parent from "./components/coms/Parent"
import { connect } from "react-redux"
// import { increment,decrement } from "./actions/counter"
import * as counterActions from "./actions/counter"
import { bindActionCreators } from "redux"
import User from "./components/user"

class App extends React.Component {
    render(){
        return (
            
{/* */}

{ this.props.counter }

{/* */} {/* */}

); } } const mapStateToProps = (state) =>{ console.log(state); return{ counter:state.counter } } // const mapDispatchToProps = (dispatch) =>{ // return { // increment: () => { dispatch(increment()) }, // decrement: () => { dispatch(decrement()) } // } // } const mapDispatchToProps = (dispatch) =>{ return{ counterActions:bindActionCreators(counterActions,dispatch) } } // 先后顺序不能颠倒 export default connect(mapStateToProps,mapDispatchToProps)(App)

user.jsx

import React from "react"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import * as userActions from "../actions/user"

class User extends React.Component{

    render(){

        const { error, isFetching, user } = this.props.user;

        let data;

        if (error) {
            data = error;
        } else if (isFetching) {
            data = "Loading...";
        } else {
            data = user.title;
        }

        return(
            

{ data }

User

) } } const mapStateToProps = (state) =>{ return{ user:state.user } } const mapDispatchToProps = (dispatch) =>{ return { userActions:bindActionCreators(userActions,dispatch) } } export default connect(mapStateToProps,mapDispatchToProps)(User)

48.Redux Redux中间件与第三方中间件logger

(Redux Redux中间件与第三方中间件logger&)

Redux Redux中间件与第三方中间件logger&

logger中间件

React从入门到实战- 企业级实战项目-宜居二_第53张图片

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"

// 异步和同步
// 定时器  网络请求


// 中间件
// const logger = store  => next => action =>{
//     console.log("dispatch->",action);
//     let result = next(action); // 加载下一个中间件
//     console.log("next state->",store.getState());
//     return result;
// }

// const error = store => next => action => {
//     try{
//         next(action)
//     }catch(e){
//         console.log("error->",e);
//     }
// }

// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))

// const render = () => {
//     ReactDOM.render(
//          store.dispatch({ type: "INCREMENT" })}
//             onDecrement={() => store.dispatch({ type: "DECREMENT" })}
//             value={store.getState()}
//         />,
//         document.getElementById('root'));

// }
// render();
// store.subscribe(render)




ReactDOM.render(
    
        
    
    ,
    document.getElementById('root'));

React从入门到实战- 企业级实战项目-宜居二_第54张图片

49.Redux Redux异步中间件redux-thunk

(Redux Redux异步中间件redux-thunk&)

Redux Redux异步中间件redux-thunk&

处理数据前经历中间件的处理,再去处理数据,增加一层防护

React从入门到实战- 企业级实战项目-宜居二_第55张图片

单一化写法

React从入门到实战- 企业级实战项目-宜居二_第56张图片

用户操作记录,next加载中间件,中间件要放在创建仓库store的上面,所有用户操作都会加载中间件

React从入门到实战- 企业级实战项目-宜居二_第57张图片

可以有多个中间件

React从入门到实战- 企业级实战项目-宜居二_第58张图片

Throw 抛出错误

React从入门到实战- 企业级实战项目-宜居二_第59张图片

常用的中间件系统都已经提供了

React从入门到实战- 企业级实战项目-宜居二_第60张图片

src\actions\counter.js

redux-thunk异步

import * as actions from "../constants"
// export function increment(num){
//     return{
//         type:actions.INCREMENT,
//         num
//     }
// }

export function increment(num){
    return dispatch => {
        setTimeout(() =>{
            dispatch({
                type:actions.INCREMENT,
                num
            })
        },1000)
    }
}


export function decrement(num){
    return{
        type:actions.DECREMENT,
        num
    }
}

src\reducers\users.js

reducer 等待loading状态

import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"

const initialState = {
    user:{},
    isFetching: false,
    error: null,
}

const user = ( state = initialState,action ) => {
    switch(action.type){
        case FETCH_USER_SUCCESS:
            return {
                isFetching: false,
                error: null,
                user: action.user
            };
        case FETCH_USER_REQUEST:
            return {
                isFetching: true,
                error: null,
                user: {}
            }
        case FETCH_USER_FAILURE:
            return {
                isFetching: false,
                error: action.error,
                user: {}
            };
        default:
            return state;
    }
}

export default user

src\actions\users.js

thunk网络异步请求,dispatch触发传递数据

import { FETCH_USER_SUCCESS,FETCH_USER_FAILURE,FETCH_USER_REQUEST } from "../constants"

export const fetch_user_failure = (error) => {
    return {
        type: FETCH_USER_FAILURE,
        error
    };
};

export const fetch_user = (user) => {
    return {
        type: FETCH_USER_SUCCESS,
        user
    }
};

export const fetch_user_request = () => {
    return {
        type: FETCH_USER_REQUEST
    }
};


export const get_user = () =>{
    return dispatch =>{
        dispatch(fetch_user_request())
        fetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
        .then(res => res.json())
        .then(data =>{
            dispatch(fetch_user(data.chengpinDetails[0]))
        })
        .catch(error =>{
            dispatch(fetch_user_failure(error));
        })
    }
}

user.jsx

div的className调整

import React from "react"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"
import * as userActions from "../actions/user"

class User extends React.Component{

    render(){

        const { error, isFetching, user } = this.props.user;

        let data;

        if (error) {
            data = error;
        } else if (isFetching) {
            data = "Loading...";
        } else {
            data = user.title;
        }

        return(
            

{ data }

User

) } } const mapStateToProps = (state) =>{ return{ user:state.user } } const mapDispatchToProps = (dispatch) =>{ return { userActions:bindActionCreators(userActions,dispatch) } } export default connect(mapStateToProps,mapDispatchToProps)(User)

React从入门到实战- 企业级实战项目-宜居二_第61张图片

50.Redux Redux-thunk网络请求

(Redux Redux-thunk网络请求&)

Redux Redux-thunk网络请求&

Thunk主要用于处理异步,异步操作有定时器和网络请求

希望延时1s增加值,无论是触发action,都是同一个action,把异步写在aciton中。

Dispatch触发事件。

React从入门到实战- 企业级实战项目-宜居二_第62张图片

需要处理异步

引入异步中间件

React从入门到实战- 企业级实战项目-宜居二_第63张图片

网络异步请求

React从入门到实战- 企业级实战项目-宜居二_第64张图片

修改reducers,修改state的初始,提取出来。State的操作不能直接改变state,success的时候return {}对象从action中读取user对象。

React从入门到实战- 企业级实战项目-宜居二_第65张图片

State是只读的,要改变需要返回一个新的state

React从入门到实战- 企业级实战项目-宜居二_第66张图片

修改action,单独进行异步操作return dispatch在回调中进行异步操作。

把数据给fetch_user里面,通过dispatch触发。Get_USER前台可以直接调用

React从入门到实战- 企业级实战项目-宜居二_第67张图片

React从入门到实战- 企业级实战项目-宜居二_第68张图片

通过connect关联redux,最后没有分号,可以读取数据

React从入门到实战- 企业级实战项目-宜居二_第69张图片

数据来源于user中的title,通过点击按钮读取数据,通过动作方法来读取数据。

点击user数据发生变化。

React从入门到实战- 企业级实战项目-宜居二_第70张图片

React从入门到实战- 企业级实战项目-宜居二_第71张图片

51.Redux Redux-thunk请求三种状态

(Redux Redux-thunk请求三种状态&)

Redux Redux-thunk请求三种状态&

网络请求延时,加载等待的过程,调整慢,isFetching等待状态

React从入门到实战- 企业级实战项目-宜居二_第72张图片

React从入门到实战- 企业级实战项目-宜居二_第73张图片

Actions也对应有三种等待状态

React从入门到实战- 企业级实战项目-宜居二_第74张图片

视图中响应,三种状态都赋值给data,只用加载data即可

React从入门到实战- 企业级实战项目-宜居二_第75张图片

视图中loading的状态,检查debugger返回是否为true

React从入门到实战- 企业级实战项目-宜居二_第76张图片

调用等待

React从入门到实战- 企业级实战项目-宜居二_第77张图片

异步都需要dispatch触发,否则无法传递数据

React从入门到实战- 企业级实战项目-宜居二_第78张图片

user.js

import { FETCH_USER_SUCCESS,FETCH_USER_REQUEST, FETCH_USER_FAILURE } from "../constants"

const initialState = {
    user:{},
    isFetching: false,
    error: null,
}

const user = ( state = initialState,action ) => {
    switch(action.type){
        case FETCH_USER_SUCCESS:
            return {
                isFetching: false,
                error: null,
                user: action.user
            };
        case FETCH_USER_REQUEST:
            return {
                isFetching: true,
                error: null,
                user: {}
            }
        case FETCH_USER_FAILURE:
            return {
                isFetching: false,
                error: action.error,
                user: {}
            };
        default:
            return state;
    }
}

export default user

src\actions\user.js

import { FETCH_USER_SUCCESS,FETCH_USER_FAILURE,FETCH_USER_REQUEST } from "../constants"

export const fetch_user_failure = (error) => {
    return {
        type: FETCH_USER_FAILURE,
        error
    };
};

export const fetch_user = (user) => {
    return {
        type: FETCH_USER_SUCCESS,
        user
    }
};

export const fetch_user_request = () => {
    return {
        type: FETCH_USER_REQUEST
    }
};


export const get_user = () =>{
    return dispatch =>{
        dispatch(fetch_user_request())
        fetch("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php")
        .then(res => res.json())
        .then(data =>{
            dispatch(fetch_user(data.chengpinDetails[0]))
        })
        .catch(error =>{
            dispatch(fetch_user_failure(error));
        })
    }
}
// counter
export const INCREMENT = "INCREMENT"
export const DECREMENT = "DECREMENT"

// user
export const FETCH_USER_SUCCESS = "FETCH_USER_SUCCESS"
export const FETCH_USER_REQUEST = "FETCH_USER_REQUEST";
export const FETCH_USER_FAILURE = "FETCH_USER_FAILURE";

52.Redux Redux调试工具

(Redux Redux调试工具&)

Redux Redux调试工具&

检测redux数据的变化,在Chrome中应用安装即可

通过依赖来启动插件

引用到主入口文件,包裹整个插件

React从入门到实战- 企业级实战项目-宜居二_第79张图片

React从入门到实战- 企业级实战项目-宜居二_第80张图片

React从入门到实战- 企业级实战项目-宜居二_第81张图片

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore,applyMiddleware } from "redux"
import { composeWithDevTools } from 'redux-devtools-extension';
import logger from "redux-logger"
import thunk from "redux-thunk"
// import reducer from "./reducers/counter"
import { Provider } from "react-redux"
import rootReducer from "./reducers"

// 异步和同步
// 定时器  网络请求


// 中间件
// const logger = store  => next => action =>{
//     console.log("dispatch->",action);
//     let result = next(action); // 加载下一个中间件
//     console.log("next state->",store.getState());
//     return result;
// }

// const error = store => next => action => {
//     try{
//         next(action)
//     }catch(e){
//         console.log("error->",e);
//     }
// }

// 创建store仓库
// const store = createStore(rootReducer,{},applyMiddleware(logger,error));
const store = createStore(rootReducer,{},composeWithDevTools(applyMiddleware(logger,thunk)));
// store.subscribe(() => console.log("state:", store.getState()))

// const render = () => {
//     ReactDOM.render(
//          store.dispatch({ type: "INCREMENT" })}
//             onDecrement={() => store.dispatch({ type: "DECREMENT" })}
//             value={store.getState()}
//         />,
//         document.getElementById('root'));

// }
// render();
// store.subscribe(render)




ReactDOM.render(
    
        
    
    ,
    document.getElementById('root'));

(React 进阶&)

React 进阶&

1.React 进阶 组件优化1

(组件优化1&)

组件优化1&

parent.jsx

外部需要拿到count的值通过回调函数

回调函数获取定时器中的值,定时器网络请求组件销毁处理

state变化render重新渲染pureComponent

import React from "react"
import Child from "./child"
import Child1 from "./child1"


/**
 * 计数例子
 *  
 *  定时器
 *  网络请求
 *  事件监听
 *    在组件被销毁前都应得到相应的处理
 * 
 */

const MyAPI = {
    count:0,
    subscribe(cb){
        this.intervalId = setInterval(() =>{
            this.count += 1
            cb(this.count);
        },1000)
    },
    unSubscribe(){
        clearInterval(this.intervalId);
        this.reset();
    },
    reset(){
        this.count = 0;
    }
}

export default class Parent extends React.Component {

    state = {
        count:0
    }

    componentDidMount(){
        MyAPI.subscribe((currentCount) =>{
            this.setState({
                count:currentCount
            })
        })
    }

    componentWillUnmount(){
        MyAPI.unSubscribe();
    }

    render() {
        console.log("parent -> render");
        return (
            
Parent:{ this.state.count }
) } }

child1.jsx 不通过生命周期方式进行处理

import React from 'react';


/**
 * Component:不会对数据进行比较
 * PureComponent:对数据进行浅比较 props
 * 
 */
export default class Child1 extends React.PureComponent {

    render() {
        console.log("child1 -> render");
        return (
            
Child1:{ this.props.num }
); } }

child.jsx state发生改变render重新渲染,整个Child重新渲染,通过生命周期Child不用渲染

shouldComponentUpdate

import React from 'react';

export default class Child extends React.Component {

    /**
     * 
     * @param {*} nextProps 
     * @param {*} nextState 
     * 
     * 关于渲染问题
     */
    shouldComponentUpdate(nextProps,nextState){
        if(nextProps.num === this.props.num){
            return false;
        }
        return true;
    }

    render() {
        console.log("child -> render");
        return (
            
Child:{ this.props.num }
); } }

App.js

HashRouter

import React from 'react';
import Demo1 from "./components/Demo1/parent"
import Home from "./components/Home"
import { HashRouter, Route, Switch } from "react-router-dom"

function App() {
    return (
        
            
                
                
            
        
    );
}

export default App;

Home.jsx

import React from 'react';
import Demo2 from "./Demo2"
import Demo3 from "./Demo3"
import Demo4 from "./Demo4"

import Banner from "./Demo5/banner"
import Chengpin from "./Demo5/chengpin"

import NewBanner from "./Demo5/New/NewBanner"
import NewChengpin from "./Demo5/New/NewChengpin"

import Demo6 from "./Demo6/Parent"

function Home() {
    return (
        
); } export default Home;

2.React 进阶 组件优化2

(组件优化2&)

组件优化2&

index.jsx,列表数据动态生成

Fragment返回li

import React,{ Fragment } from "react"

class Item extends React.Component {
    render() {
        return (
            
                
  • Demo2 Item1
  • Demo2 Item1
  • ) } } export default class Demo2 extends React.Component { render() { return (
    ) } }

    React从入门到实战- 企业级实战项目-宜居二_第82张图片

    3.React 进阶 组件优化3

    (组件优化3&)

    组件优化3&

    index.jsx color只有在comment中使用,context上下文对象,getChildContext系统提供方法,context对象直接传递history不用两次传递

    context孙子组件通信传递history

    import React from "react"
    import PropTypes from "prop-types"
    
    const Topic = (props) =>{
        return(
            
    ) } /** * * 路由:this.props.history.push("/"):必须是路由直接子元素,如果是孙子元素,则不能使用 * * withRouter * */ const Comment = (props,context) =>{ return(
    { context.color }
    ) } export default class Demo3 extends React.Component{ getChildContext(){ return{ color:"red" } } render(){ return(
    ) } } Comment.contextTypes = { color:PropTypes.string } Demo3.childContextTypes = { color:PropTypes.string }

    4.React 进阶 Fragment

    (React 进阶 Fragment&)

    React 进阶 Fragment&

    5.React 进阶 Context

    (React 进阶 Context&)

    React 进阶 Context&

    6.React 进阶 高阶组件

    (React 进阶 高阶组件&)

    React 进阶 高阶组件&

    index.jsx 可以在高阶组件中对MyData进行处理

    高阶组件定义,

    import React from "react"
    
    /**
     * 
     * 高阶组件
     *  1.函数
     *  2.参数一个组件
     *  3.返回值也是一个组件
     */
    
    const withFetch = (ComposeComponent) =>{
        return class extends React.Component{
            render(){
                return(
                    
                )
            }
        }
    }
    
    class MyData extends React.Component{
        render(){
            return(
                
    MyData:{this.props.data}
    ) } } const WithFetch = withFetch(MyData); export default class Demo4 extends React.Component{ render(){ return(
    ) } }

    7.React 进阶 高阶组件应用

    (React 进阶 高阶组件应用&)

    React 进阶 高阶组件应用&

    banner组件与chengpin组件出了url不同其他都一样

    相似组件通过高阶组件优化处理

    banner.jsx

    import React, { Component } from 'react';
    
    class Banner extends Component {
      constructor() {
        super();
        this.state = {
          loading: true,
          banner: null
        };
      }
    
      componentDidMount() {
        fetch('http://iwenwiki.com/api/blueberrypai/getIndexBanner.php')
          .then(res => res.json())
          .then(banner => {
            this.setState({
              loading: false,
              banner: banner
            });
          })
      }
    
      render() {
        if(this.state.loading) {
          return (
            
    loading
    ) } else { return (

    {this.state.banner.banner[0].title}

    ) } } } export default Banner;

    chengpin.jsx

    import React, { Component } from 'react';
    
    class Chengpin extends Component {
      constructor() {
        super();
        this.state = {
          loading: true,
          chengpin: null
        };
      }
    
      componentDidMount() {
        fetch('http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php')
          .then(res => res.json())
          .then(chengpin => {
            this.setState({
              loading: false,
              chengpin: chengpin
            });
          })
      }
    
      render() {
        if(this.state.loading) {
          return (
            
    loading
    ) } else { return (

    {this.state.chengpin.chengpinInfo[0].title}

    ) } } } export default Chengpin;

    withFetch.jsx return两个函数

    import React,{Component} from 'react'
    
    const withFetch = (url) => (View) => {
        return class extends Component {
            constructor() {
                super();
                this.state = {
                    loading: true,
                    data: null
                }
            }
    
            componentDidMount() {
                fetch(url)
                    .then(res => res.json())
                    .then(data => {
                        this.setState({
                            loading: false,
                            data: data
                        });
                    })
            }
    
            render(){
                if(this.state.loading){
                    return(
                        
    loadding....
    ) }else{ return } } } } export default withFetch

    NewBanner.jsx,有两个参数第二个参数是组建视图,相同得到放到高阶组件处理

    import React from "react"
    import withFetch from "../withFetch"
    
    const Banner = withFetch("http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")(props =>{
        return(
            

    { props.data.banner[0].title }

    ) }) export default Banner;

    NewChengpin.jsx

    import React from "react"
    import withFetch from "../withFetch"
    
    const Chengpin = withFetch("http://iwenwiki.com/api/blueberrypai/getChengpinInfo.php")(props =>{
        return(
            

    { props.data.chengpinInfo[0].title }

    ) }) export default Chengpin;

    React从入门到实战- 企业级实战项目-宜居二_第83张图片

    8.React 进阶 错误边界处理

    (React 进阶 错误边界处理&)

    React 进阶 错误边界处理&

    Parent.jsx

    import React from 'react'
    import Errors from "./Errors"
    import ErrorBoundary from "./ErrorBoundary"
    
    export default class Parent extends React.Component{
    
        state = {
            count:0
        }
    
        increment = () =>{
            this.setState({
                count:this.state.count+1
            })
        }
    
    
        decrement = () =>{
            this.setState({
                count:this.state.count-1
            })
        }
    
    
        render(){
            return(
                

    这是一个标题

    { this.state.count }

    { '加载时发生错误' }

    }>
    ) } }

    Errors.jsx

    错误边界componentDidCatch

    import React from 'react'
    
    export default class Errors extends React.Component{
    
        render(){
            return(
                
      { null.map((element,index) =>{ return
    • { element }
    • }) }
    ) } }

    ErrorBoundary.jsx

    import React from "react"
    
    export default class ErrorBoundary extends React.Component{
        state = {
            hasError:false,
            error:null,
            errorInfo:null
        }
    
        /**
         * 子元素发生错误时触发
         */
    
        componentDidCatch(error,errorInfo){
            this.setState({
                hasError:true,
                error:error,
                errorInfo:errorInfo
            })
        }
    
        render(){
            if(this.state.hasError){
                return 
    { this.props.render(this.state.error,this.state.errorInfo) }
    } return this.props.children; } }

    (React&Redux实战-登录注册认证&)

    React&Redux实战-登录注册认证&

    (React 企业级实战项目-宜居&)

    React 企业级实战项目-宜居&

     

     

     

    你可能感兴趣的:(项目案例,react)