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,
相关推荐
码蜂窝编程官方23 分钟前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
gqkmiss23 分钟前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
Summer不秃29 分钟前
Flutter之使用mqtt进行连接和信息传输的使用案例
前端·flutter
旭日猎鹰33 分钟前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
Viktor_Ye39 分钟前
高效集成易快报与金蝶应付单的方案
java·前端·数据库
hummhumm41 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
乐闻x1 小时前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
一条晒干的咸魚1 小时前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
花海少爷1 小时前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript
Amd7941 小时前
Nuxt.js 应用中的 webpack:compiled 事件钩子
前端·webpack·开发·编译·nuxt.js·事件·钩子