React知识点整理

2019-02-24  本文已影响0人  晴窗细语

初入React

JSX语法

React组件

React数据流

state
props
static defaultProps = {
    classPrefix: 'tabs', 
    onChange: () => {},
};

static propTypes = {
  tab: React.PropTypes.oneOfType([
    React.PropTypes.string,
    React.PropTypes.node,
  ]).isRequired,
  order: React.PropTypes.string.isRequired,
  disble: React.PropTypes.bool,
};

React生命周期

分为挂载、渲染、卸载几个阶段

挂载或卸载

主要做组件状态初始化

挂载
挂载流程
卸载
卸载流程
数据更新

指父组件向下传递props或组件自身执行setState方法时发生的一系列更新动作

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

class App extends Component {
    componentWillReceiveProps(nextProps){
        //this.setState({})
    }

    shouldComponentUpdate(nextProps, nextState) {

    }

    componentWillUpdate(nextProps, nextState) {

    }

    componentDidUpdate(prevProps, prevState) {

    }

    render() {

    }
}

组件自身state更新
组件自身state更新

不能在componentWillUpdate里执行setState

父组件更新props而更新
componentWillReceiveProps(nextProps) {

}

React与DOM

refs

refs是React组件中特殊的props,可以附加到任何一个组件上。组件被调用时会新建一个该组件的实例,refs则指向这个实例。

漫谈React

事件系统

在React底层,主要对合成事件做了两件事:事件委派和自动绑定。

在React中使用原生事件

React生命周期方法中,componentDidMount会在组件已经完成安装并且在浏览器中存在真实的DOM后调用,此时可以完成原生事件的绑定。

import React, {Component} from 'react';

class NativeEventDemo extends Component {
    componentDidMound() {
        this.refs.button.addEventListener('click', e => {
            handleClick(e);
        });
    }

    handerClick(e) {
        console.log(e);
    }

    componentWillUnMount() {
        this.refs.button.removeEventListener('click');
    }

    render() {
        return <button ref="button">Test</button>
    }
}

注:在React中使用DOM原生事件时,一定要在组件卸载时手动卸除,否则很可能会出现内存泄漏的问题。

对比React合成事件与JavaScript原生事件

组件间通信

父组件向子组件通信

父组件通过props向子组件传递需要的信息

import React, {Component} from 'react';

function ListItem({value}) {
    return (
        <li>
            <span>{value}</span>
        </li>
    );
}

function List({list, title}) {
    return(
        <div>
            <ListTitle title={title} />
            <ul>
                {this.props.list.map((entry, index) => {
                    <ListItem key={`list-${index}`} value={entry.text}>

                })}
            </ul>
        </div>
    );
}

子组件向父组件通信

this.props.function()

跨级组件通信

组件新能优化

影响网页性能最大的因素是浏览器的重绘重排版(回流与重绘?)。

纯函数

纯函数由三大原则构成:

PureRender

Pure指的是组件满足纯函数的条件,即组件的渲染是被相同的props和state渲染进而得到相同的结果

Immutable
key

解读React源码

Virtual DOM实际上是在浏览器端用JavaScript实现的一套DOM API,它之于React就好似一个虚拟空间,包括一套Virtual DOM模型、生命周期的维护和管理、性能高效的diff算法和将Virtual DOM展示为原生DOM的path方法。

Virtual DOM模型

一个DOM标签所需的基本元素:

Virtual DOM中的节点称为ReactNode,它分为三种类型ReactElement、ReactFragment和ReactText。其中,ReactElement又分为ReactComponentElement和ReactDOMElement。

创建React元素
//createElement只是做了简单的参数修正,返回一个ReactElement实例对象,也就是虚拟元素的实例
ReactElement.createElement = function(type, config, children){

}

DOM标签组件

ReactDOMComponent针对Virtual DOM标签的处理主要分为:

更新属性

删除不需要的旧属性,更新新属性。

更新子节点

生命周期的管理艺术

生命周期在不同状态下的执行顺序:

first render
first render
props change
props change
state change
state change

自定义组件的声明周期主要通过3个阶段进行管理:MOUNTING、RECEIVE_PROPS、UNMOUNTING

MOUNTING

mountComponent负责管理生命周期中的getInitialState、componentWillMount、render和componentDidMount。

RECEIVE_PROPS

updateComponent负责管理生命周期中的componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate、render和componentDidUpdate。

UNMOUNTING

unmountComponent负责管理生命周期中的componentWilUnmount。

解密setState机制

setState调用栈
import React, {component} from 'react';

class Example extends Component {
    constructor() {
        super();
        this.state = {
            val: 0;
        }
    }

    componentDidMount() {
        this.setState({val: this.state.val + 1});
        console.log(this.state.val);

        this.setState({val: this.state.val + 1});
        console.log(this.state.val);

        setTimeout(() => {
            this.setState({val: this.state.val + 1});
            console.log(this.state.val);

            this.setState({val: this.state.val + 1});
            console.log(this.state.val);
        }, 0);
    }

    render() {
        return null;
    }
}

//输出 0 0 2 3

事务

diff算法

diff帮助计算出Virtual DOM中真正变化的部分,并只针对该部分进行原生DOM操作,而非重新渲染整个页面

详解diff
diff策略

React分别对tree diff、component diff以及element diff进行算法优化。

tree diff
component diff
element diff

节点在新集合中的索引值大于在旧集合中的索引时,需移动
删除操作是移动完成之后遍历旧集合,若有新集合中未出现的节点则删除

React Patch方法

将tree diff计算出来的DOM差异队列更新到真实的DOM节点上,让浏览器能够渲染出更新的数据

认识Flux架构模式

React独立架构

MV*与Flux

MVC/MVVM

主要涉及三种角色:Model、View和Controller

Flux

核心思想是<mark style="box-sizing: border-box;">数据和逻辑永远单向流动</mark>。

flux

在Flux应用中,数据从action到dispatcher再到store,最终到view的路线是单项不可逆的

Flux基本概念

一个Flux应用由3大部分组成:dispatcher、store和view,其中dispatcher负责分发事件;store负责保存数据,同时响应时间并更新数据;view负责订阅store中的数据。

dispatcher

dispatcher是Flux中最核心的方法,也是flux这个npm包中的核心方法。 只需关心.register(callback)和.dispatch(action)这两个API。

action

action是一个普通的JavaScript对象,一般包含type、payload等字段,用于描述一个事件以及需要改变的相关数据。

store
controller-view

一般来说,controller-view是整个应用最顶层的view,主要进行store与React组件之间的绑定,定义数据更新以及传递的方式

view

如果界面操作需要修改数据,必须使用dispatcher分发一个action。

actionCreator

深入Redux应用架构

Redux简介

Redux三大原则
单一数据源
状态是只读的

定义一个reducer,其功能是根据当前触发的action对当前应用的状态(state)进行迭代。没有直接修改应用的状态,而是返回了一份全新的状态

状态修改均由纯函数完成 在Redux里,通过定义reducer来确定状态的修改,而每一个reducer都是纯函数,即其没有副作用,接受一定的输入,必定会得到一定的输出。

Redux核心API

Redux的核心是一个store,这个store由Redux提供的createStore(reducers[, initialState])方法生成。

Redux中最核心的API是createStore,通过createStore方法创建的store是一个对象,包含四个方法:

subscribe()和replaceReducer()方法一般会在Redux与某个系统做桥接的时候使用

与React绑定

react-redux提供了一个组件和一个API帮助Redux和React进行绑定。

一个是React组件<Provider />,一个是connect()

Redux middleware

middleware的由来
Redux同步数据流动
redux同步数据流动
应用middleware后Redux处理事件的逻辑
应用middleware后Redux处理事件的逻辑

每一个middleware处理一个相对独立的业务需求,通过串联不同的middleware实现变化多样的功能

理解middleware机制

Redux提供了applyMiddleware方法来加载middleware。

import compose from './compose';

export default function applyMiddleware(...middlewares) {
    return (next) => (reducer, initialState) {
        let store = next(reducer, initialState);
        let dispatch = sotre.dispatch;
        let chain = [];

        var middlewareAPI = {
            getState: store.getState,
            dispatch: (action) => dispatch(action),
        };

        chain = middlewares.map(middleware => middleware(middlewareAPI));
        dispatch = compose(...chain)(store.dispatch);

        return {
            ...store,
            dispatch,
        };
    }
}

函数式编程思想设计

middleware是一个层层包裹的匿名函数,即函数式编程中的currying,是一种使用匿名单参数函数来实现多参数的方法。

currying的middleware皆有的好处:

给middleware分发store
//创建普通的store
let newStore = applyMiddleware(mid1, mid2, mid3, ...)(createStore)(reducer, null);

组合串联middleware
dispatch = compose(...chain)(store.dispatch);

//假设n=3,dispatch为
dispatch = f1(f2(f3(store.dispatch)));

不能在middleware中调用dispatch

Redux异步流

Redux与路由

在Redux应用中,遇到了一些新的问题,其中最迫切的是,应用程序的所有状态都应该保存在一个单一的store中,而当前的路由状态很明显也属于应用状态的一部分。如果直接使用React Router,就意味着所有路由相关的信息脱离了Redux store的控制,这样就违背了Redux的设计思想。

React Router
路由的基本原理

理由的基本原理即是保证View和URL同步,而View可以看成是资源的一种表现。

路由的基本原理
React Router特性
声明式路由
import {Router, Route, browserHistory} from 'react-router';

const routes = (
    <Router history={browserHistory}>
        <Route path="/" component={App} />
    </Router>
);

嵌套路由及路径匹配
import {Router, Route, IndexRoute, browserHistory} from 'react-router';

const routes = (
    <Router history={browserHistory}>
        <IndexRoute component={MailList} />
        <Route path="/mail/:mailId" component={Mail}></Route>
    </Route>
);

支持多种路由切换方式

路由切换可以使用hashChange或history.pushState。

React Router提供了两种解决方案

<mark style="box-sizing: border-box;">browserHistory即history.pushState的实现</mark>

React Router Redux

职责主要是将应用的路由信息与Redux的store绑定在一起

采用Redux架构时,所有的应用状态都必须放在一个单一的store中管理,路由状态也不例外

将React Router与Redux store绑定

React Router Redux提供了简单直白的API syncHistoryWithStore来完成与Redux store的绑定工作。只需传入React Router中的history,以及Redux中的store,就可以获得一个增强后的history对象。

import { browserHistory } from  'react-router';
import { syncHistoryWithState } from 'react-router-redux';
import reducers from '<project-path>/reducers'

const store = createStore(reducers);
const history = syncHistoryWithStore(browserHistory, store);

用Redux的方式改变路由

无论是Flux还是Redux,想要改变数据,必须要分发一个action

import { browserHistory } from 'react-router';
import { routerMiddleware} from 'react-router-redux';

const middleware = routerMiddleware(browserHistory);
const store = createStore(
    reducers,
    applyMiddleware(middleware)
);

import {push} from 'react-router-redux';

store.dispatch(push('/home'));

Redux与组件

容器型组件

容器型组件,意为组件是怎么工作的,具体一些就是数据是怎么更新的。不包含任何Virtual DOM的修改或组合,也不会包含组件的样式。

展示型组件

展示型组件,意为组件是怎么渲染的。包含Virtual DOM的修改和组合,也可能包含组件的样式。

Redux中的组件
Layouts
//一般写法为
const layout = ({ children }) => (
    <div className='container'>
        <Header />
        <div className='content'>
            { children }
        </div>
    </div>
);

views
Components
上一篇 下一篇

猜你喜欢

热点阅读