图解 Vue2 diff 算法:首尾四向对比核心逻辑全拆解, 告别死记硬背八股文
这是Vue从入门到精通系列文章的第13篇,上一篇文章中提到了虚拟DOM, 今天花点时间重点讲讲里面非常核心的内容–diff算法。 很多人在看到这一块的时候都感觉头大,但为了面试还是硬着头皮去背那些八股文。与其花时间背八股文,不如克服畏难心里,跟着我一起来看看diff算法的奥秘,它是否又真的有那么难。 讲diff算法首先我们需要明确一个问题,它是为了解决什么问题才引入了。前文我们提到为了解决直接减少直接操作原生DOM引入了虚拟DOM,当数据变化时,Vue 会生成新的虚拟 DOM(VNode),然后通过 Diff 算法对比新旧 VNode,只把真正变化的部分更新到真实的网页上,而不是推倒重来。 是的,这就是为什么引入diff算法 原因– 解决 DOM 操作带来的“昂贵”代价, 而不是给你增加面试难度。 Vue中的diff算法也不是从石头里蹦出来的,也不是尤大从睡一觉从梦中得到灵感想出来。Vue 在 2.0 版本引入虚拟 DOM 时,并没有从零开始写算法,而是深度借鉴了一个名为 Snabbdom 的轻量级库,它引入了著名的 双端 Diff 算法,而这也是本文要讲的重点。 diff算...
原生 DOM 真的慢吗?为什么现代框架都迷恋虚拟 DOM?
这是Vue从入门到精通系列文章的第12篇,今天我们来说说虚拟DOM吧。 根据过去该系列文章的阅读数我发现,大家不太爱看有大段代码的文章,所以这次也就不做这一块的代码剖析,有兴趣的读者可下载源码慢慢品味。 什么是虚拟DOM? 怎么出现的?虚拟DOM也不是什么高大上的东西,它本质上就是个普通的 JavaScript 对象,它既不是什么高深的黑科技,也不是多此一举的冗余设计,而是前端工程师为了解决“原生 DOM 太矫情”的破局方法。 为啥说原生 DOM 矫情?因为直接操作它的成本实在太高了。为什么这么说呢?因为浏览器里的 DOM 不仅是个节点,还关联着布局、样式等一堆资源,每次修改 DOM 都可能触发“重排”或“重绘”这俩操作就像让餐厅重新装修再上菜,耗时又耗力。 在简单页面里还好,一旦遇到复杂应用——比如一个带大量列表、表单和实时更新的后台系统,光是找DOM节点就得写一堆getElementBy方法,不仅容易出错,维护起来更是让人头大。虚拟 DOM 的出现,就是为了帮我们“隔离开”这种繁琐又昂贵的直接操作。 说白了,就是操作原生DOM太费劲了,我直接找中间商来干这活,而虚拟DOM就是...
Vue进阶系列第11篇--说说你对vue的mixin的理解,它的本质是什么?有什么应用场景?
这是Vue从入门到精通系列文章的第11篇,今天来讲讲Vue2中已经弃用的一个特性–Mixin。Mixin 在Vue2 版本中扮演者非常重要的角色,很多 Hack 技巧和代码的复用上都依赖着Mixin。虽然 Vue3版本弃用了,但是,法拉利老了还是法拉利,一起来认识一下吧。 Mixin是什么咱们先说说Mixin到底是啥——它是面向对象编程里的一种类,里面装着能重复用的方法。其他类不用费劲继承这个Mixin类,就能直接拿过来用它里面的方法,特别方便。 Mixin类一般就是个独立的功能模块,咱们需要用这个功能的时候,把它“混”进需要的地方就行。这样既能重复用代码、少写冗余内容,又不会有多重继承那种绕来绕去的复杂问题,简直是双赢。 Vue中的Mixin先看Vue官方的定义,说白了就是:mixin(混入),是种特别灵活的方式,能把Vue组件里那些能重复用的功能,单独抽出来分发。 它本质就是个JS对象,里面能放组件里的各种功能,比如data、components、methods、created、computed这些,你想放啥功能都能放。咱们只要把多个组件都要用的功能,写成一个对象,塞进mix...
Vue进阶系列第10篇--nextTick 工作原理揭秘:附核心代码实现与解析
不出意外这应该是2025年该公众号更新的最后一篇文章,在这里感谢大家的关注与陪伴。愿大家新的一年代码零 bug,接口全 200,升职加薪,一路开挂。 这是Vue从入门到精通系列文章的第10篇,在上一篇文章中讲了Vue中的nextTick的定义和几种使用场景,今天我们结合源码来说说nextTick的原理和实现。 nextTick 的源码在 Vue 项目的 /src/core/util/next-tick.js 里,核心逻辑不复杂,咱们拆解开来讲,不用怕看不懂。 核心变量和函数首先有几个关键东西: callbacks:就是咱们说的“异步操作队列”,所有通过 nextTick 传入的回调函数,都会被放进这个数组里。 pending:一个标识位,用来保证同一时间只执行一次异步任务,避免重复执行。 timerFunc:核心函数,用来决定用什么方式执行异步任务(会做降级处理)。 flushCallbacks:用来执行 callbacks 队列里所有回调函数的函数。 nextTick 核心函数逻辑咱们先看 nextTick 函数的核心代码(保留关键逻辑,去掉冗余注释): 123...
Vue进阶系列第9篇--你真的懂nextTick吗?我表示很怀疑
这是Vue从入门到精通系列文章的第9篇,今天我们来讲讲Vue中的nextTick的定义和几种使用场景,下一篇单独开一篇讲解它的实现原理。 为什么我会对nextTick“情有独钟“呢,这里还有一个小故事。记得最早接触前端开发解除Vue的时候,由于自己属于看了2周Vue官方文档就开始写业务的半路出家和尚,编程能力属于菜狗都算不上那种。 有一次有个业务逻辑是需要再页面更新之后才进行数据变更的,当时哪知道有nextTick这么牛而x之的函数,直接一个setTimeout, 不出意外项目上线后bug时隐时现,最后排查到了是这里有错,当时带我的导师给我指出问题时,咱脸上火辣辣的,哈哈。 言归正传,怎么来讲讲 nextTick吧,以后故事慢慢讲。 nextTick是什么?官方定义(不是我瞎写的哈)官方给出的说法是:nextTick 会在下次 DOM 更新循环结束之后,执行我们传入的延迟回调。简单说就是,当我们修改了 Vue 数据之后,要是想立刻拿到更新后的 DOM 元素,就可以用这个方法。 通俗理解很多刚学 Vue 的朋友可能会有疑问:我明明改了数据,怎么打印 DOM 内容还是旧的?其实核心原...
Vue进阶系列第8篇--Vue组件间通信方式都有哪些?
今天内容略粗糙(码字有点累),而且知识点有点多,不想看全文的可以直接看总结,浓缩的就是精华。 这是Vue从入门到精通系列文章的第8篇,今天我们来讲讲Vue面试必问的一个问题–Vue组件间通信方式都有哪些? 一、组件间通信的概念开始之前,我们先把“组件间通信”这个词拆开来理解: • 组件• 通信 我们都知道,组件是Vue最强大的功能之一,Vue中每一个.vue文件都可以视作一个独立组件。而通信,指的是发送者通过某种媒介、以某种格式将信息传递给接收者,从而达成特定目的——广义来讲,任何信息的交互都属于通信。 所以,组件间通信就是指各个.vue组件通过某种方式传递信息,进而实现特定业务需求。举个例子,我们使用UI框架中的Table组件时,常会往组件里传入数据,这一操作的本质,就是组件间在进行通信。 在Vue中,每个组件都有自己独立的作用域,组件间的数据默认是无法共享的,但实际开发中,我们经常需要让不同组件共享数据、协同工作——这就是组件通信要解决的核心问题。只有让组件间能顺畅通讯,才能搭建出一个有机、完整的前端系统。 二、组件间通信的分类组件间通信主要可分为以下几类: • 父子组...
Vue进阶系列第7篇--对象添加属性之后页面没有刷新,怎么回事?
这是Vue从入门到精通系列文章的第7篇,今天我们来讲讲Vue中非常常见的一个问题:给对象添加属性之后页面没有刷新。 在Vue开发的时候,很多开发者都会碰到这样的问题:直接给响应式对象加新属性后,数据本身已经更新了,但页面却没跟着刷新。 这不是Vue的漏洞,而是它的响应式系统底层工作方式导致的。这篇文章会从问题根源入手,分别讲Vue2和Vue3两个版本的解决办法,还会补充一些常见的注意点。 核心原因:响应式系统的检测局限Vue的响应式核心是监听对象属性的读取(get)和修改(set)操作,通过这种监听实现数据和页面的联动。但不同版本的监听方式有差异,都没法直接监测到“新增属性”这个操作: Vue2 的局限:Vue2用Object.defineProperty这个API来监听属性。组件初始化的时候,Vue会逐个遍历data里的所有对象属性,给它们加上getter和setter监听逻辑。而初始化之后新增的属性,没法自动加上这套监听逻辑,所以属性变化的时候不会触发监听,自然也就不会让页面刷新。 Vue3 的局限:Vue3换成了Proxy来代理整个对象,理论上能监听更多操作,但默认情况...
Vue进阶系列第6篇:Vue实例生命周期详解--组件从创建到销毁的全过程
这是Vue从入门到精通系列文章的第6篇,今天我们来谈谈剖析一下Vue实例的生命周期。这里我们讲Vue2版本的,Vue3版本生命周期的解析我回放在Vue3对应的专题下面。 Vue2里的每个组件,都有一段从创建到销毁的完整“生命周期”。就像一个东西从生产出来到最终报废,不同阶段有不同的状态,Vue2在这些关键阶段都设置了“钩子函数”,让我们能在合适的时机做该做的事。 一、创建阶段:组件的“初始化”这个阶段是组件从无到有的过程,核心是把数据、方法这些基础东西准备好,还没和页面上的DOM产生关联。 1. beforeCreate组件实例刚被创建出来,就像一个空架子——data里的数据、methods里的方法都还没初始化,这时候用this也拿不到这些东西。这个钩子基本用不上,只能做些和组件实例没关系的简单操作。 2. created这时候组件的“核心功能”已经就绪了:响应式数据、方法、侦听器都初始化好了,用this能直接访问this.msg、this.getData()这些。但DOM还没生成,this.$el是undefined。这个阶段最适合做异步数据请求、处理路由参数、初始化全局变...
Vue进阶系列第5篇--Vue实例挂载的过程中发生了什么?
大家好,我是jvxiao。 这是Vue从入门到精通系列文章的第5篇,今天我们来谈谈剖析一下Vue实例挂载过程中发生了什么。 Vue实例(也可以叫组件)的挂载,说到底就是把我们写的Vue代码,变成页面上能看到、能交互的真实元素的过程。这个过程看似复杂,其实一步步拆解开,都是很朴素的逻辑,尤其是我们常用的Vue 3(比如Nuxt 3背后的核心),挂载流程更是清晰明了。 一、创建应用实例在Vue 3里,没有以前那种全局的Vue实例了,而是用createApp函数来创建一个应用实例。比如说我们导入根组件App.vue后,调用createApp(App),就相当于搭好了一个项目的“架子”。 这个架子里会包含全局配置,比如我们注册的全局组件、自定义指令这些,但这时候还没和页面上的任何元素产生关联,只是一个单纯的配置集合。我们可以在这个阶段给架子添点东西,比如注册全局能用的按钮组件,或者定义一个全局指令,这些都会在后续挂载时生效。 二、调用mount方法接下来就是触发挂载的关键一步——调用mount方法。我们会把mount绑定到页面上一个指定的DOM元素上,通常是#app,比如app.moun...
Vue进阶系列第4篇-- v-show 和 v-if 的实用解析:搞懂用法,选对场景
大家好,我是jvxiao。 这是Vue从入门到精通系列文章的第3篇,今天我们说的是Vue中的两个指令–v-show和v-if。 在 Vue 开发里,控制元素显示或隐藏是很常见的需求,而 v-show 和 v-if 就是专门干这个活的两个核心指令。它们俩目标一致,都是根据条件(比如一个布尔值、返回布尔值的表达式)来决定元素要不要“露脸”,但用法、原理和适用场景却大不相同。如果用错了,可能会影响页面性能,甚至出现意想不到的问题,今天就把这两个指令的来龙去脉说清楚。 两者的共同点:目标一致,核心功能相同不管是 v-show 还是 v-if,本质上都是“条件渲染工具”。简单说,就是你给它们一个“判断标准”,比如“用户是不是管理员”“开关是不是打开的”,它们就会按照这个标准,决定元素该显示还是隐藏。 比如想让一个按钮只在用户是管理员时显示,用 v-if 可以,用 v-show 也可以(只是背后逻辑不一样),代码写法都很简单: 1234<!-- 用 v-if 实现管理员按钮显示 --><button v-if="isAdmin">删除数据<...