前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • Vue

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

  • Webpack

  • Node

  • Javascript

  • 综合

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

自从有了 VNode ,开发页面的方式就变成了书写 VNode,但如果日常开发中需要手写 VNode ,那绝对是反人类的,在“组件的本质”一章中我们使用了 snabbdom 的 h 函数来辅助讲解一些小例子,h 函数作为创建 VNode 对象的函数封装,在一定程度上改善了这个问题,但却没有解决本质问题,这也是为什么我们需要模板或 jsx 的原因。但 h 函数依然很重要,因为无论是模板还是 jsx 都需要经过编译,那么是直接编译成 VNode 树好呢?还是编译成由 h 函数组成的调用集合好呢?这个其实很难说,但可以肯定的一点是,我们将可公用、灵活、复杂的逻辑封装成函数,并交给运行时,这能够大大降低编译器的书写难度,甚至经过编译器生成的代码也具有一定的可读性,而 h 函数就是众多运行时函数中的一个。

# 在VNode创建时确定其类型 - flags

一个最简单的 h 函数如下:

function h() {
  return {
    _isVNode: true,
    flags: VNodeFlags.ELEMENT_HTML,
    tag: 'h1',
    data: null,
    children: null,
    childFlags: ChildrenFlags.NO_CHILDREN,
    el: null
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

这个 h 函数只能用来创建一个空的 <h1></h1> 标签,可以说没有任何意义。为了让 h 函数更加灵活,我们可以增加一些参数,问题是哪些内容应该提取到参数中呢?如果提取的参数多了,就会导致函数的使用不便,如果提取的参数少了又会导致函数的功能不足,所以这也是一个探索的过程。实际上只需要把 tag、data 和 children 提取为参数即可:

function h(tag, data = null, children = null) {
  //...
}
@前端进阶之旅: 代码已经复制到剪贴板

我们来看看为什么三个参数就能满足需求,对于 _isVNode 属性,它的值始终都为 true,所以不需要提取到参数中。对于 flags 属性,我们可以通过检查 tag 属性值的特征来确定该 VNode 的 flags 属性值,如下:

function h(tag, data = null, children = null) {
  let flags = null
  if (typeof tag === 'string') {
    flags = tag === 'svg' ? VNodeFlags.ELEMENT_SVG : VNodeFlags.ELEMENT_HTML
  }
}
@前端进阶之旅: 代码已经复制到剪贴板

如上代码所示,如果 tag 是字符串则可以确定该 V

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
原理篇
面经篇
AI 面试
自检篇
每日一题
  • 综合
    • 综合题型
    • 其他问题
    • 设计模式
    • 思维导图
    • 学习路线
  • 前端基础
    • HTTP
    • 浏览器
    • 计算机基础
  • 进阶学习
    • NPM工作流
    • Docker
    • Canvas
    • Node学习指南
    • 前端综合文章
  • 其他
    • Handbook
    • 职场话题
    • CSS可视化
小程序题库
公众号动态
博客动态
开发者导航
  • Vue

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

  • Webpack

  • Node

  • Javascript

  • 综合