React16、17和Vue2、3生命周期、渲染顺序

11 篇文章 0 订阅
4 篇文章 0 订阅

目录

对比

命名规则

react:componentWillXxx,componentDidXxx

vue2:beforeXxx,xxxed

vue3:onBeforeXxx,onXxxed

生命周期

应用

created(vue2)(此时可访问this,更早地响应):ajax请求

mounted:操作dom(初始化节点、事件监听、副作用、ajax、网络请求)

WillUnmount:清除 timer,取消ajax、网络请求、订阅

渲染顺序

洋葱模型

React

组件挂载:插入 DOM 树

挂载前constructor()

挂载时render()

挂载后componentDidMount()

更新

更新时render():prop/state改变

更新后componentDidUpdate()

卸载

卸载前componentWillUnmount():

React17增删的生命周期

废除的生命周期

componentWillMount

componentWillRecieveProps

componentWIllUpdate

新增的生命周期

getDerivedStateFromProps(nextProps, prevState):用props更新state的过程

替换componentWillReceiveProps:只有当父组件造成重新渲染时才调用

在每次渲染render之前都会调用:返回一个对象表示新的 state;若不需要更新,返回 null 即可

getSnapshotBeforeUpdate(prevProps, prevState):读取最新的DOM数据

替换 componentWillUpdate(update后 DOM 更新前被调用)

返回值将作为 componentDidUpdate(prevProps, prevState, snapshot) 的snapshot

componendDidCatch(error, info):错误边界

常见问题

 setState 更新的值不变,还是会触发生命周期钩子

Vue

初始阶段:beforeCreate、created、beforeMount、mounted

更新阶段:beforeUpdate、updated

销毁阶段:beforeUnmout、unmounted

生命周期

Vue3

使用:先导入

onErrorCaptured监听组件的统一报错:onErrorCaptured(error, component, details)


对比

命名规则

react:componentWillXxx,componentDidXxx

vue2:beforeXxx,xxxed

vue3:onBeforeXxx,onXxxed

生命周期

生命周期React16React17Vue2Vue3(使用先导入)
初始化constructorbeforeCreatesetup
created
componentWillMountbeforeMountonBeforeMount
componentDidMountmountedonMounted
更新componentWIllUpdategetSnapshotBeforeUpdate(prevProps, prevState)beforeUpdateonBeforeUpdate
shouldComponentUpdate,componentDidUpdate

updated

onUpdated
卸载componentWillUnmountbeforeDestroyonBeforeUnmount
destroyedonUnmounted
监听组件的统一报错componendDidCatch(error, info)错误边界onErrorCaptured(error, component, details)

应用

created(vue2)(此时可访问this,更早地响应):ajax请求

mounted:操作dom(初始化节点、事件监听、副作用、ajax、网络请求)

WillUnmount:清除 timer,取消ajax、网络请求、订阅

渲染顺序

洋葱模型

React

生命周期钩子函数就是回调函数

组件挂载:插入 DOM 树

挂载前constructor()

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数

挂载时render()

class 组件中唯一必须实现的方法。

挂载后componentDidMount()

组件(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。

更新

更新时render():prop/state改变

它只有在 prop 或state发生变化时才可能更新和重新渲染

更新后componentDidUpdate()

首次渲染不会执行此方法。

卸载

卸载前componentWillUnmount():

class Welcome extends React.Component {
    state = {
        msg: 'hello world'
    }
    constructor(props){
        super(props);
        console.log('constructor');
    }
    componentDidMount = () => {
        // react中发起ajax请求的初始操作,在这个钩子中完成
        console.log('componentDidMount');
    }
    componentDidUpdate = () => {
        // 等DOM更新后触发的钩子
        console.log('componentDidUpdate');
    }
    componentWillUnmount = () => {
        console.log('componentWillUnmount');
    }
    handleClick = () => {  
        /* this.setState({
          msg: 'hi react'
        }); */
        //this.forceUpdate();
        root.unmount();   // 触发卸载组件
    }
    render(){
        console.log('render');
        return (
            <div>
                <button onClick={this.handleClick}>点击</button>
                { this.state.msg }
            </div>
        );
    }
}

React17增删的生命周期

废除的生命周期

componentWillMount

componentWillRecieveProps

componentWIllUpdate

官网文档指出使用这些生命周期的代码会在未来版本的react中更容易产生bug,尤其是对于异步渲染的版本。由于未来采用异步渲染机制,所以即将在17版本中去掉的生命周期钩子函数

dom 被挂载之前的阶段都可以被打断重来,导致 componentWillMountcomponentWillUpdatecomponentWillReceiveProps 在一次更新中可能会被触发多次,因此那些只希望触发一次的副作用应该放在 componentDidMount

新增的生命周期

getDerivedStateFromProps(nextProps, prevState):用props更新state的过程

替换componentWillReceiveProps:只有当父组件造成重新渲染时才调用

接收父组件传递过来的 props 和组件之前的状态

每次渲染render之前都会调用:返回一个对象表示新的 state;若不需要更新,返回 null 即可

最常见的误解就是 getDerivedStateFromPropscomponentWillReceiveProps 只会在 props “改变”时才会调用。实际上只要父组件重新渲染时,这两个生命周期函数就会重新调用,不管 props 有没有“变化”

static静态函数:定义在React组件类上的,而非实例上,无法通过this来访问组件的属性或状态,而是可以直接通过组件类本身调用。静态方法通常用于执行与组件实例无关的任务,例如工具函数。

class Form extends Component {
  state = {
    email: this.props.defaultEmail,
    prevUserID: this.props.userID
  };

  static getDerivedStateFromProps(props, state) {
    // Any time the current user changes,
    // Reset any parts of state that are tied to that user.
    // In this simple example, that's just the email.
    if (props.userID !== state.prevUserID) {
      return {
        prevUserID: props.userID,
        email: props.defaultEmail
      };
    }
    return null;
  }

  // ...
}

getSnapshotBeforeUpdate(prevProps, prevState):读取最新的DOM数据

Snapshot[ˈsnæpʃɑːt]:快照

替换 componentWillUpdate(update后 DOM 更新前被调用)
返回值将作为 componentDidUpdate(prevProps, prevState, snapshot) 的snapshot

在更新期间保留其滚动位置的聊天线程

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // Are we adding new items to the list?
    // Capture the scroll position so we can adjust scroll later.
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // If we have a snapshot value, we've just added new items.
    // Adjust scroll so these new items don't push the old ones out of view.
    // (snapshot here is the value returned from getSnapshotBeforeUpdate)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

componendDidCatch(error, info):错误边界

如果一个组件定义了componentDidCatch生命周期,则他将成为一个错误边界(错误边界会捕捉渲染期间、在生命周期方法中和在它们之下整棵树的构造函数中的错误,

就像使用了try catch,不会将错误直接抛出了,保证应用的可用性

常见问题

 setState 更新的值不变,还是会触发生命周期钩子

Vue

初始阶段:beforeCreate、created、beforeMount、mounted

更新阶段:beforeUpdate、updated

销毁阶段:beforeUnmout、unmounted

生命周期

Vue3

使用:先导入
// vue3
<script setup>     
import { onMounted } from 'vue';   // 使用前需引入生命周期钩子
 
onMounted(() => {
  // ...
});
 
// 可将不同的逻辑拆开成多个onMounted,依然按顺序执行,不会被覆盖
onMounted(() => {
  // ...
});
</script>
 
// vue2
<script>     
export default {         
  mounted() {   // 直接调用生命周期钩子            
    // ...         
  },           
}
</script> 

onErrorCaptured监听组件的统一报错:onErrorCaptured(error, component, details)
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!'
    };
  },
  methods: {
    throwError() {
      // 人为地抛出一个错误
      throw new Error('An error occurred.');
    }
  },
  onErrorCaptured(error, component, details) {
    console.error('Captured an error in component:', component);
    console.error('Error details:', error);
    console.error('Details:', details);
    // 可以选择返回 false 来阻止错误继续传播
    // return false;
  }
};
</script>

你真的了解 React 生命周期吗 - 掘金

Vue的钩子函数[路由导航守卫、keep-alive、生命周期钩子] - 掘金

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值