最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文解析Vue h函數(shù)到底是個(gè)啥

 更新時(shí)間:2025年02月17日 09:49:31   作者:二川bro  
h()函數(shù)是Vue.js中的一個(gè)工具函數(shù),用于創(chuàng)建虛擬DOM節(jié)點(diǎn),具有更高的靈活性和控制力,本文介紹Vue h函數(shù)到底是個(gè)啥,感興趣的朋友一起看看吧

h 到底是個(gè)啥?


 

對(duì)于了解或?qū)W習(xí)Vue高階組件(HOC)的同學(xué)來(lái)說(shuō),h() 函數(shù)無(wú)疑是一個(gè)經(jīng)常遇到的概念。

那么,這個(gè)h() 函數(shù)究竟如何使用呢,又在什么場(chǎng)景下適合使用呢?


 

一、h 是什么

看到這個(gè)函數(shù)你可能會(huì)有些許困惑,為什么叫h呢?代表著什么呢?
 

官方定義

返回一個(gè)“虛擬節(jié)點(diǎn)” ,通??s寫(xiě)為 VNode: 一個(gè)普通對(duì)象,其中包含向 Vue 描述它應(yīng)該在頁(yè)面上呈現(xiàn)哪種節(jié)點(diǎn)的信息,包括對(duì)任何子節(jié)點(diǎn)的描述。用于手動(dòng)編寫(xiě)render

h其實(shí)代表的是 hyperscript 。它是 HTML 的一部分,表示的是超文本標(biāo)記語(yǔ)言,當(dāng)我們正在處理一個(gè)腳本的時(shí)候,在虛擬 DOM 節(jié)點(diǎn)中去使用它進(jìn)行替換已成為一種慣例。這個(gè)定義同時(shí)也被運(yùn)用到其他的框架文檔中

Hyperscript 它本身表示的是 “生成描述 HTML 結(jié)構(gòu)的腳本”

二、語(yǔ)法

h() 函數(shù)的基本語(yǔ)法如下:

h(tag, props, children)
  • tag:可以是字符串或組件,表示要?jiǎng)?chuàng)建的 HTML 標(biāo)簽或 Vue 組件。
  • props:是一個(gè)對(duì)象,包含要傳遞給標(biāo)簽或組件的屬性,如類(lèi)名、樣式、事件監(jiān)聽(tīng)器等。
  • children:可以是字符串、數(shù)組或函數(shù),表示子節(jié)點(diǎn)。子節(jié)點(diǎn)可以是文本、其他 VNode 或一個(gè)返回 VNode 的函數(shù)。

以下是一個(gè)簡(jiǎn)單的代碼示例,展示了如何使用 h() 函數(shù)創(chuàng)建一個(gè)包含標(biāo)題和段落的組件:

  <!DOCTYPE html>
  <html>
    <head>
    <meta charset="utf-8">
    <title>h()</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0-rc.4/vue.global.js"></script>
    </head>
    <body>
       <div id="app">
       </div>
       <script>
        const App = {
          render() {
            return Vue.h('h1', {}, '二川兄弟')
          }
        }
        // console 結(jié)果請(qǐng)?jiān)诳刂婆_(tái)查看
        console.log(Vue.h('h1', {}, '二川兄弟'))
        Vue.createApp(App).mount('#app')
      </script>
    </body>
  </html>

效果:

打印:

在這個(gè)示例中,我們創(chuàng)建了一個(gè) <h1> 容器,內(nèi)部插入文字 “二川兄弟”。所有這些都是通過(guò) h() 函數(shù)來(lái)實(shí)現(xiàn)的,而不是使用模板語(yǔ)法。

三、源碼解析

要深入理解 h() 函數(shù),我們需要查看 Vue.js 的源碼。在 Vue.js 的實(shí)現(xiàn)中,h() 函數(shù)是一個(gè)封裝了 VNode 創(chuàng)建邏輯的工具函數(shù)。它接收標(biāo)簽名、屬性和子節(jié)點(diǎn)作為參數(shù),并返回一個(gè)包含這些信息的 VNode 對(duì)象。

export function h(type: any, propsOrChildren?: any, children?: any): VNode {
  if (arguments.length === 2) {
    if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
      // single vnode without props
      if (isVNode(propsOrChildren)) {
        return createVNode(type, null, [propsOrChildren])
      }
      // props without children
      return createVNode(type, propsOrChildren)
    } else {
      // omit props
      return createVNode(type, null, propsOrChildren)
    }
  } else {
    if (isVNode(children)) {
      children = [children]
    }
    return createVNode(type, propsOrChildren, children)
  }
}

VNode 是 Vue.js 對(duì)真實(shí) DOM 的一種輕量級(jí)表示。它包含了節(jié)點(diǎn)的類(lèi)型、屬性、子節(jié)點(diǎn)等信息,但不包含具體的 DOM 元素。Vue.js 會(huì)在渲染時(shí)將 VNode 轉(zhuǎn)換為真實(shí)的 DOM 元素。

h() 函數(shù)的源碼中,你會(huì)看到大量的邊界情況處理和類(lèi)型檢查。例如,如果子節(jié)點(diǎn)是一個(gè)字符串,它會(huì)被轉(zhuǎn)換為一個(gè)文本節(jié)點(diǎn);如果子節(jié)點(diǎn)是一個(gè)數(shù)組,它會(huì)遍歷數(shù)組并遞歸地創(chuàng)建子節(jié)點(diǎn)的 VNode;如果子節(jié)點(diǎn)是一個(gè)函數(shù),它會(huì)調(diào)用該函數(shù)并傳遞當(dāng)前上下文來(lái)創(chuàng)建子節(jié)點(diǎn)的 VNode。

_createVNode 又做了啥?

function _createVNode(
  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
  props: (Data & VNodeProps) | null = null,
  children: unknown = null,
  // 更新標(biāo)志
  patchFlag: number = 0,
  // 自定義屬性
  dynamicProps: string[] | null = null,
  // 是否是動(dòng)態(tài)節(jié)點(diǎn),(v-if v-for)
  isBlockNode = false 
): VNode {
  // type必傳參數(shù)
  if (!type || type === NULL_DYNAMIC_COMPONENT) {
    if (__DEV__ && !type) {
      warn(`Invalid vnode type when creating vnode: ${type}.`)
    }
    type = Comment
  }
  // Class 類(lèi)型的type標(biāo)準(zhǔn)化
  // class component normalization.
  if (isFunction(type) && '__vccOpts' in type) {
    type = type.__vccOpts
  }
  // class & style normalization.
  if (props) {
    // props 如果是響應(yīng)式,clone 一個(gè)副本
    if (isProxy(props) || InternalObjectKey in props) {
      props = extend({}, props)
    }
    let { class: klass, style } = props
    // 標(biāo)準(zhǔn)化class, 支持 string , array, object 三種形式
    if (klass && !isString(klass)) {
      props.class = normalizeClass(klass)
    }
    // 標(biāo)準(zhǔn)化style, 支持 array ,object 兩種形式 
    if (isObject(style)) {
      // reactive state objects need to be cloned since they are likely to be
      // mutated
      if (isProxy(style) && !isArray(style)) {
        style = extend({}, style)
      }
      props.style = normalizeStyle(style)
    }
  }
  // encode the vnode type information into a bitmap
  const shapeFlag = isString(type)
    ? ShapeFlags.ELEMENT
    : __FEATURE_SUSPENSE__ && isSuspense(type)
      ? ShapeFlags.SUSPENSE
      : isTeleport(type)
        ? ShapeFlags.TELEPORT
        : isObject(type)
          ? ShapeFlags.STATEFUL_COMPONENT
          : isFunction(type)
            ? ShapeFlags.FUNCTIONAL_COMPONENT
            : 0
  if (__DEV__ && shapeFlag & ShapeFlags.STATEFUL_COMPONENT && isProxy(type)) {
    type = toRaw(type)
    warn(
      `Vue received a Component which was made a reactive object. This can ` +
        `lead to unnecessary performance overhead, and should be avoided by ` +
        `marking the component with \`markRaw\` or using \`shallowRef\` ` +
        `instead of \`ref\`.`,
      `\nComponent that was made reactive: `,
      type
    )
  }
  // 構(gòu)造 VNode 模型
  const vnode: VNode = {
    __v_isVNode: true,
    __v_skip: true,
    type,
    props,
    key: props && normalizeKey(props),
    ref: props && normalizeRef(props),
    scopeId: currentScopeId,
    children: null,
    component: null,
    suspense: null,
    dirs: null,
    transition: null,
    el: null,
    anchor: null,
    target: null,
    targetAnchor: null,
    staticCount: 0,
    shapeFlag,
    patchFlag,
    dynamicProps,
    dynamicChildren: null,
    appContext: null
  }
  normalizeChildren(vnode, children)
  // presence of a patch flag indicates this node needs patching on updates.
  // component nodes also should always be patched, because even if the
  // component doesn't need to update, it needs to persist the instance on to
  // the next vnode so that it can be properly unmounted later.
  // patchFlag 標(biāo)志存在表示節(jié)點(diǎn)需要更新,組件節(jié)點(diǎn)一直存在 patchFlag,因?yàn)榧词共恍枰?,它需要將?shí)例持久化到下一個(gè) vnode,以便以后可以正確卸載它
  if (
    shouldTrack > 0 &&
    !isBlockNode &&
    currentBlock &&
    // the EVENTS flag is only for hydration and if it is the only flag, the
    // vnode should not be considered dynamic due to handler caching.
    patchFlag !== PatchFlags.HYDRATE_EVENTS &&
    (patchFlag > 0 ||
      shapeFlag & ShapeFlags.SUSPENSE ||
      shapeFlag & ShapeFlags.TELEPORT ||
      shapeFlag & ShapeFlags.STATEFUL_COMPONENT ||
      shapeFlag & ShapeFlags.FUNCTIONAL_COMPONENT)
  ) {
    // 壓入 VNode 棧
    currentBlock.push(vnode)
  }
  return vnode
}

四、使用場(chǎng)景

h() 函數(shù)在 Vue.js 中有多種使用場(chǎng)景,以下是一些常見(jiàn)的場(chǎng)景:

渲染函數(shù)

  • 當(dāng)需要完全控制組件的渲染邏輯時(shí),可以使用渲染函數(shù),并在其中使用 h() 函數(shù)來(lái)創(chuàng)建 VNode。這種方式提供了比模板語(yǔ)法更高的靈活性和控制力。

以下是一個(gè)使用渲染函數(shù)的示例,展示了如何根據(jù)條件動(dòng)態(tài)渲染不同的內(nèi)容:

import { h } from 'vue';
export default {
  props: ['isLoggedIn'],
  render() {
    return h('div', 
      {}, 
      this.isLoggedIn 
        ? h('p', {}, 'Welcome back!') 
        : h('p', {}, 'Please log in.')
    );
  }
};

高階組件(HOC)

  • 高階組件是一種模式,它接收一個(gè)組件作為參數(shù),并返回一個(gè)新的組件。在創(chuàng)建新組件的過(guò)程中,h() 函數(shù)用于定制或擴(kuò)展原始組件的渲染邏輯。

以下是一個(gè)高階組件的示例,展示了如何為組件添加額外的類(lèi)名:

function withClassName(WrappedComponent, className) {
  return {
    props: WrappedComponent.props,
    render() {
      return h(WrappedComponent, { ...this.$props, class: className });
    }
  };
}
// 使用高階組件
const MyComponentWithClass = withClassName(MyComponent, 'my-custom-class');

動(dòng)態(tài)組件

  • 在需要根據(jù)條件動(dòng)態(tài)渲染不同組件時(shí),h() 函數(shù)可以方便地根據(jù)條件創(chuàng)建不同的 VNode。

以下是一個(gè)動(dòng)態(tài)組件的示例,展示了如何根據(jù)條件渲染不同的組件:

import { h, defineComponent } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
export default defineComponent({
  props: ['condition'],
  render() {
    return this.condition 
      ? h(ComponentA, { ...this.$props }) 
      : h(ComponentB, { ...this.$props });
  }
});

手動(dòng)創(chuàng)建復(fù)雜結(jié)構(gòu)

  • 在某些情況下,可能需要手動(dòng)創(chuàng)建復(fù)雜的組件結(jié)構(gòu),而不是使用模板語(yǔ)法。這時(shí),h() 函數(shù)就顯得非常有用。

以下是一個(gè)手動(dòng)創(chuàng)建復(fù)雜結(jié)構(gòu)的示例,展示了如何創(chuàng)建一個(gè)帶有嵌套子組件的表格:

import { h } from 'vue';
import TableRow from './TableRow.vue';
export default {
  props: ['data'],
  render() {
    return h('table', 
      {}, 
      this.data.map(row => 
        h(TableRow, { key: row.id, row: row })
      )
    );
  }
};

五、其他比較

與模板語(yǔ)法相比,使用 h() 函數(shù)提供了更高的靈活性和控制力。模板語(yǔ)法更適合于簡(jiǎn)單的組件和靜態(tài)內(nèi)容,而 h() 函數(shù)則更適合于復(fù)雜的組件和動(dòng)態(tài)內(nèi)容。

此外,與 JSX 相比,h() 函數(shù)更加簡(jiǎn)潔和直接。JSX 是一種語(yǔ)法糖,它允許在 JavaScript 中編寫(xiě)類(lèi)似 HTML 的代碼。然而,JSX 需要額外的編譯步驟,并且可能會(huì)增加代碼的復(fù)雜性。而 h() 函數(shù)則是 Vue.js 內(nèi)置的工具函數(shù),無(wú)需額外的編譯步驟,并且更加符合 Vue.js 的設(shè)計(jì)哲學(xué)。

六、最佳實(shí)踐

在使用 h() 函數(shù)時(shí),以下是一些最佳實(shí)踐:

保持簡(jiǎn)潔

  • 盡量避免在渲染函數(shù)中編寫(xiě)過(guò)多的邏輯??梢詫?fù)雜的邏輯拆分成多個(gè)函數(shù)或組件,以提高代碼的可讀性和可維護(hù)性。

使用輔助函數(shù)

  • 可以編寫(xiě)一些輔助函數(shù)來(lái)簡(jiǎn)化 h() 函數(shù)的使用。例如,可以編寫(xiě)一個(gè)函數(shù)來(lái)創(chuàng)建帶有特定樣式的節(jié)點(diǎn),或者一個(gè)函數(shù)來(lái)創(chuàng)建帶有事件監(jiān)聽(tīng)器的節(jié)點(diǎn)。

避免過(guò)度使用

  • 在大多數(shù)情況下,模板語(yǔ)法已經(jīng)足夠滿(mǎn)足需求。只有在需要更高的靈活性和控制力時(shí),才應(yīng)該考慮使用 h() 函數(shù)。

與模板語(yǔ)法結(jié)合使用

  • 可以將 h() 函數(shù)與模板語(yǔ)法結(jié)合使用。例如,可以在模板中使用 <script setup> 語(yǔ)法來(lái)定義渲染函數(shù),并在其中使用 h() 函數(shù)來(lái)創(chuàng)建復(fù)雜的節(jié)點(diǎn)結(jié)構(gòu)。

七、總結(jié)

h() 函數(shù)是 Vue.js 框架中一個(gè)強(qiáng)大且靈活的工具,用于在渲染函數(shù)中創(chuàng)建虛擬 DOM 節(jié)點(diǎn)。通過(guò)深入理解 h() 函數(shù)的語(yǔ)法、源碼和使用場(chǎng)景,開(kāi)發(fā)者可以更好地掌握 Vue.js 的渲染機(jī)制,并在實(shí)際開(kāi)發(fā)中靈活運(yùn)用這一工具來(lái)創(chuàng)建高效、可維護(hù)的組件。無(wú)論是編寫(xiě)渲染函數(shù)、實(shí)現(xiàn)高階組件,還是處理動(dòng)態(tài)組件和復(fù)雜結(jié)構(gòu),h() 函數(shù)都是不可或缺的一部分。

到此這篇關(guān)于一文解析Vue h函數(shù)到底是個(gè)啥的文章就介紹到這了,更多相關(guān)Vue h函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue2?與?Vue3?的數(shù)據(jù)綁定原理及實(shí)現(xiàn)

    Vue2?與?Vue3?的數(shù)據(jù)綁定原理及實(shí)現(xiàn)

    這篇文章主要介紹了Vue2與Vue3的數(shù)據(jù)綁定原理及實(shí)現(xiàn),數(shù)據(jù)綁定是一種把用戶(hù)界面元素的屬性綁定到特定對(duì)象上面并使其同步的機(jī)制,使開(kāi)發(fā)人員免于編寫(xiě)同步視圖模型和視圖的邏輯
    2022-09-09
  • uniapp 微信小程序之金額展示套餐

    uniapp 微信小程序之金額展示套餐

    文章介紹了uniapp微信小程序金額展示套餐的相關(guān)內(nèi)容,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-01-01
  • vue指令之表單控件綁定v-model v-model與v-bind結(jié)合使用

    vue指令之表單控件綁定v-model v-model與v-bind結(jié)合使用

    這篇文章主要介紹了vue指令之表單控件綁定v-model v-model與v-bind結(jié)合使用,需要的朋友可以參考下
    2019-04-04
  • Vue3 組件的開(kāi)發(fā)詳情

    Vue3 組件的開(kāi)發(fā)詳情

    這篇文章主要介紹了Vue3組件的開(kāi)發(fā),上一篇文章我們價(jià)紹了Vue3(三)網(wǎng)站首頁(yè)布局開(kāi)發(fā),今天繼續(xù)上篇內(nèi)容展開(kāi)組件的開(kāi)發(fā),需要的朋友可以參考一下
    2021-11-11
  • Vue全局自適應(yīng)大小:使用postcss-pxtorem方式

    Vue全局自適應(yīng)大小:使用postcss-pxtorem方式

    本文介紹了如何在Vue項(xiàng)目中使用postcss-pxtorem插件實(shí)現(xiàn)響應(yīng)式設(shè)計(jì),postcss-pxtorem可以自動(dòng)將CSS文件中的px單位轉(zhuǎn)換為rem單位,從而實(shí)現(xiàn)更好的自適應(yīng)布局,通過(guò)配置postcss-pxtorem插件,可以在構(gòu)建時(shí)自動(dòng)完成轉(zhuǎn)換,無(wú)需手動(dòng)修改代碼
    2025-01-01
  • uniapp頁(yè)面完成水印添加功能代碼示例(自定義文字)

    uniapp頁(yè)面完成水印添加功能代碼示例(自定義文字)

    這篇文章主要介紹了uniapp頁(yè)面完成水印添加功能(自定義文字)的相關(guān)資料,包括如何編寫(xiě)頁(yè)面代碼、數(shù)據(jù)代碼以及如何展示效果圖,通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-01-01
  • vue-admin-element項(xiàng)目突然就起不來(lái)了的解決

    vue-admin-element項(xiàng)目突然就起不來(lái)了的解決

    這篇文章主要介紹了vue-admin-element項(xiàng)目突然就起不來(lái)了的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • axios封裝,使用攔截器統(tǒng)一處理接口,超詳細(xì)的教程(推薦)

    axios封裝,使用攔截器統(tǒng)一處理接口,超詳細(xì)的教程(推薦)

    這篇文章主要介紹了axios封裝使用攔截器處理接口,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Element Collapse 折疊面板的使用方法

    Element Collapse 折疊面板的使用方法

    這篇文章主要介紹了Element Collapse 折疊面板的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • MAC+PyCharm+Flask+Vue.js搭建系統(tǒng)

    MAC+PyCharm+Flask+Vue.js搭建系統(tǒng)

    最近新做了個(gè)項(xiàng)目,使用的是MAC+PyCharm+Flask+Vue.js搭建系統(tǒng),本文就來(lái)分享一下搭建步驟,感興趣的可以了解一下
    2021-05-05

最新評(píng)論

宣城市| 修武县| 弥渡县| 习水县| 集安市| 沙坪坝区| 宁海县| 易门县| 安顺市| 大连市| 开封县| 越西县| 什邡市| 玉林市| 汕头市| 年辖:市辖区| 丰顺县| 涟源市| 仙桃市| 武陟县| 清流县| 庐江县| 沧州市| 禄丰县| 沙洋县| 长治市| 长白| 南江县| 诸城市| 大姚县| 鲁山县| 盖州市| 阳春市| 西安市| 林甸县| 宜城市| 尼勒克县| 永宁县| 土默特左旗| 津南区| 寿宁县|