8.2.2 Vue.js 源码剖析-虚拟 DOM

本文深入剖析 Vue.js 源码中的虚拟 DOM,包括虚拟 DOM 的概念、使用原因、在 Vue 中的应用,以及关键函数如 createElement、update 和 patch 的工作原理。讲解了虚拟 DOM 如何提高开发效率并实现跨平台,以及在更新过程中如何通过 Diff 算法减少 DOM 操作,强调了 key 在优化更新过程中的作用。
摘要由CSDN通过智能技术生成

本文为拉勾网大前端高薪训练营第一期笔记


8.2.2 Vue.js 源码剖析-虚拟 DOM

虚拟 DOM 回顾

什么是虚拟 DOM

虚拟 DOM(Virtual DOM) 是使用 JavaScript 对象来描述 DOM,虚拟 DOM 的本质就是 JavaScript 对
象,使用 JavaScript 对象来描述 DOM 的结构。应用的各种状态变化首先作用于虚拟 DOM,最终映射
到 DOM。Vue.js 中的虚拟 DOM 借鉴了 Snabbdom,并添加了一些 Vue.js 中的特性,例如:指令和组
件机制。

Vue 1.x 中细粒度监测数据的变化,每一个属性对应一个 watcher,开销太大Vue 2.x 中每个组件对应一个 watcher,状态变化通知到组件,再引入虚拟 DOM 进行比对和渲染

为什么要使用虚拟 DOM

使用虚拟 DOM,可以避免用户直接操作 DOM,开发过程关注在业务代码的实现,不需要关注如
何操作 DOM,从而提高开发效率
作为一个中间层可以跨平台,除了 Web 平台外,还支持 SSR、Weex。
关于性能方面,在首次渲染的时候肯定不如直接操作 DOM,因为要维护一层额外的虚拟 DOM,
如果后续有频繁操作 DOM 的操作,这个时候可能会有性能的提升,虚拟 DOM 在更新真实 DOM
之前会通过 Diff 算法对比新旧两个虚拟 DOM 树的差异,最终把差异更新到真实 DOM

Vue.js 中的虚拟 DOM

演示 render 中的 h 函数

h 函数就是 createElement()

vm.$createElement(tag, data, children, normalizeChildren)

tag: 标签名称或者组件对象

data: 描述tag,可以设置DOM的属性或者标签的属性

children: tag中的文本内容或者子节点

VNode

核心属性

  • tag
  • data
  • children
  • text
  • elm
  • key
const vm = new Vue({
  el: '#app',
  render(h) {
    // h(tag, data, children)
    // return h('h1', this.msg)
    // return h('h1', { domProps: { innerHTML: this.msg } }) 
    // return h('h1', { attrs: { id: 'title' } }, this.msg) 
    const vnode = h(
      'h1', {
      attrs: { id: 'title' }
    },
      this.msg)
    console.log(vnode)
    return vnode
  },
  data: {
    msg: 'Hello Vue'
  }
})

虚拟 DOM 创建过程分析

在这里插入图片描述在这里插入图片描述

createElement

功能

createElement() 函数,用来创建虚拟节点 (VNode),我们的 render 函数中的参数 h,就是
createElement()

render(h) {
	// 此处的 h 就是 vm.$createElement 
	return h('h1', this.msg)
}

定义

在 vm._render() 中调用了,用户传递的或者编译生成的 render 函数,这个时候传递了 createElement

  • src/core/instance/render.js
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
// normalization is always applied for the public version, used in
// user-written render functions.
vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)

vm._c和vm.$createElement都调用createElement,区别只有最后一个参数

  • src/core/vdom/create-element.js

执行完 createElement 之后创建好了 VNode,把创建好的 VNode 传递给 vm._update() 继续处理

export function createElement(
  context: Component,
  tag: any,
  data: any,
  children: any,
  normalizationType: any,
  alwaysNormalize: boolean
): VNode | Array<VNode> {
  // 判断第三个参数
  // 如果 data 是数组或者原始值的话就是 children,实现类似函数重载的机制 
  if (Array.isArray(data) || isPrimitive(data)) {
    normalizationType = children
    children = data
    data = undefined
  }
  if (isTrue(alwaysNormalize)) {
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值