欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3中虛擬dom的介紹與使用詳解

 更新時(shí)間:2024年01月14日 08:36:50   作者:CSU_XZY  
Vue?是如何將一份模板轉(zhuǎn)換為真實(shí)的?DOM?節(jié)點(diǎn)的,又是如何高效地更新這些節(jié)點(diǎn)的呢,這些都離不開(kāi)虛擬dom這個(gè)概念,下面我們就來(lái)了解下虛擬dom這個(gè)概念以及它是什么吧

Vue 是如何將一份模板轉(zhuǎn)換為真實(shí)的 DOM 節(jié)點(diǎn)的,又是如何高效地更新這些節(jié)點(diǎn)的呢?這些都離不開(kāi)虛擬dom這個(gè)概念,接下來(lái)我們就先了解下虛擬dom這個(gè)概念以及它是什么。

什么是虛擬dom

在使用前端框架的時(shí)候,我們經(jīng)常會(huì)聽(tīng)到虛擬dom這個(gè)概念。那么到底什么是虛擬dom呢?

虛擬 DOM (Virtual DOM,簡(jiǎn)稱 VDOM) 是一種編程概念,意為將目標(biāo)所需的 UI 通過(guò)數(shù)據(jù)結(jié)構(gòu)“虛擬”地表示出來(lái),保存在內(nèi)存中,然后將真實(shí)的 DOM 與之保持同步。這個(gè)概念是由 React 率先開(kāi)拓,隨后被許多不同的框架采用,當(dāng)然也包括 Vue。簡(jiǎn)單來(lái)說(shuō),虛擬 DOM 就是一個(gè)用 JavaScript 對(duì)象表示真實(shí) DOM 的概念。

vue3中,虛擬dom,也就是代碼里面的vnode,他就是一個(gè)對(duì)象,定義位于 packages/runtime-core/src/vnode.ts 文件中。VNode 類的結(jié)構(gòu)如下,具體字段是怎么使用的我們后續(xù)章節(jié)一個(gè)個(gè)講解。

export interface VNode<
  HostNode = RendererNode,
  HostElement = RendererElement,
  ExtraProps = { [key: string]: any }
> {
  __v_isVNode: true
  [ReactiveFlags.SKIP]: true
  type: VNodeTypes
  props: (VNodeProps & ExtraProps) | null
  key: string | number | symbol | null
  ref: VNodeNormalizedRef | null
  scopeId: string | null
  slotScopeIds: string[] | null
  children: VNodeNormalizedChildren
  component: ComponentInternalInstance | null
  dirs: DirectiveBinding[] | null
  transition: TransitionHooks<HostElement> | null
  // DOM
  el: HostNode | null
  anchor: HostNode | null // fragment anchor
  target: HostElement | null // teleport target
  targetAnchor: HostNode | null // teleport target anchor
  staticCount: number
  suspense: SuspenseBoundary | null
  ssContent: VNode | null
  ssFallback: VNode | null
  shapeFlag: number
  patchFlag: number
  dynamicProps: string[] | null
  dynamicChildren: VNode[] | null
  appContext: AppContext | null
  ctx: ComponentInternalInstance | null
  memo?: any[]
  isCompatRoot?: true
  ce?: (instance: ComponentInternalInstance) => void
}

與其說(shuō)虛擬 DOM 是一種具體的技術(shù),不如說(shuō)是一種模式,所以并沒(méi)有一個(gè)標(biāo)準(zhǔn)的實(shí)現(xiàn)。我們可以用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明:

const vnode = {
  type: 'div',
  props: {
    id: 'hello'
  },
  children: [
    /* 更多 vnode */
  ]
}

這里所說(shuō)的 vnode 即一個(gè)純 JavaScript 的對(duì)象 (一個(gè)“虛擬節(jié)點(diǎn)”),它代表著一個(gè) <div> 元素。它包含我們創(chuàng)建實(shí)際元素所需的所有信息。它還包含更多的子節(jié)點(diǎn),這使它成為虛擬 DOM 樹(shù)的根節(jié)點(diǎn)。

一個(gè)運(yùn)行時(shí)渲染器將會(huì)遍歷整個(gè)虛擬 DOM 樹(shù),并據(jù)此構(gòu)建真實(shí)的 DOM 樹(shù)。這個(gè)過(guò)程被稱為掛載 (mount)。

如果我們有兩份虛擬 DOM 樹(shù),渲染器將會(huì)有比較地遍歷它們,找出它們之間的區(qū)別,并應(yīng)用這其中的變化到真實(shí)的 DOM 上。這個(gè)過(guò)程被稱為更新 (patch),又被稱為“比對(duì)”(diffing) 或“協(xié)調(diào)”(reconciliation)。

虛擬 DOM 帶來(lái)的主要收益是它讓開(kāi)發(fā)者能夠靈活、聲明式地創(chuàng)建、檢查和組合所需 UI 的結(jié)構(gòu),同時(shí)只需把具體的 DOM 操作留給渲染器去處理。

為什么使用虛擬dom

在前端開(kāi)發(fā)中,頻繁地操作 DOM 是非常耗時(shí)的,因?yàn)槊看尾僮鞫紩?huì)引發(fā)瀏覽器的重排和重繪。為了解決這個(gè)問(wèn)題,虛擬 DOM 應(yīng)運(yùn)而生。通過(guò)在內(nèi)存中模擬 DOM,我們可以批量地計(jì)算出 DOM 的變化,從而減少對(duì)真實(shí) DOM 的操作次數(shù)。這樣可以提高應(yīng)用的性能,特別是在大型應(yīng)用中。

例如當(dāng)一次操作中有100次更新DOM的動(dòng)作時(shí),虛擬DOM不會(huì)立即操作DOM,而是和原本的DOM進(jìn)行對(duì)比,將這100次更新的變化部分內(nèi)容保存到內(nèi)存中,最終一次性地應(yīng)用在DOM樹(shù)上,再進(jìn)行后續(xù)操作,避免大量無(wú)謂的計(jì)算量。

虛擬DOM實(shí)際上就是采用JavaScript對(duì)象來(lái)存儲(chǔ)DOM節(jié)點(diǎn)的信息,將DOM的更新變成對(duì)象的修改,并且這些修改計(jì)算在內(nèi)存中發(fā)生,當(dāng)修改完成后,再將JavaScript轉(zhuǎn)換成真實(shí)的DOM節(jié)點(diǎn),交給瀏覽器,從而達(dá)到性能的提升。

虛擬dom的好處

使用虛擬 DOM 的好處主要有以下幾點(diǎn):

  • 性能優(yōu)化:通過(guò)減少直接操作真實(shí) DOM 的次數(shù),可以降低瀏覽器的重繪和回流成本,從而提高頁(yè)面性能。
  • 跨平臺(tái):虛擬 DOM 不依賴于瀏覽器環(huán)境,可以方便地在不同平臺(tái)(如服務(wù)器端渲染、移動(dòng)端應(yīng)用等)使用。
  • 易于測(cè)試:因?yàn)樘摂M DOM 是 JavaScript 對(duì)象,我們可以直接對(duì)其進(jìn)行操作和斷言,而不需要依賴瀏覽器環(huán)境。

同時(shí)vue3的設(shè)計(jì)也是這樣的,我們可以看到源碼的組織結(jié)構(gòu)將各個(gè)目錄拆開(kāi)來(lái),runtime-core的實(shí)現(xiàn)就是與平臺(tái)無(wú)關(guān)的。在瀏覽器環(huán)境下使用runtime-domdom操作,在其他平臺(tái)使用各個(gè)平臺(tái)的dom操作,實(shí)現(xiàn)了跨平臺(tái)。

vue中vnode是如何運(yùn)行的

從高層面的視角看,Vue 組件掛載時(shí)會(huì)發(fā)生如下幾件事:

  • 編譯:Vue 模板被編譯為渲染函數(shù):即用來(lái)返回虛擬 DOM 樹(shù)的函數(shù)。這一步驟可以通過(guò)構(gòu)建步驟提前完成,也可以通過(guò)使用運(yùn)行時(shí)編譯器即時(shí)完成。
  • 掛載:運(yùn)行時(shí)渲染器調(diào)用渲染函數(shù),遍歷返回的虛擬 DOM 樹(shù),并基于它創(chuàng)建實(shí)際的 DOM 節(jié)點(diǎn)。這一步會(huì)作為響應(yīng)式副作用執(zhí)行,因此它會(huì)追蹤其中所用到的所有響應(yīng)式依賴。
  • 更新:當(dāng)一個(gè)依賴發(fā)生變化后,副作用會(huì)重新運(yùn)行,這時(shí)候會(huì)創(chuàng)建一個(gè)更新后的虛擬 DOM 樹(shù)。運(yùn)行時(shí)渲染器遍歷這棵新樹(shù),將它與舊樹(shù)進(jìn)行比較,然后將必要的更新應(yīng)用到真實(shí) DOM 上去。

可以看到我們一切操作都是針對(duì)于虛擬DOM的,只有在最后提交的時(shí)候才會(huì)將虛擬DOM掛載到瀏覽器上面

怎么創(chuàng)建虛擬dom

vue3中,我們?cè)?code>template模版中編寫(xiě)的代碼最終都會(huì)通過(guò)compiler模塊進(jìn)行編譯,編譯之后會(huì)返回一個(gè)render字符串,后面在應(yīng)用運(yùn)行的時(shí)候會(huì)調(diào)用這個(gè)render生成render函數(shù)。在函數(shù)里面會(huì)調(diào)用不同的方法進(jìn)行虛擬dom的創(chuàng)建。

例如下面的模版:

可以去template-explorer.vuejs.org/ 網(wǎng)站體驗(yàn)?zāi)0婢幾g結(jié)果

<template>
  <hello-world :msg="msg" :info="info"></hello-world>
  <div>
    <button @click="addAge">Add age</button>
    <button @click="toggleMsg">Toggle Msg</button>
  </div>
</template>

經(jīng)過(guò)編譯之后會(huì)生成如下函數(shù):

import { resolveComponent as _resolveComponent, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
?
const _hoisted_1 = ["onClick"]
const _hoisted_2 = ["onClick"]
?
export function render(_ctx, _cache, $props, $setup, $data, $options) {
  const _component_hello_world = _resolveComponent("hello-world")
?
  return (_openBlock(), _createElementBlock(_Fragment, null, [
    _createVNode(_component_hello_world, {
      msg: _ctx.msg,
      info: _ctx.info
    }, null, 8 /* PROPS */, ["msg", "info"]),
    _createElementVNode("div", null, [
      _createElementVNode("button", { onClick: _ctx.addAge }, "Add age", 8 /* PROPS */, _hoisted_1),
      _createElementVNode("button", { onClick: _ctx.toggleMsg }, "Toggle Msg", 8 /* PROPS */, _hoisted_2)
    ])
  ], 64 /* STABLE_FRAGMENT */))
}

現(xiàn)在我們不用理解這個(gè)代碼的所有內(nèi)容,我們只用關(guān)注里面創(chuàng)建節(jié)點(diǎn)的代碼,例如createVNode,createElementVNode這些就是用來(lái)創(chuàng)建虛擬dom的。調(diào)用完之后會(huì)生成虛擬dom樹(shù)。由于樹(shù)結(jié)構(gòu)過(guò)大, 我們這里不做展示,整個(gè)結(jié)構(gòu)和我們上面定義的虛擬dom結(jié)構(gòu)一致。

接下來(lái)我們可以看下創(chuàng)建虛擬dom的具體實(shí)現(xiàn),我們只挑常用的創(chuàng)建虛擬dom的方法。所有和虛擬dom有關(guān)的內(nèi)容都位于源碼packages/runtime-core/src/vnode.ts

createVNode

function _createVNode(
  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT, // 如果是組件,type就是組件內(nèi)容。如果是普通類型就是一個(gè)字符串,比方說(shuō)div, HelloWorld之類的
  props: (Data & VNodeProps) | null = null,
  children: unknown = null, //子組件
  patchFlag: number = 0,
  dynamicProps: string[] | null = null,
  isBlockNode = false
): VNode {
  if (!type || type === NULL_DYNAMIC_COMPONENT) {
    type = Comment
  }
?
  if (isVNode(type)) { // 是Vnode的處理,例如用戶通過(guò)h函數(shù)編寫(xiě)的代碼
    const cloned = cloneVNode(type, props, true /* mergeRef: true */)
    if (children) {
      normalizeChildren(cloned, children) // 標(biāo)準(zhǔn)化孩子
    }
    if (isBlockTreeEnabled > 0 && !isBlockNode && currentBlock) {
      if (cloned.shapeFlag & ShapeFlags.COMPONENT) {
        currentBlock[currentBlock.indexOf(type)] = cloned
      } else {
        currentBlock.push(cloned)
      }
    }
    cloned.patchFlag |= PatchFlags.BAIL
    return cloned
  }
?
  // 標(biāo)準(zhǔn)化用class寫(xiě)的組件
  if (isClassComponent(type)) { 
    type = type.__vccOpts
  }
?
  // 標(biāo)準(zhǔn)化異步組件和函數(shù)式組件
  if (__COMPAT__) { 
    type = convertLegacyComponent(type, currentRenderingInstance)
  }
?
  // 標(biāo)準(zhǔn)化class props style
  //對(duì)于代理過(guò)的對(duì)象,我們需要克隆來(lái)使用他們
  //因?yàn)橹苯有薷臅?huì)導(dǎo)致觸發(fā)響應(yīng)式
  if (props) {
    props = guardReactiveProps(props)! // 防止props是響應(yīng)式的
    let { class: klass, style } = props
    if (klass && !isString(klass)) {
      props.class = normalizeClass(klass) // 標(biāo)準(zhǔn)話class
    }
    if (isObject(style)) { // 標(biāo)準(zhǔn)化style
      if (isProxy(style) && !isArray(style)) {
        style = extend({}, style)
      }
      props.style = normalizeStyle(style)
    }
  }
?
  // encode the vnode type information into a bitmap
  const shapeFlag = isString(type) // 根據(jù)type不同生成不同的shapeFlag,方便后面對(duì)不同的類型做處理
    ? ShapeFlags.ELEMENT
    : __FEATURE_SUSPENSE__ && isSuspense(type)
    ? ShapeFlags.SUSPENSE
    : isTeleport(type)
    ? ShapeFlags.TELEPORT
    : isObject(type)
    ? ShapeFlags.STATEFUL_COMPONENT // 有狀態(tài)組件
    : isFunction(type)
    ? ShapeFlags.FUNCTIONAL_COMPONENT // 函數(shù)組件
    : 0
?
  return createBaseVNode(
    type,
    props,
    children,
    patchFlag, // 更新類型
    dynamicProps,
    shapeFlag,
    isBlockNode,
    true
  )
}

createVNode主要是對(duì)傳遞的type做出判斷,通過(guò)賦值shapeFlag來(lái)標(biāo)明當(dāng)前的虛擬節(jié)點(diǎn)的類型。

如果props含有style或者class要進(jìn)行標(biāo)準(zhǔn)化。

例如<div :style="['background:red',{color:'red'}]"></div>其中第一個(gè)是cssText形式、第二個(gè)是對(duì)象形式,他們應(yīng)該被轉(zhuǎn)化為對(duì)象類型所以轉(zhuǎn)化后應(yīng)該為<div style={color:'red',background:'red'}></div>。當(dāng)然對(duì)于class也需要標(biāo)準(zhǔn)化:class={hello:true,world:false} => :class="hello"。但是這里處理的其實(shí)是用戶自己寫(xiě)了render函數(shù),而對(duì)于使用了Vue自帶的編譯系統(tǒng)之后,是不需要做這一層處理的。

最后會(huì)調(diào)用createBaseVNode進(jìn)行虛擬dom的創(chuàng)建

function createBaseVNode(
  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
  props: (Data & VNodeProps) | null = null,
  children: unknown = null,
  patchFlag = 0,
  dynamicProps: string[] | null = null, // 動(dòng)態(tài)屬性
  shapeFlag = type === Fragment ? 0 : ShapeFlags.ELEMENT,
  isBlockNode = false,
  needFullChildrenNormalization = false
) {
  const vnode = { // 創(chuàng)建一個(gè)vnode
    __v_isVNode: true, // 是不是vnode
    __v_skip: true,
    type, // type對(duì)于組件來(lái)說(shuō)就是組件內(nèi)容
    props,
    key: props && normalizeKey(props), // 標(biāo)準(zhǔn)化key
    ref: props && normalizeRef(props), // 標(biāo)準(zhǔn)化 props
    scopeId: currentScopeId,
    slotScopeIds: null,
    children, // 孩子的vnode
    component: null, // 如果是一個(gè)組件的話就會(huì)有組件的實(shí)例,組件實(shí)例的subtree上面掛載了這個(gè)組件下面所有的vnode
    suspense: null,
    ssContent: null,
    ssFallback: null,
    dirs: null, // 指令相關(guān)
    transition: null, // transition相關(guān)
    el: null, // 真實(shí)dom
    anchor: null, // 插入的位置
    target: null,
    targetAnchor: null,
    staticCount: 0,
    shapeFlag, // 組件類型
    patchFlag, // 靶向更新標(biāo)記
    dynamicProps, // 動(dòng)態(tài)props
    dynamicChildren: null, // 動(dòng)態(tài)孩子
    appContext: null, // 應(yīng)用根context
    ctx: currentRenderingInstance
  } as VNode
?
  if (needFullChildrenNormalization) {
    normalizeChildren(vnode, children) // 標(biāo)準(zhǔn)化子組件。例如插槽啥的。添加children并且更改vnode的shapFlag
    if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
      ;(type as typeof SuspenseImpl).normalize(vnode) // 標(biāo)準(zhǔn)化異步組件
    }
  } else if (children) {
    vnode.shapeFlag |= isString(children) // 判斷ShapeFlags,可以是多個(gè)類型的組合
      ? ShapeFlags.TEXT_CHILDREN
      : ShapeFlags.ARRAY_CHILDREN
  }
?
  // 編譯優(yōu)化相關(guān)?,F(xiàn)在不必了解
  if (
    isBlockTreeEnabled > 0 &&
    // avoid a block node from tracking itself
    !isBlockNode &&
    // has current parent block
    currentBlock &&
    // presence of a patch flag indicates this node needs patching on updates. // 補(bǔ)丁標(biāo)志的存在表明此節(jié)點(diǎn)需要在更新時(shí)進(jìn)行補(bǔ)丁。
    // component nodes also should always be patched, because even if the // 組件節(jié)點(diǎn)應(yīng)該是中有patchFlag
    // component doesn't need to update, it needs to persist the instance on to // 組件不需要更新,它需要將實(shí)例持久化到
    // the next vnode so that it can be properly unmounted later. 下一個(gè)vnode,以便以后可以正確地卸載它。
    (vnode.patchFlag > 0 || shapeFlag & ShapeFlags.COMPONENT) && // 有patchFlag說(shuō)明是動(dòng)態(tài)節(jié)點(diǎn)
    vnode.patchFlag !== PatchFlags.HYDRATE_EVENTS
  ) {
    currentBlock.push(vnode) // 放入到父親的區(qū)塊中去,說(shuō)明現(xiàn)在的是一個(gè)動(dòng)態(tài)節(jié)點(diǎn)
  }
?
  if (__COMPAT__) {
    convertLegacyVModelProps(vnode)
    defineLegacyVNodeProperties(vnode)
  }
?
  return vnode
}

可以看到我們創(chuàng)建了一個(gè)VNode類型的對(duì)象,也就是一個(gè)虛擬dom。同時(shí)對(duì)key、ref、chidren(needFullChildrenNormalization為true)進(jìn)行標(biāo)準(zhǔn)化。

至此我們就知道vue3中虛擬dom究竟是怎么產(chǎn)生的啦。

createElementVNode

用于創(chuàng)建普通tag的虛擬節(jié)點(diǎn)如<div></div>

export { createBaseVNode as createElementVNode }

可以看到createElementVNode其實(shí)就是createBaseVNode,用來(lái)創(chuàng)建虛擬dom

項(xiàng)目中使用

上面我們提到,Vue 模板會(huì)被預(yù)編譯成虛擬 DOM 渲染函數(shù)。Vue 也提供了 API(h函數(shù)) 使我們可以不使用模板編譯,直接手寫(xiě)渲染函數(shù)。在處理高度動(dòng)態(tài)的邏輯時(shí),渲染函數(shù)相比于模板更加靈活,因?yàn)槟憧梢酝耆厥褂?JavaScript 來(lái)構(gòu)造你想要的 vnode。

但是官方推薦的是使用模版而不是渲染函數(shù)。那么為什么 Vue 默認(rèn)推薦使用模板呢?有以下幾點(diǎn)原因:

  • 模板更貼近實(shí)際的 HTML。這使得我們能夠更方便地重用一些已有的 HTML 代碼片段,能夠帶來(lái)更好的可訪問(wèn)性體驗(yàn)、能更方便地使用 CSS 應(yīng)用樣式,并且更容易使設(shè)計(jì)師理解和修改。
  • 由于其確定的語(yǔ)法,更容易對(duì)模板做靜態(tài)分析。這使得 Vue 的模板編譯器能夠應(yīng)用許多編譯時(shí)優(yōu)化來(lái)提升虛擬 DOM 的性能表現(xiàn)(例如靜態(tài)提升,靶向更新等等)

在絕大多數(shù)情況下,Vue 推薦使用模板語(yǔ)法來(lái)創(chuàng)建應(yīng)用。然而在某些使用場(chǎng)景下,我們真的需要用到 JavaScript 完全的編程能力。這時(shí)渲染函數(shù)就派上用場(chǎng)了。Vue 提供了一個(gè) h() 函數(shù)用于創(chuàng)建 vnodes。下面我們來(lái)看看h函數(shù)的用法:

import { h } from 'vue'
?
const vnode = h(
  'div', // type
  { id: 'foo', class: 'bar' }, // props
  [
    /* children */
  ]
)

h()hyperscript 的簡(jiǎn)稱——意思是“能生成 HTML (超文本標(biāo)記語(yǔ)言) 的 JavaScript”。這個(gè)名字來(lái)源于許多虛擬 DOM 實(shí)現(xiàn)默認(rèn)形成的約定。一個(gè)更準(zhǔn)確的名稱應(yīng)該是 createVnode(),但當(dāng)你需要多次使用渲染函數(shù)時(shí),一個(gè)簡(jiǎn)短的名字會(huì)更省力。

我們可以在組件中使用h函數(shù)來(lái)執(zhí)行渲染而使用模版

import { h } from 'vue'

export default {
  setup() { // 需要確保返回的是一個(gè)函數(shù)而不是一個(gè)值,這個(gè)函數(shù)最后會(huì)被用作渲染函數(shù)render,這個(gè)render在后面會(huì)被重復(fù)調(diào)用的
    // 使用數(shù)組返回多個(gè)根節(jié)點(diǎn)
    return () => [
      h('div'),
      h('div'),
      h('div')
    ]
  }
}

以上代碼等價(jià)于

<template>
	<div></div>
  <div></div>
  <div></div>
</template>

export default {
  setup() {}
}

然后我們可以看下h函數(shù)的源碼:

export function h(type: any, propsOrChildren?: any, children?: any): VNode {
  const l = arguments.length
  if (l === 2) { // 只有兩個(gè)參數(shù),要么是只有孩子,要么是只有props
    if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
      if (isVNode(propsOrChildren)) { // 如果第二個(gè)參數(shù)是一個(gè)vnode說(shuō)明是子節(jié)點(diǎn)
        return createVNode(type, null, [propsOrChildren])
      }
      return createVNode(type, propsOrChildren) // 沒(méi)有孩子節(jié)點(diǎn)的情況
    } else {
      // 如果propsOrChildren是數(shù)組那么一定是孩子節(jié)點(diǎn)
      return createVNode(type, null, propsOrChildren)
    }
  } else { // prop和孩子節(jié)點(diǎn)都有的情況
    if (l > 3) { // 第三個(gè)參數(shù)之后都是孩子
      children = Array.prototype.slice.call(arguments, 2)
    } else if (l === 3 && isVNode(children)) {
      children = [children]
    }
    return createVNode(type, propsOrChildren, children)
  }
}

可以看到h函數(shù)有三個(gè)參數(shù),第一個(gè)參數(shù)是類型,第二個(gè)是props參數(shù)或者孩子節(jié)點(diǎn)(如果有第三個(gè)參數(shù)就是props,沒(méi)有第三個(gè)參數(shù)就要判斷下),三個(gè)參數(shù)是孩子節(jié)點(diǎn)。除了類型必填以外,其他的參數(shù)都是可選的。h函數(shù)只是對(duì)參數(shù)做了一下判斷,然后底層還是調(diào)用的createVNode進(jìn)行虛擬DOM的創(chuàng)建。

具體判斷邏輯代碼中都已經(jīng)注釋,大家可以結(jié)合著看。

總結(jié)

現(xiàn)在相信大家已經(jīng)了解了虛擬dom這個(gè)東東,后續(xù)我們所有的操作都是通過(guò)操作虛擬dom來(lái)實(shí)現(xiàn)的,最后掛載的時(shí)候通過(guò)原生的dom操作來(lái)將虛擬dom掛載到頁(yè)面上。

以上就是vue3中虛擬dom的介紹與使用詳解的詳細(xì)內(nèi)容,更多關(guān)于vue3虛擬dom的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue數(shù)據(jù)雙向綁定底層實(shí)現(xiàn)原理

    Vue數(shù)據(jù)雙向綁定底層實(shí)現(xiàn)原理

    這篇文章主要為大家詳細(xì)介紹了Vue數(shù)據(jù)雙向綁定底層實(shí)現(xiàn)原理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • vue項(xiàng)目是如何運(yùn)行起來(lái)的

    vue項(xiàng)目是如何運(yùn)行起來(lái)的

    這篇文章主要介紹了vue項(xiàng)目是如何運(yùn)行起來(lái)的,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue里如何主動(dòng)銷毀keep-alive緩存的組件

    vue里如何主動(dòng)銷毀keep-alive緩存的組件

    這篇文章主要介紹了vue里如何主動(dòng)銷毀keep-alive緩存的組件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • electron實(shí)現(xiàn)打印功能支持靜默打印、無(wú)感打印

    electron實(shí)現(xiàn)打印功能支持靜默打印、無(wú)感打印

    使用electron開(kāi)發(fā)應(yīng)用遇到了打印小票的功能,實(shí)現(xiàn)途中還是幾經(jīng)波折,下面這篇文章主要給大家介紹了關(guān)于electron實(shí)現(xiàn)打印功能支持靜默打印、無(wú)感打印的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • vue獲取參數(shù)的幾種方式總結(jié)

    vue獲取參數(shù)的幾種方式總結(jié)

    這篇文章主要介紹了vue獲取參數(shù)的幾種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • vue-cli腳手架的.babelrc文件用法說(shuō)明

    vue-cli腳手架的.babelrc文件用法說(shuō)明

    這篇文章主要介紹了vue-cli腳手架的.babelrc文件用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Vue?props傳遞的類型和寫(xiě)法分享

    Vue?props傳遞的類型和寫(xiě)法分享

    這篇文章主要介紹了Vue?props傳遞的類型和寫(xiě)法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • vue中導(dǎo)出Excel表格的實(shí)現(xiàn)代碼

    vue中導(dǎo)出Excel表格的實(shí)現(xiàn)代碼

    項(xiàng)目中我們可能會(huì)碰到導(dǎo)出Excel文件的需求,這篇文章主要介紹了vue中導(dǎo)出Excel表格的實(shí)現(xiàn)代碼,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-10-10
  • 關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題

    關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題

    這篇文章主要介紹了關(guān)于element?ui中的el-scrollbar橫向滾動(dòng)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 在vue中安裝使用sass的實(shí)現(xiàn)方法

    在vue中安裝使用sass的實(shí)現(xiàn)方法

    這篇文章主要介紹了在vue中安裝使用sass的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05

最新評(píng)論