new Vue的时候到底做了什么

Vue的加载涉及实例创建、数据监测、模板解析、虚拟DOM与真实DOM的交互。在初始化阶段,Vue实例化后创建并挂载Vnode,数据变化时,通过watcher监听并触发DIFF算法进行高效更新。DIFF算法通过对比新旧虚拟DOM,精确更新DOM,提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vue加载流程

1.初始化的第一阶段是Vue实例也就是vm对象创建前后:首先Vue进行生命周期,事件初始化发生在beforeCreate生命周期函数前,然后进行数据监测和数据代理的初始化,也就是创建vm对象的过程,当vm对象创建完成就可以通过vm对象访问到劫持的数据,比如data中的数据,methods中的方法等。然后Vue调用内部的render函数开始解析模板将其解析为一个JS对象也即在内存中生成虚拟DOM也就是Vnode对象。第二阶段是vm对象挂载前后:挂载完成前页面呈现的是未经过Vue编译的DOM结构,所有对DOM的操作最终都不会生效。挂载前首先将内存中的Vnode转换为真实DOM插入页面,此时完成挂载。页面中呈现的就是经过Vue编译的DOM结构,至此初始化过程结束。

2.开启订阅消息也就是数据劫持代理监听,其实就是写了一个watcher函数去监听数据的改变,发送网络请求,绑定自定义事件等初始化操作。当数据发生变化以后即状态变更的时候,会重新构造新的Vnode对象。然后用新的Vnode对象和旧的Vnode对象进行差异比较也就是DIFF算法,然后把差异应用到旧的Vnode对象所构建的真正的DOM树上这个过程就是patch,视图就更新了

每一个组件在加载时都会调用Vue内部的render函数把该组件的tamplate选项的模板解析为一个JS对象,这个对象和DOM节点对象结构一样,然后是数据劫持代理监听,当数据发生变化以后,将旧Vnode对象和生成的新Vnode对象比较差异然后更新DOM

Vnode: {
tag:"", 
id:, 
name:"Box", 
$el:真实页面上的DOM的引用, 
//等等属性 
chiren:[ 
{ tag:"", 
id:, 
name:"Box2",
$el:真实页面上的DOM的引用, 
//等等属性 }, 
{ 
tag:"", 
id:, 
name:"Box3",
$el:真实页面上的DOM的引用,
//等等属性 }
] }

life.png

什么是DIFF

diff算法是一种对比算法。对比两者是旧虚拟DOM和新虚拟DOM,对比出是哪个虚拟节点更改了,找出这个虚拟节点,并只更新这个虚拟节点所对应的真实节点,而不用更新其他数据没发生改变的节点,实现精准地更新真实DOM,进而提高效率

其有两个特点:

  • 比较只会在同层级进行, 不会跨层级比较
  • 在diff比较的过程中,循环从两边向中间比较

image.png

DIFF算法的过程:参考 前端进阶面试题详细解答

  • 当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁

  • 通过isSameVnode进行判断,相同则调用patchVnode方法

  • patchVnode做了以下操作:

    • 找到对应的真实dom,称为el
    • 如果都有都有文本节点且不相等,将el文本节点设置为Vnode的文本节点
    • 如果oldVnode有子节点而VNode没有,则删除el子节点
    • 如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el
    • 如果两者都有子节点,则执行updateChildren函数比较子节点
  • updateChildren主要做了以下操作:

    • 设置新旧VNode的头尾指针
    • 新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程、调用createElem创建一个新节点,从哈希表寻找 key一致的VNode 节点再分情况操作

QQ图片20220907150015.png

关于Vue中el,template,render,$mount的渲染

  • 渲染根节点:

    • 先判断有无el属性,有的话直接获取el根节点,没有的话调用$mount去获取根节点。
  • 渲染模板:

    • 有render:这时候优先执行render函数,render优先级 > template。
    • 无render:有template时拿template去解析成render函数的所需的格式,并使用调用render函数渲染。无template时拿el根节点的outerHTML去解析成render函数的所需的格式,并使用调用render函数渲染

渲染的方式:无论什么情况,最后都统一是要使用render函数渲染

`new Vue` 是用于创建一个 Vue 实例的关键语法。通过这个实例,你可以初始化和管理基于 Vue.js 框架的应用程序或组件。下面是对它的详细解析: ### 1. 基本形式 ```javascript new Vue({ // 配置选项 }) ``` 当你执行 `new Vue({...})` 时,Vue 会依据传入的对象配置生成一个新的应用实例,并将指定的模板挂载到页面上。 --- ### 2. 主要配置项解释 - **el**: - 类型:字符串 (CSS选择器) - 功能:绑定 DOM 元素作为 Vue 应用的作用域区域。例如,`el: '#app'` 表明此 Vue 实例将会接管 HTML 页面中 ID 为 app 的 div 区块。 - **data**: - 类型:对象 | 函数(当在一个组件内使用时) - 功能:包含所有需要被响应的数据属性。如: ```javascript data() { return { message: 'Hello World' } } ``` - **methods**: - 类型:对象 - 功能:定义一些可以在事件触发或其他地方调用的方法函数。比如点击按钮改变文本可以这么写: ```javascript methods:{ changeMessage(){ this.message = "Changed Message"; } } ``` - **computed**: - 类型:对象 - 功能:计算属性,基于已有数据动态派生新值并且自动缓存更新后的状态除非关联依赖发生变动。相比于普通 method 来说更高效简洁。 - **watch**: - 类型:对象 - 功能:监听特定数据的变化然后出反应,允许开发者添加副作用操作等复杂逻辑。 --- ### 简单示例 假设有一个简单的网页想要打印消息以及修改该消息的功能,则可以用如下代码实现: ```html <div id="example"> {{ message }} <button @click="reverseMessage">反转消息</button> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2"></script> <script> var vm = new Vue({ el: '#example', data: function () { return {message:"原始信息"} }, methods:{ reverseMessage:function(){ var words=this.message.split(''); this.message=words.reverse().join(''); } } }); </script> ``` 这里我们先引入了官方提供的 CDN 版本库文件加载完毕后再编写脚本来完成交互需求。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值