前端(八):react根底分分快三计划

作者:分分快三计划

  5.动态数据人机联作--state

  state用于承受管理动态数据。数据须求在构造函数中经过this.state事先表明,并在事件中通过this.setSate完毕多少更新。

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            nameList:["Sun", "Li", "Zhao", "Qian"]
        }
    }
    addPerson(){
        this.setState({
            nameList: [...this.state.nameList, "zhou"]
        })
    }
    render (){
        return (
            <div>
                <button onClick={()=>this.addPerson()}>加入周先生</button>
                <ul>
                    {this.state.nameList.map((name, index) => <li key={index 1}>{name}</li>)}
                </ul>
            </div>

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

概况:

经过本篇作品你能够对react的关键有个总体的认知。
关于react是何等,优点,清除什么难题等,互连网一大推就不啰嗦了。
驾驭虚构DOM的贯彻,参谋那边随笔
虚拟DOM
不想看的话回顾讲,其实就是用四个轻量级的dom结构(用js模拟达成),来模拟重量级的dom结构,通过比对轻量级结构后,在操作重量级dom结构巩固品质,进而达到品质优化的指标。

  1.ReactDOM.render

  index.js中的ReactDOM.render函数用于将标签只怕零部件渲染到public下的页面中。第贰个参数能够是专擅的单个标签、div包裹的四个标签,以至自定义的零件Component。

用多少个事例串起来:

规划一个负有加减效能的类型:

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>
        {caption} count: {value}
      </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下

分分快三计划 1

clipboard.png

分分快三计划 2

clipboard.png

ControlPanel 根本就一贯不行使store,纵然单独为了传递prop给组件counter就要求帮助state prop,明显不成立,在那之中react提供了Context的机能能够缓慢解决那个难点;

  2.安装react全家桶

# 安装create-react-app
cnpm install create-react-app -g
# 利用create-react-app 来创建一个项目
create-react-app 项目名称     # 假设这里的项目名称是my-app
# 进入项目文件夹
cd my-app
# 生成配置文件
# cnpm run eject       # 生成scripts文件夹和config文件夹,cnpm
# 启动服务
cnpm start           # 它相当于执行 scrpits/starts.js,这个已经在package.json中配置好了命
花色布局

actions--->客户作为
components--->组件
containers--->容器
reducer--->叁个纯函数重临新的state状态
store--> store里面担负分发action行为
index.html ---> 模板文件
webpack---> 打包配置文件

  9、综合:使用component伏乞后台数据并交给组件

  在my-app下树立server/server.js文件,运转贰个后端服务:

const express = require('express');

const app = express();
app.get("/data", function (req, res) {
    res.json({"name": "old monkey", "age": 5000})
});
app.listen(3002, function () {
    console.log("Node app start at port 3002.")
});

  Terminal运维该服务: node server/server.js。这时能够访谈 

  安装axios: cnpm install axios --save。并在package.json的布置文件中增加"proxy"配置,让它转换端口到3002:

// package.json
{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "axios": "^0.18.0",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-scripts": "1.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "proxy": "http://localhost:3002"
}

  在src/index.js中写组件:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';

class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {name: "monkey", age: 100}

    }
  // 在component内部使用ajax请求数据,并通过setState传递给App。
    componentDidMount(){
        axios.get("/data").then(res=>{
            if(res.status === 200){
                console.log(res);
                this.setState({name: res.data.name, age: res.data.age});
            }
        }, err=>{
            console.log(err);
        })
    }
    addAge(){
        this.setState({age: this.state.age   1})
    };
    decAge(){
        this.setState({age: this.state.age - 1})
    }
    render (){
        const style={
            display: "inline-block",
            width: "150px",
            height: "40px",
            backgroundColor: "rgb(173, 173, 173)",
            color: "white",
            marginRight: "20px"
        };
        return (
            <div>
                <h2>this {this.state.name } is { this.state.age } years old.</h2>
                <button style={style} onClick={()=>this.addAge()}>增加一岁</button>
                <button style={style} onClick={()=>this.decAge()}>减少一岁</button>
            </div>
        )
    }
}
ReactDOM.render(<App />, document.getElementById('root'));

编写组件:

零零件间的传递通过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}}/>
    }
}

也足以如此创建

import React from 'react';
const Level1 = React.createClass({  
  render() {
    return (
      <div></div>
    );
  }
});
export default Level1 ;  

  4.静态数目传递--props

  组件间数据通过this.props属性来拓宽数据传递。父组件在标签化时经过品质的形式传递数据,子组件通过this.props来获得具有的数额。

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component{
    render (){
        return <h2>App: { this.props.name }, { this.props.age }</h2>
    }
}
class App2 extends React.Component{
    render (){
        const name = "Sun", age=5000;

        return (
            <div>
                <h2>App2: { this.props.name }, { this.props.age }</h2>
                <App name={name} age={age} />
            </div>
        )
    }
}
ReactDOM.render(<App2 name="Li" age="20" />, document.getElementById('root'));

  注意:1.props只可以传递静态数据,不可能与客户交互;2.{}不是Object对象,如若想写<App2 obj={name: "Li", age: 20} />,就亟须超前注脚。3.style样式作为数据传递是无用且乖谬的。

const obj = {name: "Li",age: 20};
<App2 obj={obj}/>   
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组件,

分分快三计划 3

1.jpg

分分快三计划 4

2.jpg

分分快三计划 5

3.jpg

分分快三计划 6

4.jpg

  1.react为主用法

  redux是单独的用来状态管理的第三方包,它成立意况机来对单项数据开展田间管理。

分分快三计划 7

  上海教室是个体粗浅的知晓。用代码验证一下:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";

function reducer(state={name: "monkey", age: 5000}, action){
    switch (action.type){
        case "add":
            state.age   ;
            return state;
        case "dec":
            if (state.age <= 4995){
                state.name = "small monkey";
            }
            state.age --;
            return state;
        default:
            return state;
    }
}
const store = createStore(reducer);
const add = {type: "add"}, dec={type: "dec"};


class App extends React.Component{
    render (){
        const style={
            display: "inline-block",
            width: "150px",
            height: "40px",
            backgroundColor: "rgb(173, 173, 173)",
            color: "white",
            marginRight: "20px"
        };
        const store = this.props.store;
        // console.log(store.getState());
        const obj = store.getState();
        // console.log(obj);
        return (
            <div>
                <h2>this { obj.name } is { obj.age } years old.</h2>
                <button style={style} onClick={()=>store.dispatch(this.props.add)}>增加一岁</button>
                <button style={style} onClick={()=>store.dispatch(this.props.dec)}>减少一岁</button>
            </div>
        )
    }
}
function render() {
    ReactDOM.render(<App store={store} add={ add } dec={ dec } />, document.getElementById('root'));
}
render();
store.subscribe(render);

  因为action必需是个对象,所以只可以写成add = {type: "add"}的样式,而不能够直接写参数"add"。相符地,在reducer中写switch时将action.type作为参数。

  action和state生龙活虎风华正茂对应,要动用action应当要在reducer里注明。

  redux未有用state来完成动态数据更新,而是经过props来传递数据,因而在组件内部只可以通过props获取store,以至store.getState()获取state。

  redux将ReactDOM.render进行了一遍封装来设置监听。

  redux对数据和组件实行明白耦,因此能够进行文件拆分。

  把action写成函数的款式:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";

const Add = "add", Dec="dec";
function reducer(state={name: "monkey", age: 5000}, action){
    switch (action.type){
        case Add:
            state.age   ;
            if (state.age > 5005){
                state.name = "old monkey";
            }
            return state;
        case Dec:
            if (state.age <= 4995){
                state.name = "small monkey";
            }
            state.age --;
            return state;
        default:
            return state;
    }
}
const store = createStore(reducer);
class App extends React.Component{
    render (){
        const style={
            display: "inline-block",
            width: "150px",
            height: "40px",
            backgroundColor: "rgb(173, 173, 173)",
            color: "white",
            marginRight: "20px"
        };
        const store = this.props.store;
        const state = store.getState();
        return (
            <div>
                <h2>this { state.name } is { state.age } years old.</h2>
                <button style={style} onClick={()=>store.dispatch(add())}>增加一岁</button>
                <button style={style} onClick={()=>store.dispatch(dec())}>减少一岁</button>
            </div>
        )
    }
}
function render() {
    ReactDOM.render(<App store={store} add={ add } dec={ dec } />, document.getElementById('root'));
}
render();
store.subscribe(render);

生命周期:

高速学习react 先领悟它的重大----生命周期,
三个零件在不一样一时间代会调用分化的时间代的函数接口也正是呼应的生命周期函数

  8、组件的生命周期

  组件的宣示周期可分为多个状态:Mounting,已插入真实 DOM;Updating,正在被另行渲染;Unmounting:已移出真实 DOM。如下图所示(本图依据罗丝n先生示例改写)。

  分分快三计划 8

  各种函数的释义(摘自新手教程):

  componentWillMount 在渲染前调用,在顾客端也在服务端。

  componentDidMount : 在首先次渲染后调用,只在顾客端。之后组件已经转移了相应的DOM结构,能够由此this.getDOMNode()来拓宽探访。 借令你想和其余JavaScript框架一同使用,能够在此个法子中调用setTimeout, setInterval恐怕发送AJAX央求等操作(防止异部操作拥塞UI)。

  componentWillReceiveProps 在组件选择到三个新的 prop (更新后)时被调用。这么些方法在最初化render时不会被调用。

  shouldComponentUpdate 重返三个布尔值。在组件接收到新的props或许state时被调用。在初步化时依旧选拔forceUpdate时不被调用。
能够在您认可没有供给立异组件时行使。

shouldComponentUpdate(nextProps, nextState) {
    console.log(nextProps, nextState);
    console.log(this.props, this.state);
    if(this.state.update === true){
        // 只有在给定条件发生的时候返回true,也就是可以重新渲染
        return true
    }
   // 只有在给定条件发生的时候返回true,也就是可以重新渲染
   if(nextState.update === true){
        // 在下一个状态达到条件时重新渲染
        return true
    }
    return false // 其它条件返回false,不重新渲染
}

  componentWillUpdate在组件接受到新的props可能state但还并未有render时被调用。在初阶化时不会被调用。

  componentDidUpdate 在组件完结换代后立刻调用。在初叶化时不会被调用。

  componentWillUnmount在组件从 DOM 中移除的时候立刻被调用。

React.createClass和extends Component的区别:

Component{}是ES6的写法,会自行再而三Component里面包车型大巴属性
createClass({})是React的ES5写法,会转换一个React Component
语法分歧
• propType 和 getDefaultProps
• 状态的区分
• this区别
• Mixins
参照那篇小说
React.createClass和extends Component的区别
万后生可畏你的零器件是无状态的,纯输出组件也能够直接写成函数如下

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

react 组件必需一流超级传递

分分快三计划 9

clipboard.png

若是想要越级传递,1一直到5,那么供给用到redux

  6.风波绑定

  在react中,事件以属性的主意直接在标签中选择,其调用函数要用黄金时代层函数包裹。调用函数能够直接写在对象内部,何况要用bind进行监听和翻新。

  在地点的身体力行中,大家经过那后生可畏行代码代替了bind的进度:

<button onClick={()=>this.addPerson()}>加入周先生</button>

  鉴于js中从不局地成效域唯有函数成效域,所以只要直白写onClick={this.addPerson}时,this指的正是windo对象。用风度翩翩层函数包裹时,this对象指的正是其大器晚成函数。

  其余的做法有三种:

  首先,在事变绑按期期接选用this.function:

<button onClick={this.addPerson}>加入周先生</button>

  其次能够用箭头函数来声称addPerson函数,本质上和方面使用的艺术相通:

addPerson = ()=>{
    this.setState({
        nameList: [...this.state.nameList, "zhou"]
    })
};

  或然可以不改addPersonn函数,而是在构造器中增多上那样一句话:

this.addPerson = this.addPerson.bind(this)
redux

redux此前最佳刺探下flux,可是redux越来越精良。
react和redux事实上是多个独立的事物,假使您两个单独行使推荐react-redux库,大家从redux 使用方式开端,奉公守法过渡到react-redux,那一个库可以让我们简化代码的书写

  从前只行使django和jquery做小品种支出,所以决定搞风华正茂搞react框架。React 特点:注解式设计、设想DOM、JSX、组件、数据驱动。

履新时代的函数

意气风发旦组件的数码有生成了(porp,state卡塔 尔(阿拉伯语:قطر‎, 依次推行以下函数
• componentWillReceiveProps
• shouldComponentUpdate
• componentWillUpdate
• render
• componentDidUpdate

四、react-router-dom

  react-router-dom是特别用来拍卖路由的组件。

  BrowserRouter用以包裹app,它会在this.props增添一些情形参数,这充足用。

  Route用于将路由和组件绑定,三个路由对应叁个页面(组件),可能Link。其主要性的两本性情为path和component,path能够接过指标,也能够选用一个url字符串。

  Link用于将链接和Route举行绑定。

  Switch用于当前路由下的富有子路由,经常和Redirect同盟使用,用于重定向这一个未定义的子路由。

  Redirect:重定向。其重视的个性为to,只好指向叁个url字符串。

  用例一: Route Componnet Redirect

  1.创建七个路由指向五个零器件:Login和Home, 甚至三个客商登入境况的reducer。

  2.进入时首先重定向到Home页面.Home组件剖断顾客登入状态,登入则打字与印刷登陆消息并提供注销开关,点击开关会重定向到Login页面;未登入则一贯重定向到Login页面。

  3.客户登陆则重定向到Home页面,未登陆则打字与印刷登陆提醒并提供登入开关,点击开关会重定向到Home页面。

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from "redux";
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import {BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';

import { reducer } from "./reducer";
import { Login } from "./Login";
import { Home } from "./Home";

const store = createStore(reducer, applyMiddleware(thunk));
ReactDOM.render(
    (<Provider store={store}>
        <BrowserRouter>
           <Switch>
               <Route path="/login" component={ Login } />
               <Route path="/monkey" component={ Home } />
               <Redirect to={{ pathname: "/monkey" }}/>
           </Switch>
        </BrowserRouter>

    </Provider>),
    document.getElementById('root')
);

// src/Home.js
import React from "react";
import {connect} from 'react-redux';
import { Redirect } from 'react-router-dom';
import {logout} from "./reducer";

@connect(state=>state, {logout})
class Home extends React.Component{
    render(){
        const app = (
            <div>
                <h2>这是home界面</h2>
                <button onClick={this.props.logout}>点击注销</button>
            </div>
        );
        return this.props.isLogin ? app : <Redirect to={{ pathname: "/login"}} />
    }
}
export { Home }

// src/Login.js
import React from 'react';
import {connect} from 'react-redux';
import {Redirect} from 'react-router-dom';
import {login} from "./reducer";

@connect(state=>state, {login})
class Login extends React.Component{
    render(){
        console.log(this.props);
        const app = (
            <div>
                <h2>请先登录!</h2>
                <button onClick={this.props.login}>点击登录</button>
            </div>
        );
        return this.props.isLogin ? <Redirect to={{pathname: "/home"}} /> : app
    }
}
export { Login }

// src/reducer.js
// 用户登录状态
const LOGIN = "login";
const LOGOUT = "logout";

export function reducer(state={isLogin: false, user: "Li"}, action) {
    switch (action.type){
        case LOGIN:
            return {...state, isLogin:true};
        case LOGOUT:
            return {...state, isLogin:false};
        default:
            return state
    }
}

export function login() {
    return {type: LOGIN}
}
export function logout() {
    return {type: LOGOUT}
}

  用例二:Route Component Link

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Route, Switch, Redirect, Link } from 'react-router-dom';


function LinkOne(){
    return <h2>我是LineOne组件,被Route绑定给了一个Link链接</h2>
}
function LinkTwo() {
    return <h2>我是LineThree组件,被Route绑定给了一个Link链接</h2>
}
function LinkThree(){
    return <h2>我是LineThree组件,被Route绑定给了一个Link链接</h2>
}
function Test(){
    return <h2>这是无效的路由,你不要搞事情!</h2>
}

ReactDOM.render(
    (<BrowserRouter>
        <div>
            <ul>
                <li><Link to="/">LinkOne</Link></li>
                <li><Link to="/two">LinkTwo</Link></li>
                <li><Link to="/three">LinkThree</Link></li>
            </ul>
            <Switch>
                <Route path="/" exact component={ LinkOne } />
                <Route path="/two" component={ LinkTwo } />
                <Route path="/three" component={ LinkThree } />
                <Route path='/:location' component={ Test } />
            </Switch>
        </div>
    </BrowserRouter>),
    document.getElementById('root')
);

 

  

 

装载时代的函数

getDefaultProps(是安装暗中同意props卡塔尔getInitialState(遗弃,设置暗许State)
次第试行以下函数
• constructor
• componentWillMount
• render
• componentDidMount

三、redux、redux-thunk与react-redux

  react本人能够不负众望动态数据的监听和翻新,假若不是须求能够不适用redux。

  安装redux: cnpm install redux --save。

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>
      {caption} count: {value}
    </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

有关react 路由得以参照那边随笔
路由

  3.文件目录结构

my-app
    - config                        # 项目默认配置文件,由npm run eject生成
    - .gitignore                    # git配置
    - node_modules                  # 本地第三方安装包
    - package.json                  # npm项目配置,里面记录了项目的名字、版本、依赖包、和自定义配置 
    - package-lock.json
    -  public                       # 公共资源
       - index.html             # 静态页面
    - README.md            
    -  scripts                      # 配置pacakage.json中的"scripts"定义的命令
        - build.js                  # build命令,可由npm build执行,生成静态文件用于迁移到生产环境
        - start.js                  # start命令
        - test.js                
    -  src
        - App.css                   # 创建项目时自动生成的css样式,没用
        - App.js                    # react组件
        - App.test.js
        - index.css                 # 入口文件的样式
        - index.js                  # 入口文件
        - log.svg
        - registerServiceWorker.js

  项目运转时,会加载public下的index.html文件,并随着实践index.js,从而变成全数页面的渲染。

卸载时代的函数

销毁组件
•componentWillUnmount

import React,{ Component } from 'react';

class Demo extends Component {
  constructor(props) {
    // 构造函数,要创造一个组件类的实例,会调用对应的构造函数,
    //一个react组件需要构造函数,往往为了两个目的.
    //1:初始化state.2.绑定成员函数this环境。  
    // 无状态的函数就不需要构造函数,
      super(props)
      console.log("---初始化组件---")
      this.state = {
        test:'想要显示一段不一样的文字'
         //定义state,存放页面的数据,通过this.setState()方法修改
        //.this.setState()函数所做的事情,首先是改变this.state的值,然后驱动组件经历更新过程,这样才有机会让this.state里新的值出现在界面上。
      }
  }
componentWillMount () {
    console.log("---组件挂载前---最先执行的函数")

}
componentDidMount () {
    console.log("---组件挂载后---")
}
componentWillReceiveProps (nextProps) {
    console.log("---父组件重新渲染---")
值得注意的是,更新时期的componentWillReceiveProps函数,
只要父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的Props有没有改变,都会触发子组件的componentWillReceiveProps函数,但是自身的this.setState方法触发的更新过程不会调用这个函数。
}
shouldComponentUpdate (nextProps,nextState) {
    console.log("---组件接受到重绘状态---")
    它决定了一个组件什么时候不渲染。
    在更新过程中shouldComponemtUpdata 返回 false那就立刻停止更新。
    this.setState函数后会执行shouldComponemtUpdata 然后在决定我要不要更新。
  相反 shouldComponemtUpdata 函数返回 TRUE,接下来就会依次调用
   componentWillUpdata,render,componetDidUpdata函数,它把render像夹心面包似得夹在了中间。
}
componentWillUpdate (nextProps,nextState) {
  console.log("---组件将要更新---")
} 
 componentDidUpdate (prevProps,prevState) {
   console.log("---组件更新完毕---")
}
render () {
    console.log("---组件渲染---")
    return (
        <div>{this.state.test}</div>
    )
}
componentWillUnmount () {
   console.log("---组件销毁---")
}
}
export default Demo;

componentWillMount 和componentDidMount的差别:componentWillMount 能够在服务器调用,也得以在浏览器调用可是componentDidMount只好在浏览器被调用,因为装载是一个零器件放到DOM树上的进程,那么真正的装载是不容许在服务器上完毕的,服务器的渲染并不会发生DOM树。所以大家可以利用那或多或少。在componentDidMount被调用时候,组件已经棉被服装载到DOM树上了,可放心的去操作渲染出来的任何DOM。

  1.安装npm、cnpm

# 安装node.js 从而安装npm,它会在当前用户家目录下生成node_moudules文件夹,来对npm安装的全局第三方包进行管理
brew install node

# npm安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm config set registry https://registry.npm.taobao.org

# 测试
cnpm install express -g
actions:

• 是三个行事的指雁为羹
• 是普通JS对象
• 日常由艺术生成
• 必需有一个type
本人要增添一本书这么些作为足以如下:

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

reducer:
• 是响应的虚幻
• 是纯艺术
• 传入旧的情景和action
• 再次回到新的动静

具名函数:reducer(state, action) state 是现阶段景观,action是经受到的action,
在乎不可能改革参数state和action

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

前端(八):react根底分分快三计划。   2.react异步

  当二个父组件中有多个子组件时,假若每多个组件发闯祸态变化,store都要重新渲染叁回。使用异步能够只重复渲染发生情状变化的组件。

  安装redux和thunk的高级中学级件redux-thunk:cnpm install redux-thunk。引进多个函数,并校正createStore如下,别的代码保持不改变:

import { createStore, applyMiddleware } from "redux";
import thunk from 'redux-thunk';

const store = createStore(reducer, applyMiddleware(thunk));

  当然还是能够运用compose在调控台增添调试功用,前提是这亟需在浏览器中设置redux插件。

import { createStore, applyMiddleware, compose } from "redux";
const store = createStore(
    reducer,
    compose(
        applyMiddleware(thunk),
        window.devToolsExtension?window.devToolsExtension():f=>f
    )
);
在redux框架下,叁个react组件是这么运维的

读取Store的意况,用于初叶化组件的意况,同时监听Store的情事校勘,当Store状态发生转移时候,就要求更新组件的事态,进而使得渲染。当需要立异store状态时,就要派发action对象。
借助当前props,和state,渲染顾客分界面。

  3.组件间与状态机、状态机与状态机

  内层的机件调用dispatch,那么它的父组件一贯到最外层组件都急需使用store属性意气风发层风流洒脱层地传递状态机。

  状态机与状态机之间要求采用redux中的combineReducers合并成叁个对象。并由dispatch调用的action来研究其对应的reducer一级再次来到的state。

  举例:

  在src目录下新建index.redux.js文件,创建多少个reducer以致分级的action。

// src/index.redux.js
const Add = "add", Dec="dec";
export function reducerOne(state={name: "monkey", age: 5000}, action){
    switch (action.type){
        case Add:
            state.age   ;
            if (state.age > 5005){
                state.name = "old monkey";
            }
            return state;
        case Dec:
            if (state.age <= 4995){
                state.name = "small monkey";
            }
            state.age --;
            return state;
        default:
            return state;
    }
}
export function add() {
    return {type: Add}
}
export function dec() {
    return {type: Dec}
}

export function reducerTwo(state="孙悟空", action){
    if(action.type >= 5005){
        state = "斗战胜佛";
    }else if(action.type <= 4995){
        state = "小猕猴";
    }
    return state;
}
export function monkey(number) {
    return {type: number}
}

  在src/index.js中写入如下代码:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk from 'redux-thunk';

import { reducerOne, reducerTwo, add, dec, monkey } from "./index.redux";

const reducer = combineReducers({reducerOne, reducerTwo});
const store = createStore(reducer, applyMiddleware(thunk));

class Nick extends React.Component{
    render(){
        const store = this.props.store;
        const state = store.getState();
        return <h2 >Now this monkey is so-called { state.reducerTwo }</h2>
    }
}
class Monkey extends React.Component{
    render (){
        const style={
            display: "inline-block",
            width: "150px",
            height: "40px",
            backgroundColor: "rgb(173, 173, 173)",
            color: "white",
            marginRight: "20px"
        };
        const store = this.props.store;
        const state = store.getState();
        const name = state.reducerOne.name, age = state.reducerOne.age;
        return (
            <div>
                <h2>this { name } is { age } years old.</h2>
                <button style={style} onClick={()=>{store.dispatch(add()); store.dispatch(monkey(age))}}>增加一岁</button>
                <button style={style} onClick={()=>{store.dispatch(dec()); store.dispatch(monkey(age))}}>减少一岁</button>
                <Nick store={store} />
            </div>
        )
    }
}
function render() {
    ReactDOM.render(<Monkey store={store} add={ add } dec={ dec } />, document.getElementById('root'));
}
render();
store.subscribe(render);

  在Monkey组件中,onClick同不经常候触发五个情形机reducerOne,reducerTwo。尼克组件选拔点击事件触发的景观改善现在的store,并从当中得到相应的字段举行渲染。在此边供给小心:

  1.使用combineReducers将Monkey复合组件涉及到的状态机实行统黄金时代。

  2.三个reducer时,store.getState()获取的是一个目的。能够因此reducer名来获取对应reducer的state。

  3.store和action必需一流一流的往下传递。

  7.规格渲染

  render本身是三个实例方法,扶持js中的各个代码逻辑。能够用if-else来调节重返结果。条件渲染在客户登入和重定向中采取的可比频仍。

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {isLogIn: false}

    }
    login (){
        this.setState({isLogIn: true})
    };
    logout(){
        this.setState({isLogIn: false})
    }
    render (){
        let button=null;
        if (this.state.isLogIn){
            button = <button onClick={()=>this.logout()}>注销</button>
        }else {
            button = <button onClick={()=>this.login()}>登录</button>
        }
        return button
    }
}
ReactDOM.render(<App />, document.getElementById('root'));

  也可以用安慕希表明式简写:

render (){
    return (
        <div>
            {this.state.isLogIn ? <button onClick={()=>this.logout()}>注销</button> : <button onClick={()=>this.login()}>登录</button>}
        </div>
    )
}

  注意:由于{}传递的数量能够是大肆值,所以须要用div包裹。

意气风发、情形搭建

  3.组件内部参数评释和使用

  组件内部可以评释参数,无论是textNode照旧别的Node,都以以 { 参数 } 的花样被组件调用。组件react设想DOM的切实落到实处格局,它来完毕对页面和事情逻辑的划分。

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component{
    render (){
        const string = "hello, react!";
        const style1 = {
            color: "white"
        };
        const style2 = {
            textAlign:"center",
            fontStyle: "border",
            backgroundColor: "green"
        };
        return (
            <div style={style1}>
                {/*这是一段注释*/}
                <h2 style={style2}>{ string }</h2>
            </div>
        )
    }
}

ReactDOM.render(<div>
    <h2>hello, react!</h2>
    <App />
</div>, document.getElementById('root'));

  组件间能够完结嵌套。

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component{
    render (){
        return <h2>这是子组件</h2>
    }
}
class App2 extends React.Component{
    render (){
        const style = {
            backgroundColor: "blue"
        };
        return (
            <div style={style}>
                <h2>这是父组件</h2>
                <App />
            </div>
        )
    }
}

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

  2.React.Component

  React.Component是自定义组件的父类,必得重写render方法来成功组件的扬言和再次来到。所谓组件,正是用js类定义的黄金年代组html标签、样式、数据、事件等的整合,该类能够用<类名 />的办法张开标签化(实例化),实例化时自动调用render方法,并最终交由React.render完结渲染。

  4.使用react-redux

   react-redux简化了redux在组件的逐个传递难题。这里对上边包车型客车代码进行更动:

  - src/index.redux.js文件内容如下:reducer中的state那时必得另行定义,不可能一向再回到原本的state。然后微调了豆蔻梢头晃来得的数量。

// src/index.redux.js
const Add = "add", Dec="dec";
export function reducerOne(state={name: "monkey", age: 5000}, action){
    switch (action.type){
        case Add:
            if (state.age >= 5004){
                state.name = "old monkey";
            }else if(state.age > 4994 && state.age < 5004){
                state.name = "monkey";
            }
            return {...state, age: state.age 1};
        case Dec:
            if (state.age <= 4996){
                state.name = "small monkey";
            }else if(state.age > 4996 && state.age <= 5005){
                state.name = "monkey";
            }
            return {...state, age: state.age-1};
        default:
            return state;
    }
}
export function add() {
    return {type: Add}
}
export function dec() {
    return {type: Dec}
}
export function reducerTwo(state="孙悟空", action){
    if(action.type >= 5004){
        return "斗战胜佛";
    }else if(action.type <= 4996){
        return "小猕猴";
    }
    return state;
}
export function monkey(number) {
    return {type: number}
}

  - src/index.js内容如下:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk from 'redux-thunk';
import { Provider, connect } from 'react-redux';

import { reducerOne, reducerTwo, add, dec, monkey } from "./index.redux";

const reducer = combineReducers({reducerOne, reducerTwo});
const store = createStore(reducer, applyMiddleware(thunk));

class Nick extends React.Component{
    render(){
        return <h2 >Now this monkey is so-called { this.props.nick }</h2>
    }
}
class Monkey extends React.Component{
    render (){
        const style={
            display: "inline-block",
            width: "150px",
            height: "40px",
            backgroundColor: "rgb(173, 173, 173)",
            color: "white",
            marginRight: "20px"
        };
        return (
            <div>
                <h2>this { this.props.reducerOne.name } is { this.props.reducerOne.age } years old.</h2>
                <button style={style} onClick={()=>{this.props.add(); this.props.monkey(this.props.reducerOne.age)}}>增加一岁</button>
                <button style={style} onClick={()=>{this.props.dec();this.props.monkey(this.props.reducerOne.age)}}>减少一岁</button>
                <Nick nick={ this.props.reducerTwo } />
            </div>
        )
    }
}
const mapStateProps = state=>{
    return { reducerOne: state.reducerOne, reducerTwo: state.reducerTwo }
};
const actionCreator = { add, dec, monkey };
Monkey = connect(mapStateProps, actionCreator)(Monkey);  // 其实是加了一层装饰器


function render() {
    ReactDOM.render(
        <Provider store={store}>
            <Monkey/>
        </Provider>
        , document.getElementById('root'));
}
render();

  首先,从react-redux中引进Provider,用来包装app Monkey,然后将store传递给Provider就可以。

  其次,用装饰器对app Monkey举办李装运点,并传递踏入四个参数,第贰个参数是组件所急需的reducer中的状态(这里把五个reducer的情况全部写了进去),第二个参数是action指令。connect函数会依照将reducer和action生机勃勃大器晚成对应起来,所从前面平昔用action函数就能够。

  再次,onClick绑定action只须要写成onClick={this.props.action}就能够,这里须求改变七个情景,所以用箭头函数包裹了弹指间。

  connect的这种写法看起来不爽,能够用装饰器的花样写。不过必要做一下babel配置:

# 1.生成配置文件
cnpm run eject
# 2.安装插件
cnpm install babel-plugin-transform-decorators-legacy --save
# 3.在package.json中的"babel"中做如下配置:
src/package.json

"babel": {
  "presets": [
    "react-app"
  ],
  "plugins":[
    "transform-decorators-legacy"
  ]
},

  这时候将装饰器的那三行代码改为生龙活虎行,写在Monkey类上边就可以。

@connect(state=>({ reducerOne: state.reducerOne, reducerTwo: state.reducerTwo }), { add, dec, monkey })
class Monkey extends React.Component{
  ...
}

二、react一些概念

<!--public/index.html简化如下-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <title>React App</title>
    <style>
        body {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <div id="root"></div>
</body>
</html>

  react不难示例只保留简化后的public/index.html和src/index.js。

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 日记本