第 67 期 - Vue3 组件渲染器中的组件实现与生命周期处理
logoFRONTALK AI/12月29日 16:36/阅读原文

摘要

文章分析了 Vue3 源码里组件的渲染器相关内容,包括有状态和无状态组件的挂载、更新,生命周期的处理以及 setup 方法的处理等

一、组件的挂载与更新

(一)无状态组件

无状态组件只有基本的 render 方法。在挂载无状态组件时,使用 mountComponent 方法,它做了三件事:创建组件实例并双向绑定、设置组件数据和属性、设置组件渲染的副作用。例如:

const component = {
  render() {
    return h("div", "hello this is component");
  }
};
const vnode = h(component);

在创建组件实例时,通过 createComponentInstance 方法给实例添加属性,如 vnode 节点、type 类型等。创建完实例后,用 setupComponent 方法对组件数据初始化,无状态组件没有数据,目的是把 render 方法绑定到实例。最后通过 setupRenderEffect 方法设置组件渲染。在组件渲染时,在 patch 挂载组件前,需要用 renderComponentRoot 方法拿到 VNode 数据。无状态组件的更新本质是先卸载 - 后挂载。

(二)有状态组件

有状态组件带有响应式数据放在 data 属性中并以对象形式返回。有状态组件挂载核心在于获取数据并设置响应式和处理 this 指向。获取数据并设置响应式是在 applyOptions 方法中,而 this 指向处理是在 renderComponentRoot 方法中。例如:

const component = {
  data() {
    return {
      msg: "hello this is component"
    };
  },
  render() {
    return h("div", this.msg);
  }
};
const vnode = h(component);

有状态组件更新本质是监听响应式数据的变化,触发绑定好的 effect 函数。

二、生命周期的处理

(一)beforeCreate & created

beforeCreate 在实例初始化后、数据/watch 等配置前被调用,created 则是数据都配置完了,还没开始渲染前调用,这两个生命周期在源码中都放在 applyOptions 中触发回调。

(二)beforeMount & mounted

beforeMount 在组件渲染之前调用,mounted 在渲染完成后调用。在 applyOptions 中拿到生命周期函数,用 registerLifecycleHook 注册方法把回调方法存储在组件实例中,创建组件实例时补充存储生命周期回调方法的属性。在 componentUpdateFn 方法中触发回调函数。在生命周期中获取响应式数据,通过改变 this 指向来实现。

三、setup 方法处理

setup 函数和普通的 render 方法区别在于 render 函数是 setup 函数的返回值,响应式数据分散在 setup 函数中单独声明。处理时对 setup 做判断,拿到返回值塞到 render 中。例如:

const component = {
  setup() {
    const obj = reactive({ msg: "hello world" });
    return () => h("div", obj.msg);
  }
};
const vnode = h(component);
 

扩展阅读

Made by 捣鼓键盘的小麦 / © 2025 Front Talk 版权所有