最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Vue3.0進階之如何使用VNode

這篇文章主要講解了“Vue 3.0進階之如何使用VNode”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue 3.0進階之如何使用VNode”吧!

成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)介紹好的網(wǎng)站是理念、設(shè)計和技術(shù)的結(jié)合。創(chuàng)新互聯(lián)擁有的網(wǎng)站設(shè)計理念、多方位的設(shè)計風格、經(jīng)驗豐富的設(shè)計團隊。提供PC端+手機端網(wǎng)站建設(shè),用營銷思維進行網(wǎng)站設(shè)計、采用先進技術(shù)開源代碼、注重用戶體驗與SEO基礎(chǔ),將技術(shù)與創(chuàng)意整合到網(wǎng)站之中,以契合客戶的方式做到創(chuàng)意性的視覺化效果。

一、VNode 長什么樣?

// packages/runtime-core/src/vnode.ts export interface VNode<   HostNode = RendererNode,   HostElement = RendererElement,   ExtraProps = { [key: string]: any } > {  // 省略內(nèi)部的屬性 }

在 runtime-core/src/vnode.ts 文件中,我們找到了 VNode 的類型定義。通過 VNode 的類型定義可知,VNode  本質(zhì)是一個對象,該對象中按照屬性的作用,分為 5 大類。這里阿寶哥只詳細介紹其中常見的兩大類型屬性 —— 內(nèi)部屬性 和 DOM 屬性:

1.1 內(nèi)部屬性

__v_isVNode: true // 標識是否為VNode [ReactiveFlags.SKIP]: true // 標識VNode不是observable type: VNodeTypes // VNode 類型 props: (VNodeProps & ExtraProps) | null // 屬性信息 key: string | number | null // 特殊 attribute 主要用在 Vue 的虛擬 DOM 算法 ref: VNodeNormalizedRef | null // 被用來給元素或子組件注冊引用信息。 scopeId: string | null // SFC only children: VNodeNormalizedChildren // 保存子節(jié)點 component: ComponentInternalInstance | null // 指向VNode對應(yīng)的組件實例 dirs: DirectiveBinding[] | null // 保存應(yīng)用在VNode的指令信息 transition: TransitionHooks | null // 存儲過渡效果信息

1.2 DOM 屬性

el: HostNode | null // element  anchor: HostNode | null // fragment anchor target: HostElement | null // teleport target targetAnchor: HostNode | null // teleport target anchor staticCount: number // number of elements contained in a static vnode

1.3 suspense 屬性

suspense: SuspenseBoundary | null ssContent: VNode | null ssFallback: VNode | null

1.4 optimization 屬性

shapeFlag: number patchFlag: number dynamicProps: string[] | null dynamicChildren: VNode[] | null

1.5 應(yīng)用上下文屬性

appContext: AppContext | null

二、如何創(chuàng)建 VNode?

要創(chuàng)建 VNode 對象的話,我們可以使用 Vue 提供的 h 函數(shù)。也許可以更準確地將其命名為  createVNode(),但由于頻繁使用和簡潔,它被稱為 h() 。該函數(shù)接受三個參數(shù):

// packages/runtime-core/src/h.ts export function h(type: any, propsOrChildren?: any, children?: any): VNode {   const l = arguments.length   if (l === 2) {      if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {        // single vnode without props       if (isVNode(propsOrChildren)) {         return createVNode(type, null, [propsOrChildren])       }       // 只包含屬性不含有子元素       return createVNode(type, propsOrChildren) // h('div', { id: 'foo' })     } else {       // 忽略屬性       return createVNode(type, null, propsOrChildren) // h('div', ['foo'])     }   } else {     if (l > 3) {       children = Array.prototype.slice.call(arguments, 2)     } else if (l === 3 && isVNode(children)) {       children = [children]     }     return createVNode(type, propsOrChildren, children)   } }

觀察以上代碼可知, h 函數(shù)內(nèi)部的主要處理邏輯就是根據(jù)參數(shù)個數(shù)和參數(shù)類型,執(zhí)行相應(yīng)處理操作,但最終都是通過調(diào)用 createVNode 函數(shù)來創(chuàng)建  VNode 對象。在開始介紹 createVNode 函數(shù)前,阿寶哥先舉一些實際開發(fā)中的示例:

const app = createApp({ // 示例一   render: () => h('div', '我是阿寶哥') })  const Comp = () => h("p", "我是阿寶哥"); // 示例二  app.component('component-a', { // 示例三   template: "

我是阿寶哥

" })

示例一和示例二很明顯都使用了 h 函數(shù),而示例三并未看到 h 或 createVNode 函數(shù)的身影。為了一探究竟,我們需要借助 Vue 3  Template Explorer 這個在線工具來編譯一下 "

我是阿寶哥

" 模板,該模板編譯后的結(jié)果如下(函數(shù)模式):

// https://vue-next-template-explorer.netlify.app/ const _Vue = Vue return function render(_ctx, _cache, $props, $setup, $data, $options) {   with (_ctx) {     const { createVNode: _createVNode, openBlock: _openBlock,       createBlock: _createBlock } = _Vue     return (_openBlock(), _createBlock("p", null, "我是阿寶哥"))   } }

由以上編譯結(jié)果可知, "

我是阿寶哥

" 模板被編譯生成了一個 render 函數(shù),調(diào)用該函數(shù)后會返回 createBlock 函數(shù)的調(diào)用結(jié)果。其中 createBlock 函數(shù)的實現(xiàn)如下所示:

// packages/runtime-core/src/vnode.ts export function createBlock(   type: VNodeTypes | ClassComponent,   props?: Record | null,   children?: any,   patchFlag?: number,   dynamicProps?: string[] ): VNode {   const vnode = createVNode(     type,     props,     children,     patchFlag,     dynamicProps,     true /* isBlock: prevent a block from tracking itself */   )   // 省略部分代碼   return vnode }

在 createBlock 函數(shù)內(nèi)部,我們終于看到了 createVNode 函數(shù)的身影。顧名思義,該函數(shù)的作用就是用于創(chuàng)建  VNode,接下來我們來分析一下它。

三、createVNode 函數(shù)內(nèi)部做了啥?

下面我們將從參數(shù)說明和邏輯說明兩方面來介紹 createVNode 函數(shù):

3.1 參數(shù)說明

// packages/runtime-core/src/vnode.ts export const createVNode = (__DEV__   ? createVNodeWithArgsTransform   : _createVNode) as typeof _createVNode  function _createVNode(   type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,   props: (Data & VNodeProps) | null = null,   children: unknown = null,   patchFlag: number = 0,   dynamicProps: string[] | null = null,   isBlockNode = false ): VNode {   //    return vnode }

在分析該函數(shù)的具體代碼前,我們先來看一下它的參數(shù)。該函數(shù)可以接收 6 個參數(shù),這里阿寶哥用思維導圖來重點介紹前面 2 個參數(shù):

type 參數(shù)

// packages/runtime-core/src/vnode.ts function _createVNode(   type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,   // 省略其他參數(shù) ): VNode { ... }

Vue 3.0進階之如何使用VNode

由上圖可知,type 參數(shù)支持很多類型,比如常用的 string、VNode 和 Component 等。此外,也有一些陌生的面孔,比如  Text、Comment 、Static 和 Fragment 等類型,它們的定義如下:

// packages/runtime-core/src/vnode.ts export const Text = Symbol(__DEV__ ? 'Text' : undefined) export const Comment = Symbol(__DEV__ ? 'Comment' : undefined) export const Static = Symbol(__DEV__ ? 'Static' : undefined)  export const Fragment = (Symbol(__DEV__ ? 'Fragment' : undefined) as any) as {   __isFragment: true   new (): {     $props: VNodeProps   } }

那么定義那么多的類型有什么意義呢?這是因為在 patch 階段,會根據(jù)不同的 VNode 類型來執(zhí)行不同的操作:

// packages/runtime-core/src/renderer.ts function baseCreateRenderer(   options: RendererOptions,   createHydrationFns?: typeof createHydrationFunctions ): any {   const patch: PatchFn = (     n1, n2, container, anchor = null, parentComponent = null, parentSuspense = null,     isSVG = false, optimized = false   ) => {     // 省略部分代碼     const { type, ref, shapeFlag } = n2     switch (type) {       case Text: // 處理文本節(jié)點         processText(n1, n2, container, anchor)         break       case Comment: // 處理注釋節(jié)點         processCommentNode(n1, n2, container, anchor)         break       case Static: // 處理靜態(tài)節(jié)點         if (n1 == null) {           mountStaticNode(n2, container, anchor, isSVG)         } else if (__DEV__) {           patchStaticNode(n1, n2, container, isSVG)         }         break       case Fragment: // 處理Fragment節(jié)點         processFragment(...)         break       default:         if (shapeFlag & ShapeFlags.ELEMENT) { // 元素類型           processElement(...)         } else if (shapeFlag & ShapeFlags.COMPONENT) { // 組件類型           processComponent(...)         } else if (shapeFlag & ShapeFlags.TELEPORT) { // teleport內(nèi)置組件           ;(type as typeof TeleportImpl).process(...)         } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {           ;(type as typeof SuspenseImpl).process(...)         }     }   } }

介紹完 type 參數(shù)后,接下來我們來看 props 參數(shù),具體如下圖所示:

props 參數(shù)

function _createVNode(   type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,   props: (Data & VNodeProps) | null = null, ): VNode { ... }

props 參數(shù)的類型是聯(lián)合類型,這里我們來分析 Data & VNodeProps 交叉類型:

Vue 3.0進階之如何使用VNode

其中 Data 類型是通過 TypeScript 內(nèi)置的工具類型 Record 來定義的:

export type Data = Record type Record = {   [P in K]: T; };

而 VNodeProps 類型是通過類型別名來定義的,除了含有 key 和 ref 屬性之外,其他的屬性主要是定義了與生命周期有關(guān)的鉤子:

// packages/runtime-core/src/vnode.ts export type VNodeProps = {   key?: string | number   ref?: VNodeRef    // vnode hooks   onVnodeBeforeMount?: VNodeMountHook | VNodeMountHook[]   onVnodeMounted?: VNodeMountHook | VNodeMountHook[]   onVnodeBeforeUpdate?: VNodeUpdateHook | VNodeUpdateHook[]   onVnodeUpdated?: VNodeUpdateHook | VNodeUpdateHook[]   onVnodeBeforeUnmount?: VNodeMountHook | VNodeMountHook[]   onVnodeUnmounted?: VNodeMountHook | VNodeMountHook[] }

3.2 邏輯說明

createVNode 函數(shù)內(nèi)部涉及較多的處理邏輯,這里我們只分析主要的邏輯:

// packages/runtime-core/src/vnode.ts function _createVNode(   type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,   props: (Data & VNodeProps) | null = null,   children: unknown = null,   patchFlag: number = 0,   dynamicProps: string[] | null = null,   isBlockNode = false ): VNode {   // 處理VNode類型,比如處理動態(tài)組件的場景:   if (isVNode(type)) {     const cloned = cloneVNode(type, props, true /* mergeRef: true */)     if (children) {       normalizeChildren(cloned, children)     }     return cloned   }    // 類組件規(guī)范化處理   if (isClassComponent(type)) {     type = type.__vccOpts   }    // 類和樣式規(guī)范化處理   if (props) {     // 省略相關(guān)代碼   }    // 把vnode的類型信息轉(zhuǎn)換為位圖   const shapeFlag = isString(type)     ? ShapeFlags.ELEMENT // ELEMENT = 1     : __FEATURE_SUSPENSE__ && isSuspense(type)       ? ShapeFlags.SUSPENSE // SUSPENSE = 1 << 7,       : isTeleport(type)         ? ShapeFlags.TELEPORT // TELEPORT = 1 << 6,         : isObject(type)           ? ShapeFlags.STATEFUL_COMPONENT // STATEFUL_COMPONENT = 1 << 2,           : isFunction(type)             ? ShapeFlags.FUNCTIONAL_COMPONENT // FUNCTIONAL_COMPONENT = 1 << 1,             : 0    // 創(chuàng)建VNode對象   const vnode: VNode = {     __v_isVNode: true,     [ReactiveFlags.SKIP]: true,     type,     props,     // ...   }    // 子元素規(guī)范化處理   normalizeChildren(vnode, children)   return vnode }

介紹完 createVNode 函數(shù)之后,阿寶哥再來介紹另一個比較重要的函數(shù) —— normalizeVNode。

四、如何創(chuàng)建規(guī)范的 VNode 對象?

normalizeVNode 函數(shù)的作用,用于將傳入的 child 參數(shù)轉(zhuǎn)換為規(guī)范的 VNode 對象。

// packages/runtime-core/src/vnode.ts export function normalizeVNode(child: VNodeChild): VNode {   if (child == null || typeof child === 'boolean') { // null/undefined/boolean -> Comment     return createVNode(Comment)   } else if (isArray(child)) { // array -> Fragment     return createVNode(Fragment, null, child)   } else if (typeof child === 'object') { // VNode -> VNode or mounted VNode -> cloned VNode     return child.el === null ? child : cloneVNode(child)   } else { // primitive types:'foo' or 1     return createVNode(Text, null, String(child))   } }

由以上代碼可知,normalizeVNode 函數(shù)內(nèi)部會根據(jù) child 參數(shù)的類型進行不同的處理:

4.1 null / undefined -> Comment

expect(normalizeVNode(null)).toMatchObject({ type: Comment }) expect(normalizeVNode(undefined)).toMatchObject({ type: Comment })

4.2 boolean -> Comment

expect(normalizeVNode(true)).toMatchObject({ type: Comment }) expect(normalizeVNode(false)).toMatchObject({ type: Comment })

4.3 array -> Fragment

expect(normalizeVNode(['foo'])).toMatchObject({ type: Fragment })

4.4 VNode -> VNode

const vnode = createVNode('div') expect(normalizeVNode(vnode)).toBe(vnode)

4.5 mounted VNode -> cloned VNode

const mounted = createVNode('div') mounted.el = {} const normalized = normalizeVNode(mounted) expect(normalized).not.toBe(mounted) expect(normalized).toEqual(mounted)

4.6 primitive types

expect(normalizeVNode('foo')).toMatchObject({ type: Text, children: `foo` }) expect(normalizeVNode(1)).toMatchObject({ type: Text, children: `1` })

五、阿寶哥有話說

5.1 如何判斷是否為 VNode 對象?

// packages/runtime-core/src/vnode.ts export function isVNode(value: any): value is VNode {   return value ? value.__v_isVNode === true : false }

在 VNode 對象中含有一個 __v_isVNode 內(nèi)部屬性,利用該屬性可以用來判斷當前對象是否為 VNode 對象。

5.2 如何判斷兩個 VNode 對象的類型是否相同?

// packages/runtime-core/src/vnode.ts export function isSameVNodeType(n1: VNode, n2: VNode): boolean {   // 省略__DEV__環(huán)境的處理邏輯   return n1.type === n2.type && n1.key === n2.key }

在 Vue 3 中,是通過比較 VNode 對象的 type 和 key 屬性,來判斷兩個 VNode 對象的類型是否相同。

5.3 如何快速創(chuàng)建某些類型的 VNode 對象?

在 Vue 3 內(nèi)部提供了 createTextVNode 、createCommentVNode 和 createStaticVNode  函數(shù)來快速的創(chuàng)建文本節(jié)點、注釋節(jié)點和靜態(tài)節(jié)點:

createTextVNode

export function createTextVNode(text: string = ' ', flag: number = 0): VNode {   return createVNode(Text, null, text, flag) }

createCommentVNode

export function createCommentVNode(   text: string = '',   asBlock: boolean = false ): VNode {   return asBlock     ? (openBlock(), createBlock(Comment, null, text))     : createVNode(Comment, null, text) }

createStaticVNode

export function createStaticVNode(   content: string,   numberOfNodes: number ): VNode {   const vnode = createVNode(Static, null, content)   vnode.staticCount = numberOfNodes   return vnode }

感謝各位的閱讀,以上就是“Vue 3.0進階之如何使用VNode”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Vue 3.0進階之如何使用VNode這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!


網(wǎng)頁標題:Vue3.0進階之如何使用VNode
文章出自:http://fisionsoft.com.cn/article/joidpd.html