前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >组件&生命周期

组件&生命周期

作者头像
河湾欢儿
发布2018-09-06 17:35:15
1.8K0
发布2018-09-06 17:35:15
举报

组件使你可以将 UI 划分为一个一个独立,可复用的小部件,并可以对每个部件进行单独的设计。

从定义上来说, 组件就像JavaScript的函数。封装内容, 达到重用的目的. 组件可以接收任意输入(称为”props”), 并返回 React 元素,用以描述屏幕显示内容

两种组件创建的方式 1.函数式组件

代码语言:javascript
复制
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>Hello World</title>
        <!--react的核心库-->
        <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>

        <!--react的与dom相关的一些功能-->
        <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

        <!--将浏览器不支持的jsx语法转化为js语法-->
        <script crossorigin src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    </head>

    <body>
        <div id="root"></div>
        
        
    </body>

</html>
<!--
    
    组件:组成的部件,可以接受任何props输入,并返回元素
    
-->
<script type="text/babel">

    // 1. 创建一个基本的组件
    function Welcome(){
        return (
            <div>
                <p>哈哈</p>
            </div>
        )
    }

    // 2. 组件的使用
    ReactDOM.render(
        <Welcome></Welcome>, 
        document.getElementById('root') 
    );

</script>

类组件

代码语言:javascript
复制
<!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="UTF-8" />
            <title>Hello World</title>
            <!--react的核心库-->
            <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    
            <!--react的与dom相关的一些功能-->
            <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    
            <!--将浏览器不支持的jsx语法转化为js语法-->
            <script crossorigin src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
        </head>
    
        <body>
            <div id="root"></div>
            
            
        </body>
    
    </html>
    <!--
        
        组件:组成的部件,可以接受任何props输入,并返回元素
        
    -->
    <script type="text/babel">
    
        // 1. 创建一个基本的组件
        class Welcome extends React.Component{
            render (){
                return (
                    <div>
                        <p>哈哈</p>
                    </div>
                )
            }
        }
    
        // 2. 组件的使用
        ReactDOM.render(
            <Welcome></Welcome>, 
            document.getElementById('root') 
        );
    
</script>

生命周期

state和生命周期

state 允许 React 组件在不违反props规则的情况下, 根据用户操作, 网络响应, 或者其他随便什么东西, 来动态地改变其输出。 类似于vue中的data

state的定义

在类组件的constructor中定义state

代码语言:javascript
复制
constructor(props) {
    super(props);
    this.state = {
      posts: [],
      comments: []
    };
  }

****不能直接修改state(需要调用this.setState())

代码语言:javascript
复制
// 错误  这样将不会重新渲染一个组件:
this.state.comment = 'Hello';
// 正确    用 setState() 代替:
this.setState({comment: 'Hello'});
唯一可以分配 this.state 的地方是构造函数。

state(状态) 更新可能是异步的

使用回调函数的形式实现异步操作

需要将对象参数转变为回调函数的形式

代码语言:javascript
复制
// 错误
this.setState({
  counter: this.state.counter + this.props.increment,
});


// 正确
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));
使用另一种 setState() 的形式,它接受一个函数而不是一个对象。
这个函数将接收前一个状态作为第一个参数,应用更新时的 props 作为第二个参数:

state(状态)更新会被合并 你的状态可能包含几个独立的变量:

代码语言:javascript
复制
constructor(props) {
  super(props);
  this.state = {
    posts: [],
    comments: []
  };
}

***调用this.setState()修改单个的状态不会影响其他的状态,只会合并当前修改的这一个状态

钩子函数是window消息处理机制的一部分,通过设置”钩子”,应用程序可以在系统级对所有消息,事件进行过滤,访问在正常情况下无法访问的消息 钩子函数的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统

react组件的三个状态 1.mount 2.update 3.unmount react针对以上三种状态都封装了hook函数

生命周期钩子详解 如下这些方法在组件实例被创建和被插入到dom中时被调用。

1.constructor()

---constructor初始化state的好地方。如果我们不需要初始化state,也不需要bind任何方法,那么在我们的组件中不需要实现constructor函constructor在组件被mounted之前调用,我们的组件继承自React.Component,constructor函数中我们在其他操作前应该先调用super(props),否则this.props将会是undefined。

---constructor初始化state的好地方。如果我们不需要初始化state,也不需要bind任何方法,那么在我们的组件中不需要实现constructor函数。

----注意下面这种情况,很容易产生bug,我们通常的做法是提升state到父组件,而不是使劲的同步state和props。

代码语言:javascript
复制
constructor(props) {
  super(props);
  this.state = {
    color: props.initialColor
  };
}

componentWillMount()

--此方法在mounting之前被立即调用,它在render()之前调用,因此在此方法中setState不会触发重新渲染。此方法是服务器渲染中调用的唯一的生命周期钩子,通常我们建议使用constructor()。 render() --render()方法是react组件必须的,它检查this.props和this.state并且返回一个React元素,我们也可以返回null或false,代表我们不想有任何的渲染。 --render()方法应该是一个纯方法,即它不会修改组件的state,在每一次调用时返回同样的结果。它不直接和浏览器交互,如果我们想要交互,应该在componentDidMount()或者其他的生命周期函数里面。 componentDidMount() --此方法在组件被mounted之后立即被调用,初始化dom节点应该在此方法中,如果需要从远端健在数据,这里是实例化网络请求的好地方,此方法中setState会触发组件重新渲染。

Updating

props和state的改变产生更新。在重新渲染组建时,如下的方法被调用 componentWillReceiveProps()

一个已经mounted的组件接收一个新的props之前componentWillReceiveProps()被调用,如果我们需要更新state来响应prop的更改,我们可以在此方法中比较this.props和nextProps并使用this.setState来更改state。

注意,即使props没有改变,React也可以调用这个方法,因此如果你只想处理改变,请确保比较当前值和下一个值。当父组件导致你的组件重新渲染时,可能会发生这种情况。

React在组件mounting期间不会调用此方法,只有在一些组件的props可能被更新的时候才会调用。调用this.setState通常不会触发componentWillReceiveProps。

shouldComponentUpdate()

使用此方法让React知道组件的输出是否不受当前state或props更改的影响。默认行为是在每次state更改时重新渲染组件,在大多数情况下,我们应该默认改行为。

当接收到新的props或state时,shouldComponentUpdate()在渲染之前被调用。默认返回true,对于初始渲染或使用forceUpdate()时,不调用此方法。返回false不会阻止子组件的state更改时,该子组件重新渲染。

如果shouldComponentUpdate()返回false,那么componentWillUpdate(),render()和componentDidUpdate()将不会被调用。在将来,React可能将shouldComponentUpdate()作为提示而不是strict指令,返回仍然可能导致组件重新渲染。

componentWillUpdate()

当接收新的props或state时,componentWillUpdate()在组件渲染之前被立即调用。使用此函数作为在更新发生之前执行准备的机会。初始渲染不会调用此方法。

注意:这里不能调用this.setState()(如果调用会怎么样?好奇心很重呀,试了一下,会产生死循环,一直更新。

如果我们需要更新state以响应props的更改,我们应该使用componentWillReceiveProps()

render()

render()方法是react组件必须的,它检查this.props和this.state并且返回一个React元素,我们也可以返回null或false,代表我们不想有任何的渲染。

render()方法应该是一个纯方法,即它不会修改组件的state,在每一次调用时返回同样的结果。它不直接和浏览器交互,如果我们想要交互,应该在componentDidMount()或者其他的生命周期函数里面。

componentDidUpdate()

此函数在更新后立即被调用。初始渲染不调用此方法。

当组件已经更新时,使用此操作作为DOM操作的机会。这也是一个好的地方做网络请求,只要你比较当前的props和以前的props(例如:如果props没有改变,可能不需要网络请求)。

Unmounting

当从dom中移除组件时,这个方法会被调用

componentWillUnmount() 此函数在组件被卸载和销毁之前被立即调用。在此方法中执行一些必要的清理。例如清除计时器,取消网络请求或者清理在componentDidMount中创建的任何DOM元素。

代码语言:javascript
复制
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>Hello World</title>
        <!--react的核心库-->
        <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>

        <!--react的与dom相关的一些功能-->
        <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

        <!--将浏览器不支持的jsx语法转化为js语法-->
        <script crossorigin src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    </head>

    <body>
        <div id="root"></div>
    </body>

</html>
<script type="text/babel">
    
    // 创建一个类组件
    class LifeCycle extends React.Component {
        
        // 1. mount阶段
        constructor(props) {
            super(props);
            this.state = {name: 'wlt'};
            this.changeState = this.changeState.bind(this);
            console.log('constructor');
        }
        
        componentWillMount() {
            console.log('componentWillMount');
        }
        
        render() {
            console.log('render');
            return (
                <div className="life-cycle-bg">
                    <p>Hello {this.props.value}</p>
                    <p>Hello {this.state.name}</p>
                    <button onClick={this.changeState}>改变lifeCycle的state</button>
                </div>
            );
        }
        
        componentDidMount() {
            console.log('componentDidMount');
        }
        
        // 2. update阶段
        componentWillReceiveProps(nextProps) { // 只作用于属性的变化,不作用于状态的变化
            console.log('componentWillReceiveProps');
        }
    
        shouldComponentUpdate(nextProps, nextState) {
            console.log('shouldComponentUpdate');
            return true;
        }
    
        componentWillUpdate(nextProps, nextState) {
            console.log('componentWillUpdate');
        }
        
        // ---- render会重新执行
    
        componentDidUpdate(prevProps, prevState) {
            console.log('componentDidUpdate');
        }
        
        // 3. Unmount阶段
        componentWillUnmount(prevProps, prevState) {
            console.log('componentWillUnmount');
        }
        
        // 修改状态
        changeState() {
            this.setState({name: 'sxm'});
        }
    }
    
    class ParentLifeCycle extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                value: 'World',
                destroyed: false,
                rerender: false
            };
            this.handleChange = this.handleChange.bind(this);
            this.destroyComponent = this.destroyComponent.bind(this);
            this.handleRerender = this.handleRerender.bind(this);
        }
    
        handleChange() {
            this.setState((prevState, props) => ({
                value: prevState.value + ' wlt'
            }));
        }
    
        handleRerender() {
            this.setState({rerender: true});
        }
    
        destroyComponent() {
            this.setState({destroyed: true});
        }
    
        render() {
            if(this.state.destroyed) return null;
            return (
                <div className="parent-life-cycle-bg">
                    <p>
                        <button onClick={this.handleChange}>改变LifeCyle的props</button>
                        <button onClick={this.handleRerender}>父组件重新渲染,子组件re-render</button>
                        <button onClick={this.destroyComponent}>删除组件</button>
                    </p>
                    <LifeCycle value={this.state.value}/>
                </div>
            );
        }
    }
    
    ReactDOM.render(
        <ParentLifeCycle />, document.getElementById('root')
    );
</script>

state 和 生命周期

实现一个基本的定时器功能

代码语言:javascript
复制
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8" />
        <title>Hello World</title>
        <!--react的核心库-->
        <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>

        <!--react的与dom相关的一些功能-->
        <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

        <!--将浏览器不支持的jsx语法转化为js语法-->
        <script crossorigin src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
    </head>

    <body>
        <div id="root"></div>
    </body>

</html>
<script type="text/babel">


    // 创建一个组件 -- 使用函数式组件
    function Clock(){
        // 创建元素
        const element = (
            <div>
                <h1>hello world!</h1>
                <h2>It is {new Date().toLocaleTimeString()}</h2>
            </div>
        )
        
        // 使用render函数渲染已经创建的元素
        ReactDOM.render(
            element, 
            document.getElementById('root') 
        );
    }
    
    setInterval(Clock,1000)


</script>

存在的问题

完成定时器的功能,使用组件化的形式进行封装的时候,在进行组件调用的时候应该能够直接通过 就能完成一个定时器,而不用再配合外部的js操作 这样做的话能够实现相关的功能,但是不利于复用

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.06.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 生命周期
  • state和生命周期
  • state(状态) 更新可能是异步的
  • Updating
  • Unmounting
  • state 和 生命周期
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档