前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • Vue

    • 从源码解读Vue生命周期
    • 组件的本质
    • 有状态组件的设计
    • 设计 VNode
    • 辅助创建 VNode 的 h 函数
    • 自定义渲染器和异步渲染
    • 渲染器之挂载
    • 渲染器的核心 Diff 算法
    • 渲染器之patch
    • 图解 Vue 响应式原理
    • 图解 Vue 异步更新
    • 剖析 Vue 内部运行机制
    • vue响应式原理模拟
    • vue状态管理之vuex
    • 理解Vue的设计思想及实现Vue
    • diff算法深入
    • vue router vuex原理分析
    • Vue3初探响应式原理.
    • vue2源码分析
    • vue组件化实践
  • React

  • Webpack

  • Node

  • Javascript

  • 综合

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

前端面试之MVVM浅析|原理篇

文章学习导航
面试总览

30 秒速记

  • 核心判断:响应式系统由依赖收集、变更触发和调度刷新组成,关键不在“监听数据”,而在精确关联状态与副作用
  • 原理主线:围绕 「一、说一下使用 jquery 和使用框架」、「二、说一下对 MVVM 的理解」、「三、vue 中如何实现响应式」 建立输入、状态变化与输出之间的因果关系
  • 文章范围:浅出地分析了前端开发中MVVM模式的原理,比较了jQuery与现代前端框架的区别,详细讲解了MVC与MVVM的结构、核心概念及其在前端开发中的应用,帮助读者理解数据驱动视图和响应式开发的优势。
  • 边界与代价:Vue 2 的 defineProperty 与 Vue 3 的 Proxy 在新增属性、数组和集合类型上边界不同
  • 工程落地:排查视图不更新或重复更新时,应沿读取是否被追踪、写入是否触发、任务是否被去重三段定位

MVVM 通过 ViewModel 连接数据和视图,让开发者更新状态而不是手动操作 DOM。 模板会先被编译成 render 函数,执行后生成 vnode;首次渲染读取响应式属性时完成依赖收集。属性被修改后,响应式的 set 触发重新渲染,再由 patch 对比新旧 vnode 并更新页面。监听 get 的意义是只关联真正被视图使用的数据,避免无关状态变化也触发重复渲染。

这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。

版本校准: 原理文章中的代码代表特定实现与写作时间。应用到当前项目时,应先确认浏览器、框架或工具的主版本,再区分稳定的规范语义、可变化的内部实现和项目自身约束。

img

# 一、说一下使用 jquery 和使用框架的区别

# 1.1 jQuery 实现 todo-list

img

# 1.2 vue 实现 todo-list

img

# 1.3 jQuery 和框架的区别

  • 数据和视图的分离,解耦(开放封闭原则)
  • 以数据驱动视图,只关心数据变化,DOM 操作被封装

# 二、说一下对 MVVM 的理解

# 2.1 MVC

  • M - Model 数据
  • V - View 视图、界面
  • C - Controller 控制器、逻辑处理

img img

# 2.2 MVVM

  • Model - 模型、数据
  • View - 视图、模板(视图和模型是分离的)
  • ViewModel - 连接 Model 和 View

img

# 2.3 关于 ViewModel

  • MVVM 不算是一种创新
  • 但其中的 ViewModel 确实一种创新
  • 真正结合前端场景应用的创建

img img

# 2.4 MVVM 框架的三大要素

  • 响应式:vue如何监听到 data 的每个属性变化?
  • 模板引擎:vue 的模板如何被解析,指令如何处理?
  • 渲染:vue 的模板如何被渲染成 html ?以及渲染过程

# 三、vue 中如何实现响应式

# 3.1 什么是响应式

  • 修改 data 属性之后,vue 立刻监听到
  • data 属性被代理到 vm 上

img

# 3.2 Object.defineProperty

img

# 3.3 模拟实现

img

img

# 四、vue 中如何解析模板

# 4.1 模板是什么

  • 本质:字符串
  • 有逻辑,如 v-if v-for 等
  • 与 html 格式很像,但有很大区别
  • 最终还要转换为 html 来显示

模板最终必须转换成 JS 代码,因为

  • 有逻辑(v-if v-for),必须用 JS才能实现
  • 转换为 html 渲染页面,必须用 JS 才能实现
  • 因此,模板最重要转换成一个 JS 函数(render 函数)

img

# 4.2 render 函数

  • 模板中所有信息都包含在了 render 函数中
  • this 即vm
  • price 即 this.price 即 vm.price,即 data 中的 price
  • _c 即 this._c 即 vm._c

img

img

img

# 4.3 render 函数与 vdom

  • vm._c 其实就相当于 snabbdom中的 h 函数
  • render 函数执行之后,返回的是 vnode

img

img

  • updateComponent中实现了 vdom 的 patch
  • 页面首次渲染执行 updateComponent
  • data 中每次修改属性,执行updateComponent

# 五、vue 的整个实现流程

  • 第一步:解析模板成 render 函数
  • 第二步:响应式开始监听
  • 第三步:首次渲染,显示页面,且绑定依赖
  • 第四步:data 属性变化,触发 rerender

img

# 5.1 第一步:解析模板成 render 函数

img

img

img

img

  • 模板中的所有信息都被 render函数包含
  • 模板中用到的 data 中的属性,都变成了 JS 变量
  • 模板中的v-model v-for v-on 都变成了 JS 逻辑
  • render 函数返回 vnode

# 5.2 第二步:响应式开始监听

  • Object.defineProperty
  • 将 data 的属性代理到 vm上

img

# 5.3 第三步:首次渲染,显示页面,且绑定依赖

  • 初次渲染,执行 updateComponent,执行 vm._render()
  • 执行 render 函数,会访问到 vm.list vm.title
  • 会被响应式的 get 方法监听到
  • 执行 updateComponent ,会走到 vdom 的 patch 方法
  • patch 将 vnode渲染成 DOM ,初次渲染完成

img img

为何要监听 get ,直接监听 set 不行吗?

  • data 中有很多属性,有些被用到,有些可能不被用到
  • 被用到的会走到 get ,不被用到的不会走到 get
  • 未走到 get 中的属性,set的时候我们也无需关心
  • 避免不必要的重复渲染

img

# 5.4 第四步:data 属性变化

img img

  • 修改属性,被响应式的 set 监听到
  • set中执行 updateComponent
  • updateComponent 重新执行 vm._render()
  • 生成的 vnode 和 prevVnode ,通过 patch进行对比
  • 渲染到 html 中

img

面试官追问

追问 1商品详情页修改一个已响应式化的价格字段后,控制台值已变化,但有人说浏览器会直接改对应 DOM;这条解释漏掉了哪些环节?
参考回答

属性写入先被响应式 set 捕获,再触发 updateComponent,由 vm._render() 生成新的 vnode。随后新旧 vnode 经 patch 对比才落实到 HTML;数据变化并不意味着绕过虚拟节点直接操作目标 DOM。

追问 2表格页一次更新 300 行状态,工程师准备在每个 set 中手写 document.querySelector 更新单元格,你会如何基于现有渲染链路反驳?
参考回答

响应式写入应沿 set、updateComponent、vm._render() 和 patch 的既有链路更新页面,无需为每个字段另建命令式 DOM 通道。手写更新会形成第二套状态来源,容易与下一次虚拟节点渲染互相覆盖,规模增大后维护代价更高。

追问 3仪表盘原来只改一个字段,现在一次提交会改 50 个字段;如果每次 set 都立即完整执行 updateComponent,你最担心什么?
参考回答

最直接的风险是同一轮连续写入引发重复渲染和多次新旧 vnode 对比,产生无必要的工作。源码小结只给出了触发链路,没有说明批处理策略,因此实现时应确认是否存在调度与合并机制,不能仅凭该段断言具体执行次数。

追问 4线上反馈筛选条件已经变化但列表还是旧内容,你会沿 set 到 patch 的链路怎样定位断点?
参考回答

先验证目标属性是否确实经过响应式 set,再观察 updateComponent 与 vm._render() 是否执行,并比较生成的 vnode 是否包含新列表。若虚拟节点正确而页面未变,再查 patch 对比与落地;若虚拟节点已旧,问题更可能在状态读取或渲染逻辑。

追问 5组件负责人想在数据变化后整页重建 HTML,另一人坚持走 vnode 对比;在一个交互频繁的列表页里你怎么取舍?
参考回答

既有机制会生成新 vnode 并与 prevVnode 通过 patch 对比,因此应优先沿这条链路做增量更新。整页重建虽然实现直观,却放弃了差异比较,还可能破坏页面中的局部交互状态;只有脱离该渲染体系时才需另行评估。

← 浏览器渲染原理前端面试之组件化 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • Vue

    • 从源码解读Vue生命周期
    • 组件的本质
    • 有状态组件的设计
    • 设计 VNode
    • 辅助创建 VNode 的 h 函数
    • 自定义渲染器和异步渲染
    • 渲染器之挂载
    • 渲染器的核心 Diff 算法
    • 渲染器之patch
    • 图解 Vue 响应式原理
    • 图解 Vue 异步更新
    • 剖析 Vue 内部运行机制
    • vue响应式原理模拟
    • vue状态管理之vuex
    • 理解Vue的设计思想及实现Vue
    • diff算法深入
    • vue router vuex原理分析
    • Vue3初探响应式原理.
    • vue2源码分析
    • vue组件化实践
  • React

  • Webpack

  • Node

  • Javascript

  • 综合