沐游虞笔记
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 前端面试题

    • HTML面试题汇总(无答案)
    • HTML面试题汇总
    • CSS 面试题汇总(无答案)
    • CSS 面试题汇总
    • javascript 面试题汇总(无答案)
    • javascript 面试题汇总
    • promise 面试题(无答案)
    • promise 面试题
    • 浏览器面试题汇总(无答案)
    • 浏览器面试题汇总
    • 网络面试题汇总(无答案)
    • 网络面试题汇总
    • 工程化面试题汇总(无答案)
    • 工程化面试题汇总
    • VUE面试题汇总(无答案)
    • VUE面试题汇总
  • 直播课文件

    • 静态页面学习指导
    • 属性的计算过程
    • 层叠继承规则总结
    • BFC
    • JS基础知识回顾
    • DOM 事件的传播机制
    • DOM 事件的注册和移除
    • 阻止事件默认行为
    • 基础领航考试题
    • 基础领航考试题(答案)
    • 2024前端发展
    • JS核心概念学习指导
    • 第三方库与工程化学习指导
    • Vue入门学习指导
    • vue进阶学习指导
    • 前端性能优化
  • 笔面试环节知识讲解

    • 目录
    • 图像处理
    • 图像处理(面试)
    • Webpack构建优化
    • Webpack构建优化(面试)
    • TTS性能优化
    • TTS性能优化(面试)
    • 实时协作
    • 实时协作(面试)
    • 网页复制图片到剪贴板
    • 网页复制图片到剪贴板(面试)
    • vite插件
    • vite插件(面试)
    • 表单数据同步与保持
    • 表单数据同步与保持(面试)
    • 优化虚拟列表
    • 优化虚拟列表(面试)
    • 微前端解决巨石应用
    • 微前端解决巨石应用(面试)
    • DNS解析与优化
    • DNS解析与优化(面试)
    • 前端监控
    • 前端监控(面试)
    • 12.跨标签页通信
    • 12.跨标签页通信(面试)
    • 13.Vite相关优化
    • 13.Vite相关优化(面试)
    • 14.计时器节流问题
    • 14.计时器节流问题(面试)
    • 15.多文件预览支持
    • 15.多文件预览支持(面试)
    • 16.defer优化白屏时间
    • 16.defer优化白屏时间(面试)
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
  • 渲染器核心功能
  • 事件绑定与更新
  • computed面试题
  • watch面试题
  • 图解双端diff
  • 图解快速dff
  • 最长递增子序列
  • 模板编译器
  • 模板编译提升
  • 组件name作用
  • 路由传参方式
  • 基础篇

    • 序章React介绍
    • JSX基础语法
    • React基本介绍
    • 表单
    • 生命周期
    • 组件与事件绑定
    • 组件状态与数据传递
    • Hooks
    • React--redux介绍
    • React-router介绍
  • 就业篇

    • 属性默认值和类型验证
    • 高阶组件
    • Ref
    • Context
    • Render Props
    • Portals
    • 错误边界
    • 组件渲染性能优化
    • 前端框架的理解
    • Reacti和Vue描述页面的区别
    • 前端框架的分类
    • 虚拟DoM
    • React整体架构
    • React渲染流程
    • Fiber双缓冲
    • MessageChannel
    • Scheduleri调度普通任务
    • Scheduleri调度延时任务
    • 最小堆
    • React中的位运算
    • beginWork工作流程
    • completeWork工作流程
    • 图解diff算法
    • commit工作流程
    • lane模型
    • React中的事件
    • Hooks原理
    • useStateuseReducer.
    • effect相关hook
    • useCallbackuseMemo
    • useRef
    • Update
    • 性能优化策略之eagerState
    • 性能优化策略之bailout
    • bailoutContextAPl
    • 性能优化对日常开发启示
  • 前端监控概述
  • 错误监控
  • 数据上报
  • 页面性能监控
  • 用户行为收集与埋点
  • CSS3手册
  • HTML5手册
  • JavaScript语言提升

    • es补充
    • 事件循环
    • promise基础
    • Promise的链式调用
    • Promise的静态方法
    • async和await
    • Promise相关面试题
  • 网络

    • 客户端与服务器
    • 关于 Apifox 的使用
  • git文档
  • 工程化

    • CommonJS
    • ES module
    • npm文档(包管理)
    • Lass笔记
    • webpack工具
  • canvas详解
  • uinapp笔记
  • 自动化测试
  • oauth2令牌

    • 认识Oauth2
    • 三方应用实现github授权
    • 微信三方应用登录实现
    • 支付宝沙箱支付功能
  • 课程导读-必看
  • Vue3整体变化
  • Vue2响应式回顾
  • Vue3响应式变化
  • nextTick实现原理
  • 两道代码题
  • Vue运行机制
    • 渲染器核心功能
    • 事件绑定与更新
    • computed面试题
    • watch面试题
    • 图解双端diff
    • 图解快速diff
    • 最长递增子序列
    • 模板编译器
    • 模板编译提升
    • 组件name作用
    • Vue项目性能优化
    • 路由传参方式
    • vue3笔面试题汇总
    luzhichang
    2024-09-27
    目录

    Vue运行机制

    # Vue运行机制

    面试题:介绍一下 Vue3 内部的运行机制是怎样的?

    Vue3 整体可以分为几大核心模块:

    • 响应式系统
    • 编译器
    • 渲染器

    如何描述UI

    思考🤔:UI涉及到的信息有哪些?

    1. DOM元素
    2. 属性
    3. 事件
    4. 元素的层次结构

    思考🤔:如何在 JS 中描述这些信息?

    考虑使用对象来描述上面的信息

    <h1 id='title' @click=handler><span>hello</span></h1>
    
    const obj = {
      tag: 'h1',
      props: {
        id: 'title',
        onClick: handler
      },
      children: [
        {
          tag: 'span',
          children: 'hello'
        }
      ]
    }
    

    虽然这种方式能够描述出来 UI,但是非常麻烦,因此 Vue 提供了模板的方式。

    用户书写模板----> 编译器 ----> 渲染函数 ----> 渲染函数执行得到上面的 JS 对象(虚拟DOM)

    虽然大多数时候,模板比 JS 对象更加直观,但是偶尔有一些场景,JS 的方式更加灵活

    <h1 v-if="level === 1"></h1>
    <h2 v-else-if="level === 2"></h2>
    <h3 v-else-if="level === 3"></h3>
    <h4 v-else-if="level === 4"></h4>
    <h5 v-else-if="level === 5"></h5>
    <h6 v-else-if="level === 6"></h6>
    
    let level = 1;
    const title = {
      tag: `h${level}`
    }
    

    编译器

    主要负责将开发者所书写的模板转换为渲染函数。例如:

    <template>
    	<div>
      	<h1 :id="someId">Hello</h1>
      </div>
    </template>
    

    编译后的结果为:

    function render(){
      return h('div', [
        h('h1', {id: someId}, 'Hello')
      ])
    }
    

    执行渲染函数,就会得到 JS 对象形式的 UI 表达。

    整体来讲,整个编译过程如下图所示:

    image-20231113095532166

    可以看到,在编译器的内部,实际上又分为了:

    • 解析器:负责将模板解析为对应的模板 AST(抽象语法树)
    • 转换器:负责将模板AST转换为 JS AST
    • 生成器:将 JS AST 生成对应的 JS 代码(渲染函数)

    Vue3 的编译器,除了最基本的编译以外,还做了很多的优化:

    1. 静态提升
    2. 预字符串化
    3. 缓存事件处理函数
    4. Block Tree
    5. PatchFlag

    渲染器

    执行渲染函数得到的就是虚拟 DOM,也就是像这样的 JS 对象,里面包含着 UI 的描述信息

    <div>点击</div>
    
    const vnode = {
      tag: 'div',
      props: {
        onClick: ()=> alert('hello')
      },
      children: '点击'
    }
    

    渲染器拿到这个虚拟 DOM 后,就会将其转换为真实的 DOM

    image-20240901174218998

    一个简易版渲染器的实现思路:

    1. 创建元素
    2. 为元素添加属性和事件
    3. 处理children
    function renderer(vnode, container){
      // 1. 创建元素
    	const el = document.createElement(vnode.tag);
      // 2. 遍历 props,为元素添加属性
      for (const key in vnode.props) {
        if (/^on/.test(key)) {
          // 如果 key 以 on 开头,说明它是事件
          el.addEventListener(
            key.substr(2).toLowerCase(), // 事件名称 onClick --->click
            vnode.props[key] // 事件处理函数
          );
        }
      }
      // 3. 处理children
      if(typeof vnode.children === 'string'){
        el.appendChild(document.createTextNode(vnode.children))
      } else if(Array.isArray(vnode.children)) {
        // 递归的调用 renderer
        vnode.children.forEach(child => renderer(child, el))
      }
      
      container.appendChild(el)
    }
    

    组件的本质

    组件本质就是一组 DOM 元素的封装。

    假设函数代表一个组件:

    // 这个函数就可以当作是一个组件
    const MyComponent = function () {
      return {
        tag: "div",
        props: {
          onClick: () => alert("hello"),
        },
        children: "click me",
      };
    };
    

    vnode 的 tag 就不再局限于 html 元素,而是可以写作这个函数名:

    const vnode = {
      tag: MyComponent
    }
    

    渲染器需要新增针对这种 tag 类型的处理:

    function renderer(vnode, container) {
      if (typeof vnode.tag === "string") {
        // 说明 vnode 描述的是标签元素
        mountElement(vnode, container);
      } else if (typeof vnode.tag === "function") {
        // 说明 vnode 描述的是组件
        mountComponent(vnode, container);
      }
    }
    

    组件也可以使用对象的形式:

    const MyComponent = {
      render(){
        return {
          tag: "div",
          props: {
            onClick: () => alert("hello"),
          },
          children: "click me",
      	};
      }
    }
    
    function renderer(vnode, container) {
      if (typeof vnode.tag === "string") {
        // 说明 vnode 描述的是标签元素
        mountElement(vnode, container);
      } else if (typeof vnode.tag === "object") {
        // 说明 vnode 描述的是组件
        mountComponent(vnode, container);
      }
    }
    

    响应式系统

    总结:当模板编译成的渲染函数执行时,渲染函数内部用到的响应式数据会和渲染函数本身构成依赖关系,之后只要响应式数据发生变化,渲染函数就会重新执行。

    面试题:介绍一下 Vue3 内部的运行机制是怎样的?

    参考答案:

    Vue3 是一个声明式的框架。声明式的好处在于,它直接描述结果,用户不需要关注过程。Vue.js 采用模板的方式来描述 UI,但它同样支持使用虚拟 DOM 来描述 UI。虚拟 DOM 要比模板更加灵活,但模板要比虚拟 DOM 更加直观。

    当用户使用模板来描述 UI 的时候,内部的 编译器 会将其编译为渲染函数,渲染函数执行后能够确定响应式数据和渲染函数之间的依赖关系,之后响应式数据一变化,渲染函数就会重新执行。

    渲染函数执行的结果是得到虚拟 DOM,之后就需要 渲染器 来将虚拟 DOM 对象渲染为真实 DOM 元素。它的工作原理是,递归地遍历虚拟 DOM 对象,并调用原生 DOM API 来完成真实 DOM 的创建。渲染器的精髓在于后续的更新,它会通过 Diff 算法找出变更点,并且只会更新需要更新的内容。

    编译器、渲染器、响应式系统都是 Vue 内部的核心模块,它们共同构成一个有机的整体,不同模块之间互相配合,进一步提升框架性能。


    -EOF-

    两道代码题
    渲染器核心功能

    ← 两道代码题 渲染器核心功能→

    Theme by Vdoing | Copyright © 2021-2024 蜀ICP备2024068710号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式