Vue3源码梳理:运行时的设计方案概况

Vue 3 中编译时和运行时的概念区别 Vue 3 中的编译时和运行时是两个关键阶段,分别负责模板的编译和组件的实际执行。编译时阶段将模板转换为渲染函数,并进行静态提升、指令转换等优化,以减少运行时的开销。运行时阶段则负责创建组件实例、初始化响应式系统,并执行渲染和更新流程。组件实例在运行时创建,因为此时组件的所有选项和数据来源(如父组件传入的 props)都已确定,Vue 才能实例化组件并运行初始化逻辑。编译时生成组件的“类”定义,而运行时按需创建多个实例。这种分离确保了 Vue 3 的高效性和灵活性。 阅读详情

关于运行时和demo简单示例

  • 运行时,简单理解,就是把vnode渲染到页面中

    <div id='app'></div>
    <script>
      const { render, h } = Vue
    
      const vnode = h('div', {
        class: 'test',
      }, 'hello render')
    
      const container = document.querySelector('#app')
      render(vnode, container)
    </script>
    
  • 整个runtime包含两个环节

    • 1.利用h函数生成vnode
    • 2.利用render函数把vnode渲染到指定位置
  • 所以,我们的目标是

    • 理解vnode作用,为何要创建vnode
    • 创建vnode参数是干嘛的,为何要传递这些参数
  • 在理解这些之前, 我们需要了解

    • HTML DOM 节点树 与 虚拟 DOM 树
    • 这两者的区别

HTML DOM 节点树 与 虚拟 DOM 树

1 )两个概念

  • html dom 节点树
  • 虚拟 dom 树
<div>
  <h1> hello h1</h1>
  <!-- 哈哈 -->
  hello div
</div>
  • 浏览器会把它们通过一个dom树来表示
  • dom树的解释:https://zh.javascript.info/dom-nodes
  • 上述dom树的示例包含
    • 标签点击、注释节点、文本节点

2 )关于虚拟DOM

  • 官方关于虚拟dom的解释:https://cn.vuejs.org/guide/extras/rendering-mechanism.html#virtual-dom
    • 虚拟 DOM (Virtual DOM,简称 VDOM) 是一种编程概念
    • 意为将目标所需的 UI 通过数据结构“虚拟”地表示出来
    • 保存在内存中,然后将真实的 DOM 与之保持同步
    • 这个概念是由 React 率先开拓,随后在许多不同的框架中都有不同的实现,当然也包括 Vue。
  • 虚拟dom是一种理念,期望通过js对象描述一个div节点
  • 所以说,与其说虚拟 DOM 是一种具体的技术,不如说是一种模式,所以并没有一个标准的实现

3 ) 区别示例

拿文本节点来说

html dom 节点树表示

<div>text</div>

虚拟dom表示

const vnode = {
  type: 'div',
  children: 'text'
}

总结

  • 在运行时 runtime ,渲染器 renderer 会遍历整个虚拟dom树,并据此结构构建真实的dom树
  • 这个过程我们可以把它叫做挂载 mount
  • 在这个 vnode 对象发生变化时候,我们会对比 旧的 VNode 和 新的 VNode 之间的区别
  • 找出它们之间的区别,并应用这其中的变化到真实的dom上,这个过程叫做更新 patch

关于挂载和更新

简化版的demo

<div id='app'></div>
<script>
  // <div>hello render</div>
  const vnode = {
    type: 'div',
    children: 'hello render'
  }

  const vnode2 = {
    type: 'div',
    children: 'hello patch'
  }
  
  function render(oldVNode, newVNode, container) {
    // 第一次属于挂载,old不存在
    if(!oldVNode) {
      mount(newVNode, container)
    } else {
      patch(oldVNode, newVNode, container)
    }
  }

  // 挂载方法
  function mount(vnode, container) {
    const ele = document.createElement(vnode.type) // 1. 创建当前节点
    ele.innerText = vnode.children // 2.插入具体节点
    container.appendChild(ele) // 3. 将创建的节点存放到容器中
  } 

  // 卸载操作
  function unmount(container) {
    container.innerHTML = ''
  }
  
  // 更新操作
  function patch(oldVNode, newVNode, container) {
    // 1. 卸载
    unmount(container)
    // 2. 重新渲染
    const ele = document.createElement(newVNode.type)
    ele.innerText = newVNode.children
    container.appendChild(ele)
  }
  
  // 初始化时去挂载
  render(null, vnode, document.querySelector('#app'))

  // 延迟两秒进行更新
  setTimeout(() => {
    render(vnode, vnode2, document.querySelector('#app'))
  }, 2000)
</script>
  • 以上是挂载、更新的逻辑,是一个精简版的更新操作
  • vue本质上也是这类操作(删除旧节点,挂载新节点),但是性能更优,实现更复杂

h函数 和 render函数

在vue中的vnode对象实际上属性很多,我们精简一下

{
  // 是否是一个vnode对象
  "__v_isVNode": true,
  // 当前节点类型
  "type": "div",
  // 当前节点的属性
  "props": {"class": "test"}
  // 它的子节点
  "children": "hello render"
}
  • h函数本质上就是一个生成vnode的函数
  • https://cn.vuejs.org/api/render-function.html#h

官方示例

import { h } from 'vue'

// 除了 type 外,其他参数都是可选的
h('div')
h('div', { id: 'foo' })

// attribute 和 property 都可以用于 prop
// Vue 会自动选择正确的方式来分配它
h('div', { class: 'bar', innerHTML: 'hello' })

// class 与 style 可以像在模板中一样
// 用数组或对象的形式书写
h('div', { class: [foo, { bar }], style: { color: 'red' } })

// 事件监听器应以 onXxx 的形式书写
h('div', { onClick: () => {} })

// children 可以是一个字符串
h('div', { id: 'foo' }, 'hello')

// 没有 prop 时可以省略不写
h('div', 'hello')
h('div', [h('span', 'hello')])

// children 数组可以同时包含 vnode 和字符串
h('div', ['hello', h('span', 'hello')])
  • 官方文档上提供了各种各样的使用方式
  • 注意,除了 type 外,其他参数都是可选的
  • h 函数最多可接收三个参数
    • type: string | Component: 既可以是字符串(原生标记),也可以是一个Vue组件的定义
    • props?: object | null: 要传递的 prop
    • children?: Children | Slot | Slots: 子节点

2 ) render 函数

  • https://cn.vuejs.org/api/options-rendering.html#render

    render(vnode, container)
    
  • vnode 虚拟dom树

  • container: 承载的容器,真实节点的渲染节点位置

  • 通过render函数,我们可以通过编程形式来把虚拟dom转换成真实dom挂载到指定的容器盒子上

核心设计原则


1 ) 概述

  • vue源码中包含两块
    • runtime-core
    • runtime-dom
  • vue为什么要这么划分
    • 为什么不像是reactivity,都组织到一起
  • vue挂载和更新的逻辑处理是什么

2 ) vue为何分开设计

  • runtime-core 是运行时核心代码

    • 只放核心逻辑,不会放置宿主环境下的相关操作
    • 当当前的vue需要在浏览器端运行时,它就可以把操作dom的一些逻辑作为参数传递到render里面
    • 比如在 baseCreateRenderer 方法中的options,里面可以解构出很多 API
    • 这些 API 都是宿主环境传过来的函数
    • 假如当前 Vue 需要在浏览器上渲染,就把自己的一些 API 传递过来,类似于接口对接的方式,满足不同宿主平台的调用
    • 以此来满足不同平台的不同挂载渲染场景
  • runtime-dom 是浏览器渲染的核心逻辑,多是一个浏览器相关基本操作

    • 这里的很多API都会被作为参数,传递到 runtime-core 包中使用
    • 实现了 渲染 和 宿主平台 两者的解耦
    • 这里宿主平台可以是浏览器,可以是类浏览器环境
    • 一般基于vue渲染都是spa,服务端渲染 ssr
    • 除了这些渲染情况,还有weex, uniapp等都会用到vue的渲染服务
  • 所以

    • 分包的原因是:
      • 针对不同的宿主环境使用不同的API
  • 挂载和更新的逻辑处理

    • baseCreateRenderer 最终返回了一个对象 {render, hydrate, createApp},这个对象里有 render 函数

    • render函数有三个参数: vnode, container, isSVG 这第三个参数不用管

      const render: RootRenderFunction = (vnode, container, isSVG) => {
        // 不存在vnode
        if (vnode == null) {
          if (container._vnode) {
            unmount(container._vnode, null, null, true)
          }
        } else {
          // 存在vnode更新
          patch(container._vnode || null, vnode, container, null, null, null, isSVG)
        }
        flushPostFlushCbs()
        container._vnode = vnode
      }
      
    • 进入patch函数

      const patch: PatchFn = (
        n1,
        n2,
        container,
        anchor = null,
        parentComponent = null,
        parentSuspense = null,
        isSVG = false,
        slotScopeIds = null,
        optimized = __DEV__ && isHmrUpdating ? false : !!n2.dynamicChildren
      ) => {
        if (n1 === n2) {
          return
        }
      
        // patching & not same type, unmount old tree
        if (n1 && !isSameVNodeType(n1, n2)) {
          anchor = getNextHostNode(n1)
          unmount(n1, parentComponent, parentSuspense, true)
          n1 = null
        }
      
        if (n2.patchFlag === PatchFlags.BAIL) {
          optimized = false
          n2.dynamicChildren = null
        }
      
        const { type, ref, shapeFlag } = n2
        switch (type) {
          case Text:
            processText(n1, n2, container, anchor)
            break
          case Comment:
            processCommentNode(n1, n2, container, anchor)
            break
          case Static:
            if (n1 == null) {
              mountStaticNode(n2, container, anchor, isSVG)
            } else if (__DEV__) {
              patchStaticNode(n1, n2, container, isSVG)
            }
            break
          case Fragment:
            processFragment(
              n1,
              n2,
              container,
              anchor,
              parentComponent,
              parentSuspense,
              isSVG,
              slotScopeIds,
              optimized
            )
            break
          default:
            if (shapeFlag & ShapeFlags.ELEMENT) {
              processElement(
                n1,
                n2,
                container,
                anchor,
                parentComponent,
                parentSuspense,
                isSVG,
                slotScopeIds,
                optimized
              )
            } else if (shapeFlag & ShapeFlags.COMPONENT) {
              processComponent(
                n1,
                n2,
                container,
                anchor,
                parentComponent,
                parentSuspense,
                isSVG,
                slotScopeIds,
                optimized
              )
            } else if (shapeFlag & ShapeFlags.TELEPORT) {
              ;(type as typeof TeleportImpl).process(
                n1 as TeleportVNode,
                n2 as TeleportVNode,
                container,
                anchor,
                parentComponent,
                parentSuspense,
                isSVG,
                slotScopeIds,
                optimized,
                internals
              )
            } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
              ;(type as typeof SuspenseImpl).process(
                n1,
                n2,
                container,
                anchor,
                parentComponent,
                parentSuspense,
                isSVG,
                slotScopeIds,
                optimized,
                internals
              )
            } else if (__DEV__) {
              warn('Invalid VNode type:', type, `(${typeof type})`)
            }
        }
      
        // set ref
        if (ref != null && parentComponent) {
          setRef(ref, n1 && n1.ref, parentSuspense, n2 || n1, !n2)
        }
      }
      
    • 里面有一个switch,根据当前vnode的type来划分vnode的类型进行各自的处理

    • 挂载的操作,本质上都是依赖patch函数来执行的,内部根据type来匹配各类挂载流程

    • 所以,整个挂载的操作,本质上是依赖于patch函数来执行的,内部基于type来执行不同类型节点的挂载

    • 整个render的大致逻辑如下

      • baseCreateRenderer 这个函数
        • 包含核心的render方法
        • render方法的渲染会在vnode存在的时候使用patch函数
        • patch函数会根据当前节点的vnode类型来选择不用的节点挂载
        • 而每一种类型的挂载节点都类似处理:
          • 旧节点不存在时,进行挂载;
          • 旧节点存在进行更新
华为AR6140E/S5735设备密码策略配置全攻略:从复杂度到锁定机制 本文详细介绍了华为AR6140E/S5735设备的密码策略配置方法,涵盖密码复杂度、时效性和防护性三大核心维度。通过具体的CLI命令示例,指导管理员如何设置密码长度、字符组合、有效期及登录失败锁定等安全机制,为企业网络提供全面的用户名密码防护策略。 阅读详情

相关推荐

从零到英雄:如何用FPGA和AD9288打造你的第一台便携式示波器

本文详细介绍了如何利用FPGA和AD9288 ADC芯片从零开始打造一台高性能便携式示波器。通过硬件架构设计、高速数据采集系统实现及信号处理与显示系统的开发,读者可以掌握400Msps采样率的实现方法,并了解关键器件选型与系统优化技巧。

jjj34的博客 279

Vue代码思路

通过设置不同的断点和样式,可以让页面在不同的设备和屏幕尺寸上呈现出不同的布局效果。通过在不同的设备和屏幕尺寸上应用不同的样式规则,可以让页面呈现出更加灵活的效果。在ESLint的配置文件中, 可以定义代码风格和质量的标准和规则。这些配置可以确保项目的代码风格和质量符合团队的规范,同时还可以提高开发效率。一般来说,可以将相关的页面和组件放在同一个路由下,例如用户管理相关的页面和组件可以放在用户管理的路由下。例如,可以创建一个按钮组件, 该组件可以接受不同的参数来自定义按钮的样式和行为。

weixin_74248177的博客 1076

从零到一:Zephyr RTOS 在 STM32F4 上的移植与实战(含设备树配置详解)

本文详细介绍了如何从零开始将Zephyr RTOS移植到STM32F4开发板,涵盖开发环境搭建、硬件抽象层分析、设备树配置及系统裁剪等关键步骤。通过实战案例,帮助开发者掌握Zephyr RTOS在嵌入式设备中的应用,提升物联网边缘计算设备的开发效率。

weixin_26976635的博客 591

Vue3源码梳理:关于运行时和编译时

上述 v-if 和 m-com 自定义组件不是正常的html, 浏览器是不认识的,所以不会解析。.vue文件是单文件组件, 在template中写入的html是真实的html标记节点么?vue中的编译时,准确来说是编译器的意思,核心代码在 compiler-core模块下。运行时做不到的事情,通过html标签结构的方式来渲染解析成真实的dom节点。初次渲染,会生成一个ul标签,同时生成三个li标签,并把他们挂载到div中。这个过程主要是:让假标记,被渲染成真实的html标签,最终呈现给用户。

Wang的专栏 990

谷歌Gemini模型免费API调用全攻略:从注册到实战(附代码示例)

本文详细介绍了如何免费调用谷歌Gemini模型的API,从注册获取API密钥到实战应用的全过程。内容涵盖环境准备、基础API调用、多模态处理、高级功能及生产环境实践,帮助开发者高效利用Gemini模型进行代码生成和复杂任务处理。附有代码示例,适合AI开发者和技术爱好者。

weixin_29212429的博客 1606

3D点云处理:PointNet++与PointTransformer的对比

摘要: 3D点云处理中,PointNet++和PointTransformer是两种主流深度学习模型。PointNet++通过分层采样和分组策略提取局部特征,而PointTransformer利用自注意力机制捕捉全局上下文。实验表明,PointTransformer在分类(ModelNet40准确率92.1%)和分割(ShapeNet mIoU 85.7%)任务上性能更优,但计算开销较大(训练时间180秒/轮)。PointNet++在实时性场景更具优势(训练时间120秒/轮)。未来可结合两者优势,或优化Tr

shejizuopin的博客 1121

【Vue3】源码解析-Runtime

【Vue3】源码解析-Runtime

欢迎指错||纠正||建议||水评+点赞&&评论&&关注&&转发 1627

正点原子stm32f103RChal库制作数字秒表:如用keil5和正点原子STM32F1开发板实现?

🏆本文收录于 《全栈Bug调优(实战版)》 专栏,该专栏专注于分享我在真实项目开发中遇到的各类疑难Bug及其深层成因,并系统提供高效、可复现的解决思路和实操方案。无论你是刚入行的新手开发者,还是拥有多年项目经验的资深工程师,本专栏都将为你提供一条系统化、高质量的问题排查与优化路径,助力你加速成长,攻克技术壁垒,迈向技术价值最大化与职业发展的更高峰🚀!    📌 特别说明: 文中部分技术问题来源于真实生产环境及网络公开案例,均经过精挑细选与系统化整理,并结合多位一线资深架构师和工程师多年实战经验沉淀,提

**My Coding Family** 1265

带你从0开始了解vue3核心(运行时)

本质上就是在setupComponent(初始化组件实例属性)中判断是否有setup,如果有将执行并将setup返回值作为组件实例render属性的值。其他逻辑和无状态组件挂载一样,在初始化组件实例(setupComponent)时,需要处理状态数据,将其转换成响应式数据。在设置完新vNode的props后,它将再次遍历旧Vnode,删除新Vnode不存在的属性。h函数的执行还是比较简单的,主要就是上面所讲到的问题,搞清楚就没啥问题了。在当前组件挂载后,我们需要将创建出来的dom元素赋值给vnode的。

Web面试那些事儿的博客 1016

一般无穷积分的收敛判别法

文章目录积分里的狄屎判别法证明阿贝尔判别法总结补充:级数中的狄屎和Abel 积分里的狄屎判别法 F(u)=∫auf(x)dx在[a,+∞)F(u)=\int_a^uf(x)dx在[a,+\infty)F(u)=∫au​f(x)dx在[a,+∞)有界 x→+∞时,g(x)单减→0x\to+\infty时,g(x)单减\rightarrow0x→+∞时,g(x)单减→0 ⇒\Rightarrow⇒ ...

universe_1207的博客 1万+

基于 Simulink 的双向 DC/AC 逆变器中 IGBT/MOSFET 寄生参数影响分析实战教程

摘要:本教程详细解析了Simulink中IGBT/MOSFET寄生参数对双向DC/AC逆变器的影响。通过对比理想模型与含寄生参数(如20nH内部电感、50nH回路电感)的仿真,揭示了电压尖峰、高频振荡等实际问题。建模步骤包括搭建基准电路、引入寄生参数、配置高精度求解器(步长10ns),并给出抑制措施:添加RC缓冲电路、调整驱动电阻。关键发现:寄生参数会显著增加开关损耗和EMI噪声,需通过参数扫描优化设计。教程还提供了代数环报错、仿真速度优化等实战技巧,帮助工程师从理想仿真过渡到高保真分析。

xiaoheshang_123的博客 68

Vue3源码梳理:源码目录结构及源码阅读方法

源码目录结构及源码阅读方法

Wang的专栏 2078

柔性电极材料新突破:清华团队实现0.1mV级脑信号采集精度

清华团队的 0.1mV 级柔性电极突破,不仅是材料科学与神经工程的跨界胜利,更标志着脑机接口从 “信号采集” 向 “神经交互” 的范式转变。当电极与脑组织实现 “柔性共生”,人类首次拥有了窥探大脑微观电活动的 “精密探头”,这既是神经疾病诊疗的里程碑,更是人机融合时代的新起点。随着技术标准化与产业生态的完善,这场始于实验室的 “柔性革命”,正加速向临床病房、智能工厂、消费电子等场景渗透,为脑机接口的大规模应用铺设 “柔性跑道”。:当柔性电极实现 “神经信号的无损捕捉”,如何平衡技术创新与伦理边界?

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 2946

Vue2源码梳理:源码构建流程与运行时和编译时的版本选择

在 Vue.js 2.0 中,最终渲染都是通过 render 函数,如果写 template 属性,则需要编译成 render 函数。所以我们写的 .vue 文件在运行的时候已经编译成 js 函数了,并且模板部分已经编译成 render 函数了。很显然,这个编译过程对性能会有一定损耗,所以通常开发阶段更推荐使用 Runtime-Only 的 Vue.js。而 .vue文件 是在编译过程中,通过 vue-loader 处理的。那么这个编译过程会发生运行时,需要带有编译器的版本。打开 .config 文件。

Wang的专栏 1617

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Vue3源码解读--方向篇

vue源码解读

嗨,欢迎来到我的 优快云 博客小天地!一名深耕多年的技术发烧友。在这里,我将把日常工作中积累的宝贵经验,从复杂架构设计的精妙之处,到代码优化的实战技巧,毫无保留地分享给大家。 1679

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Vue3源码梳理:运行时之基于h函数生成vnode的内部流程

h函数本质上是处理一个参数的问题核心代码是在中进行的里面生成vnode的核心方法,做了一件重要的事情是构建了一个shapeFlag第一次构建的时候,它的flag是ELEMENT类型接下来return 了函数它根据typepropschildrenshapeFlag生成了一个 vnode 节点通过按位或运算,来改变flag的值,重新赋值给shapeFlag最终 return vnode 对象。

Wang的专栏 1335

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Vue3源码学习9——运行时+编译时

基于之前的以及,其实Vue3的都梳理完成了,最后要做的一步就是它们,以实现真实Vue3使用时的样子实际使用Vue3的时候,大概是这么用的这里的过程涉及两部分apptemplaterendertemplateapp。

gaotlantis的博客 689

如何阅读vue3源码

摘要:Vue3源码调试与阅读指南 调试Vue3源码的步骤包括:1)从GitHub下载core目录源码,使用pnpm安装依赖;2)新版(3.5.17+)无需开启sourcemap,旧版需修改package.json配置;3)用liveserver运行examples/composition下的demo进行调试。阅读建议关注核心逻辑,重点理解响应性、编译器和运行时三部分。源码位于packages/vue/dist目录,dev命令生成vue.global.js文件供调试使用。

wxiao_xiao_miao的博客 657

从Vue3源码深入理解ref响应式

首先我们要去学习源码,就要对整个项目有一个基本了解,了解每个模块、每个目录的作用,这样对我们后期阅读源码也会有很大的帮助;我们将项目从Github上克隆下来:bash代码解读复制代码如果因为网络问题克隆不下来,点击这个链接获取源码;笔者克隆下来时,当前版本号为3.5.12。我们看到整个项目的目录还是非常多的,又有编译时,又有运行时的目录,主要的代码都存放在packages目录,因此我们主要看下它下面的目录结构:bash代码解读复制代码。

qq_66118130的博客 1020

视频教程-前端工程师就业班VueJS基础+去哪儿网实战+源码讲解【JS++前端】-Vue

前端工程师就业班VueJS基础+去哪儿网实战+源码讲解【JS++前端】 一线...

weixin_31289685的博客 1007

Vue3源码 第一篇-总览

Vue3源码总览 文章目录Vue3源码总览前言一、从哪里搞到源码?二、开始学习1.准备所需文件,并且引入Vue32.如何读源码3.Vue.createApp()3.1 ensureRenderer()总结 前言 之前读过Vue2的源码,所以Vue3源码发布后就迫不及待的赶紧下载下来读了读,对比Vue2的源码还是有许多改变,但是对Vue2源码有所了解还是比较好读的,我自己也是一边读代码一边记笔记,把自己的一些笔记和想法分享在这里,如果有错误的地方希望大佬斧正,废话不多说,开冲~~ 提示:以下是本篇文章

不忘初心 1714

探索Vue.js核心:手写Vue3源码(mini版)

探索Vue.js核心:手写Vue3源码(mini版) 项目介绍 你是否曾经好奇过Vue.js是如何工作的?你是否想要深入了解Vue3的内部机制?如果是,那么这个开源项目——Vue-源码实现(mini版),正是为你量身定制的。这个项目不仅提供了详细的代码注解,还配备了丰富的文章讲解,帮助你一步步理解Vue3的核心实现。 通过这个项目,你将能够清晰地看到Vue3的运行流程,从响应式系统的实现到Vue应...

gitblog_00544的博客 381

Vue3源码之createApp

前言 Vue3版本源码架构与Vue2版本存在非常大的不同,从使用方式的角度来讲,对它们可以简单概括为: Vue2版本是命令方式使用,通过new Vue去创建Vue实例,组件中使用选项组合代码逻辑 Vue3版本将命令和功能API函数化,通过createApp去创建应用实例,组件中通过组合式API和选项组合代码 这里需要区分与Vue2中的一些概念,Vue2中Vue实例实际上就是组件实例,而Vue3中createApp则是创建一个上下文,称之为应用实例。组件实例是通过其他方式来获得的,例如Vue3中mount

玉案轩窗的博客 1万+

3.为什么我的vue数据修改后视图未更新,梳理Vue2和Vue3中常见的数据不更新场景

Vue数据不更新问题的核心在于响应式机制的实现。Vue2受限于Object.defineProperty,需通过辅助方法(如$set)弥补不足;而Vue3通过Proxy提供了更完善的响应式支持。无论是Vue2还是Vue3,理解其原理并遵循“数据驱动视图”的原则,配合最佳实践,都能有效避免视图更新异常。

qq_1401820561的博客 2683

Vue3源码梳理:watch监听函数的核心实现

watch 可以监听响应式数据的变化,从而触发指定的函数watch 函数监听三个参数监听的响应式对象回调函数 cb配置对象 optionsimediate: 初始化完成后会被立刻触发一次deep: 深度监听测试示例: watch.html,测试vue源码的watch函数name : '张三' }) watch(obj ,(val , oldVal) => {clearTimeout(timer) obj . name = '李四' } , 2000)

Wang的专栏 2154

Vue3源码梳理:computed计算属性的核心实现

计算属性 computed 会基于其响应式依赖被缓存,并且在依赖的响应式数据发生变化时,重新计算测试示例: computed.html,测试vue源码的属性name : '张三' }) const computedObj = computed(() => {return '姓名: ' + obj . value . name }) effect(() => {clearTimeout(timer) obj . value . name = '李四' } , 2000)

Wang的专栏 1304
上一篇: Vue3源码梳理:响应式系统的前世今生
下一篇: Vue3源码梳理:运行时之基于h函数生成vnode的内部流程
Wang's Blog
博客等级 码龄12年 7433粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值