学习《深入react技术栈》-- 数据流和生命周期

前端之家收集整理的这篇文章主要介绍了学习《深入react技术栈》-- 数据流和生命周期前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1. React数据流

React数据流是自上向下单向流动,即父组件到子组件

stateprops是react组件中重要的概念。如果顶层组件初始化props,那么react会向下遍历整棵组件树,重新尝试渲染搜索相关的子组件。而state只关心每个组件自己内部的状态,这些状态只能在组件内部改变。

把组件看成一个函数,那么它接受了props作为参数,内部由state作为函数的内部参数,返回一个Virtual DOM的实现。

state

在react没有结合redux框架前,它自身也同样可以管理组件的内部状态,这类状态统一称为state

当组件内部使用库内置的setState方法时,该组件会尝试重新渲染。我们可以这样理解,因为我们改变了内部状态,组件需要更新。

import React,{Component} from 'react'

class Counter extends Component {
    constructor(props) {
        supre(props)
        this.state = {
            count: 0
        }
    }
    handleClick(e) {
        e.preventDefault()
        this.setState({
            count: this.state.count + 1
        })
    }
    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onClick={this.handleClick.bind(this)}></button>
            </div>
        )
    }
}

在react中常常在事件处理方法中更新state,如上述计数器。这样就可以把组件内状态封装在实现中。

setState是一个异步方法,一个生命周期内所有的setState方法会合并操作。

props

props是react用来让组件之间互相联系的一种机制。react的单向数据流,主要的流动管道就是props。props本身是不可变的。当我们试图修改props的原始值时,react会报出类型错误的警告。如下,我们在constructor中修改了props的值。

react为props同样提供了默认配置,通过defaultProps静态变量的方式来定义。当组件被调用的时候,默认值保证渲染后始终有值。

子组件props

在react中有一个重要且内置的prop--children,它代表组件的子组件集合。children可以根据传入子组件的数量来决定是否是数组类型。this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array。

React.Children是react官方提供的一系列操作children的方法。它提供map,forEach,count等函数,可以为我们处理子组件提供便利。

用function props与父组件通信

可以通过props传递函数给子组件,通过子组件调用和父组件进行信息交互。

propTypes

propTypes用户桂法props的类型与必须的状态。如果组件定义了propTypes,那么在开发环境下,就会对组件的props值得类型做检查,如果传入的props不能与之匹配,React会在控制台进行warning。

2. React生命周期

react组件的生命周期可以根据广义定义描述,可以分为挂载,渲染和卸载这几个阶段。当渲染后的组件需要更新时,我们会重新渲染组件,直至卸载。

生命周期可以分为两种:
1. 当组件在挂载或卸载的时候;
2. 当组件接收新的数据时,即组件更新时。

挂载和卸载过程

1. 组件的挂载

组件的挂载是最基本的过程,这个过程主要做组件状态的初始化:

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

class App extends Component {
    static propTypes = {}
    static defaultProps = {}
    constructor(props) {
        supre(props)
        this.state = {}
    }
    componentWillMount() {}
    componentDidMount() {}
    render() {
        return ()
    }
}

我们可以看到propTypes和defaulProps分别代表props类型检查和默认类型。这两个属性被声明成静态属性,意味着从类外面可以对它们进行访问,例如:App.propTypes和App.defaultProps。

这里可以看到两个明显的声明周期方法。componentWillMount会在render方法之前执行,componentDidMount方法会在render方法后执行,分别代表渲染前后的时刻。

这里没有什么特别的地方,包括读取初始state和props以及两个组件生命周期方法componentWillMount和componentDidMount,这些都只会在组件初始化时运行一次。

如果我们在componentWillMount中执行setState方法,这样是没有意义的。因为此时组件还没有渲染完毕,调用setState组件会更新state,但组件只会渲染一次。

如果我们在componentDidMount中执行setState,组件会再次更新,不过初始化过程中就渲染了两次组件。

组件的卸载

组件的卸载很简单,只有componentWillUnmount这一个卸载前状态:

import React,{Component} from 'react'

class App extends Component {
    componentWillUnmount() {
    }
    render() {
        return ()
    }
}

在componentWillUnMount方法中,我们常常会执行一些清理方法

数据更新过程

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

import React,PropTypes } from 'react';

class App extends Component {
    componentWillReceiveProps(nextProps) {
        this.setState({})
    }
    shouldComponentUpdate(nextProps,nextState) {
        return true
    }
    componentWillUpdate(nextProps,nextState) {
    
    }
    componentDidUpdate(prevProps,prevState) {
    }
    
    render() {
        return ()
    }
}

如果组件自身的state更新了,那么会一次执行shouldComponentUpdate,componentWillUpdate,render,componentDidUpdate。

shouldComponentUpdate它接受需要更新的props和state,让开发者增加必要的条件判断,在需要的时候更新,不需要的时候不更新。

默认情况下,当props改变的时候,react会渲染所有子节点,因为shouldComponentUpdate默认返回true。

componentWillUpdate和componentDidUpdata这两个生命周期方法很容易理解,它们代表更新过程中渲染前后的时刻。此时,我们可以想到componentWillUpdate方法提供需要更新的props和state,而componentDidUpdate提供更新前的props和state。

注意:不能在componentWillUpdate中执行setState。

如果组件是由父组件更新props而更新的,那么在shouldComponentUpdate之前会执行componentWillReceiveProps方法。此方法可以作为在传入props之后,渲染之前setState的机会。

3. React与DOM

现在我们讨论下如何将组件渲染到真实的DOM上。

ReactDOM

ReactDOM中的API比较少,只有findDOMNode,unmountComponentAtNode和render。

  • findDOMNode

在React中只有在componentDidMount和componentDidUpdate方法中可以获取到真正的DOM元素。React提供获取DOM元素方法有两种,其中一种就是findDOMNode:

DOMElement findDOMNode(ReactComponent component)

当组件被渲染到DOM中后,findDOMNode返回该React组件实例相应的DOM节点。它可以用于获取表单的value以及用于DOM的测量。

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

class App extends Component {
    componentDidMount() {
        const dom = ReactDOM.findDOMNode(this)
    }
    
    render() {
        return ()
    }
}

如果在render中返回null,那么findDOMNode也返回null。findDOMNode只对以及挂载的组件有效。

  • render

要把react渲染的虚拟DOM渲染到浏览器的DOM当中,就要使用render方法了。

ReactComponent render(
    ReactElement element,DOMElement container,[function callback]
)

方法把元素挂载到container中,并返回element的实例子(即refs引用)。如果是无状态组件,render会返回null,当组件安装完毕,callback就会被调用

当组件在初次渲染之后再次更新时,react不会把整个组件重新渲染一次,而会用它高效的DOM diff算法做局部的更新。

这里没怎么看,感觉用处不大就不介绍了。

  • refs

刚才我们描述了ReactDOM的render方法,比如我们渲染App组件到root节点下:

const myAppInstance=ReactDOM.render(<App/>,document.getElementById('root'));
myAppInstance.doSth();

我们利用render方法获取了App组件的实力,然后我们可以对它做一些操作。但是在组件内JSX不会返回一个组件的实例,它是一个ReactElement,只是告诉react被挂载的组件应该长什么样子:

cosnt MyApp = <App />

refs是react组件中非常特殊的props,可以附件到任何组件上,字面意思理解就是reference,组件被调用时会新建一个该组件的实例。
它也可以是一个回调函数,这个回调函数会在组件被挂载后立即执行:

import React,{ Component } from 'react';
class App extends Component {
    constructor(props){
        super(props);
        this.handleClick = this.handleClick.bind(this);
    }
    handleClick() {
        if (this.myTextInput !== null) {
        this.myTextInput.focus();
    }
    
    render() {
        return (
        <div>
            <input type="text" ref={(ref) => this.myTextInput = ref} />
            <input
                type="button"
                value="Focus the text input"
                onClick={this.handleClick}
            />
        </div>
        );
    }
}

在这个例子,我们得到了input组件的真正实例,所以可以在按钮被按下后调用输入框focus方法。该例子把refs放到原生的DOM组件input中,我们可以通过refs得到DOM节点;如果把refs放到React组件,比如:<TextInput>,我们获得的就是TextInput的实例,因此就可以调用TextInput的实例方法

refs同样支持字符串,对于DOM操作,不仅可以使用findDOMNode获得该组件DOM,还可以使用refs获得组件内部的DOM。

import React,{ Component } from 'react'
import ReactDOM from 'react-dom'

class App extends Component {
    componentDidMount() {
        // myComp 是 Comp 的一个实例,因此需要用 findDOMNode 转换为相应的 DOM
        const myComp = this.refs.myComp;
        const dom = findDOMNode(myComp);
    }
    render() {
        return (
            <div>
                <Comp ref="myComp" />
            </div>
        );
    }
}

获取一个react组件的引用,既可以使用this来获取当前react组件,也可以使用refs来获取你拥有的子组件的引用。

原文链接:https://www.f2er.com/react/302153.html

猜你在找的React相关文章