Vue渲染器之组件的渲染

对于一个a.vue文件(组件),它有template,script,style三部分,使用的时候需要先import a from ./a.vue

经过vue-loader处理后 , a 其实变成了一个对象,template就变成了对象中的render函数,返回的是VNode.其中vnode.type 属性来存储组件的选项对象a

js 复制代码
//这个组件对应的VNode
{
type:a,
//props:{}
//....
}

现在处理组件转变为处理这个对象,现在只需要聚焦这个对象即可了

在render中的 patch 函数中会根据 type 判断节点类型,其实处理组件跟处理普通标签差不多,当n1为null时,执行 mountComponent ,反之执行 updateComponent

组件模版与状态

现在再来讨论一下,这个组件对象里应该包含什么东西,首先对于一个组件,我们要知道它渲染了什么,这里用虚拟DOM表示。Vue规定组件内的render函数的返回值就是虚拟DOM,所以我们现在可以得到组件的描述-虚拟DOM(之后用subTree代指)

接着组件应该有自己的状态也就是数据,规定是data函数返回的,并且这些数据可以在render函数中通过this访问。

进行组件维护

对于组件我们必须注册一个实例,用来维护组件运行过程中的所有信息,例如生命周期函数、组件渲染的子树(subTree)、组件是否已经被挂载、组件自身的状态等

应该在第一次渲染也就是mountComponent注册它的实例。

js 复制代码
function mountComponent(vnode, container, anchor) {
  const { render, state } = vnode.type
  const state = reactive(data())
  const instance = {
    // 组件自身的状态数据,即 data
    state,
    // 一个布尔值,用来表示组件是否已经被挂载,初始值为 false
    isMounted: false,
    // 组件所渲染的内容,即子树(subTree)
    subTree: null
  }

  // 将组件实例设置到 vnode 上,用于后续更新
  vnode.component = instance
}

结合响应式

接着执行setupRenderEffect,它的作用就是注册带副作用的渲染函数.用来完成子组件的自动更新.而这个副作用函数componentUpdateFn做了什么呢

其实很简单就是利用之前的实例拿到上面的属性isMounted进行判断

如果是false,渲染组件,执行renderComponentRoot可以拿到subTress,之后在执行patch进行挂载.

反正更新,首先执行updateComponentPreRender更新组件实例,再执行patch

父组件导致的更新

上面是子组件自身状态改变自动更新,下面来讨论一下父组件的状态改变导致子组件更新

也就是会触发上面提到的updateComponent,在里面会比较组件VNode中的props,chilren等属性是否相同,相同代表不需要更新,反正需要更新.接下来会进行下面两步操作

  1. invalidateJob(instance.update)
  2. instance.update()

第一步是因为Vue更新粒度是组件级别的,子组件也可能因为自身数据改变触发更新,这样可以避免重复渲染

第二步是触发了子组件的更新渲染

深入探析如何注册组件实例(处理setup)

在这个createComponentInstance函数中会进行组件实例的创建,创建之后我们还要设置实例才行,如果是组合式api的写法交给这个函数setupComponent进行设置的.

在这个函数中先初始化props,slots.接着执行核心函数setupStatefulComponent,它的作用是

  1. 创建渲染上下文代理,虽然实例中会存放对应的属性,例如data,setupState(setup的返回值),props,ctx(选项式api中的methods,computer,inject等),但是为了方便用户,render函数会直接访问实例instance.ctx属性,所以需要对它加一层代理,用来控制数据的读取及修改.看看他的捕获函数
  • get: 访问的key不以 <math xmlns="http://www.w3.org/1998/Math/MathML"> 开头 , 依次判断 s e t u p S t a t e , d a t a , p r o p s , c t x 是否包含这个 k e y . 反正 , 进行判断是不是 V u e 暴露出的 开头,依次判断setupState,data,props,ctx是否包含这个key.反正,进行判断是不是Vue暴露出的 </math>开头,依次判断setupState,data,props,ctx是否包含这个key.反正,进行判断是不是Vue暴露出的xxx属性或方法,再判断是不是在ctx中以$开头的key,最后判断他是不是全局属性
  • set: 开发环境修改props会提示
  1. 处理setup函数
  • 首先会创建setupContext对象,他就是setup函数的第二个参数,可以解构出attrs、slots和 emit三个属性以及expose函数。setupContext的目的就是让我们可以在setup函数内部访问组件实例上的属性、插槽、派发事件的方法enit以及暴露组件方法的函数expose.
  • 执行setup,第一个参数是instance.props,第二个参数是setupContext.返回结果可以是一个对象也可以是一个函数,当返回函数时将被当成render函数.如果setupResult是一个对象,那么对其返回结果做一层代理,把结果赋值给instance.setupState,
相关推荐
拉不动的猪4 分钟前
webpack分包优化简单分析
前端·vue.js·webpack
德莱厄斯9 分钟前
没开玩笑,全框架支持的 dialog 组件,支持响应式
前端·javascript·github
非凡ghost38 分钟前
Affinity Photo(图像编辑软件) 多语便携版
前端·javascript·后端
非凡ghost40 分钟前
VideoProc Converter AI(视频转换软件) 多语便携版
前端·javascript·后端
endlesskiller1 小时前
3年前我不会实现的,现在靠ai辅助实现了
前端·javascript
用户904706683571 小时前
commonjs的本质
前端
Zyx20071 小时前
用 JavaScript 打造 AI 大脑:前端开发者的新时代——基于 Brain.js 的浏览器端 NLP 实战
javascript·机器学习
Sailing1 小时前
5分钟搞定 DeepSeek API 配置:从配置到调用一步到位
前端·openai·ai编程
麦麦大数据1 小时前
F035 vue+neo4j中医南药药膳知识图谱可视化系统 | vue+flask
vue.js·知识图谱·neo4j·中医·中药·药膳·南药
Pa2sw0rd丶1 小时前
如何在 React 中实现键盘快捷键管理器以提升用户体验
前端·react.js