vue面试题-原理层

  • 虚拟dom
    • 虚拟dom是什么?
    • 虚拟dom在vue中做了什么?
      • vue 渲染两条线
    • 虚拟dom是如何提升vue的渲染效率的?
      • 局部更新节点数据
      • 将直接操作dom的地方拿到两个js对象之中去做比较
    • 虚拟dom生成三要素
      • 节点类型/目标元素 [必须有]
      • 节点属性
      • 子节点
  • Diff中的patch

虚拟dom

虚拟dom是什么?

  • a.vue2x 才有虚拟dom
  • b.本质 js对象 =>跨平台

虚拟dom在vue中做了什么?

vue 渲染两条线
  • 1.首次渲染:将真实dom转化虚拟dom (js对象)
  • 2.后续更新:更新的时候做对比

vue的渲染过程 (htm1,css,js)

<template>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
  </ul>
</template>

vue面试题-原理层_第1张图片

虚拟dom是如何提升vue的渲染效率的?

vue 特点

  • 组件化
  • 数据去驱动
局部更新(节点数据)
将直接操作dom的地方拿到两个js对象之中去做比较

vue面试题-原理层_第2张图片

虚拟dom生成三要素

虚拟 DOM (Virtual DOM) 是一种编程概念,它是在用户界面更新过程中用于跟踪和最小化必要的更改的技术。

节点类型/目标元素 [必须有]
节点属性
子节点

在生成虚拟 DOM 时,以下是三个主要要素:

  1. 节点类型/目标元素:在虚拟 DOM 中,每个节点都有一个特定的类型。这可能是元素节点(如
    , 等)、文本节点(如文本内容)或组件节点(如自定义组件)。节点类型决定了如何渲染和更新该节点。
  2. 节点属性:每个节点都有一组属性,这些属性定义了节点的外观和行为。例如,元素节点可能有类名、样式、事件处理器等属性。这些属性在虚拟 DOM 中以键值对的形式存储,可以在不改变底层 DOM 结构的情况下进行修改和更新。
  3. 子节点:每个节点可能有一个或多个子节点,这些子节点可以是其他元素、文本或组件节点。在虚拟 DOM 中,子节点的顺序和数量都是重要的,因为它们决定了渲染的结果。

让我们通过一个简单的例子来理解这三个要素:

假设我们有一个简单的 HTML 元素——一个包含文本的

元素。

<div id="myDiv">Hello, World!div>

在虚拟 DOM 中,这将被表示为一个节点对象,其中包含以下三个要素:

  1. 节点类型/目标元素:这是一个元素节点,类型为
  2. 节点属性:该节点有一个 id 属性,值为 "myDiv"
  3. 子节点:该节点有一个文本子节点,内容为 "Hello, World!"

现在,如果我们想更新这个

元素的内容,我们不需要直接操作 DOM。相反,我们可以更新虚拟 DOM,然后让库或框架将更改应用到实际的 DOM。例如,我们可以将文本更改为 "Hello, Virtual DOM!"。在虚拟 DOM 中,这将表现为子节点的更改。

虚拟 DOM 使得我们能够以更加可预测和高效的方式更新用户界面,尤其是在处理复杂的应用程序和频繁的更新时。

Diff中的patch


// 1.初始化 patch(container,vnode)
// 2.更新 update(vnode, newVnode)

// 初始化流程
function createElement(vnode){
  let tag = vnode.tag // 目标元素 ul
  let attrs = vnode.attrs || {}  // 属性
  let children = vnode.children || [] // 子节点

  if(!tag) {
    return null
  }

  // 1.创建对应的dom
  let elem = document .createElement(tag)
 

  // 2.给dom添加属性
   let attrName
  for(attrName in attrs){
   if(attrs.hasOwnProperty(attrName)){
      // class
      elem.setAttribute(attrName, attrs[attrName])
   } 
  }

  // 3.将子元素添加到目标之上
  children.forEach((childVnode)=>{
    elem.appendChild(createElement(childVnode))
  })

  return elem
}

// 更新流程
function updateChildren(vnode, newVnode){
  let children = vnode.children || [] // 现有节点
  let newChildren = newVnode.children || [] // 新节点

  children.forEach((childrenVnode, index)=>{ // 循环的每一项
    let newChildrenVnode = newChildren[index]

   // 第一层没有变化
    if(childrenVnode.tag === newChildrenVnode.tag){
       // 递归查询子元素 深层次对比 > 递归
      updateChildren(childrenVnode,newChildrenVnode)
    }else{
      
    // 两者tag不一样
      replaceNode(childrenVnode, newChildrenVnode)
     } 
  }) 
}  

你可能感兴趣的:(前端面试题,前端杂货铺,vue.js,javascript,前端)