自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Vue 3.0 進(jìn)階之動(dòng)態(tài)組件探秘

開發(fā) 前端
本文是 Vue 3.0 進(jìn)階系列 的第四篇文章,在這篇文章中,阿寶哥將介紹 Vue 3 中的內(nèi)置組件 —— component,該組件的作用是渲染一個(gè) “元組件” 為動(dòng)態(tài)組件。

 [[383029]]

本文轉(zhuǎn)載自微信公眾號(hào)「全棧修仙之路」,作者全棧修仙之路。轉(zhuǎn)載本文請(qǐng)聯(lián)系全棧修仙之路公眾號(hào)。 

本文是 Vue 3.0 進(jìn)階系列 的第四篇文章,在這篇文章中,阿寶哥將介紹 Vue 3 中的內(nèi)置組件 —— component,該組件的作用是渲染一個(gè) “元組件” 為動(dòng)態(tài)組件。如果你對(duì)動(dòng)態(tài)組件還不了解的話也沒關(guān)系,文中阿寶哥會(huì)通過(guò)具體的示例,來(lái)介紹動(dòng)態(tài)組件的應(yīng)用。

由于動(dòng)態(tài)組件內(nèi)部與組件注冊(cè)之間有一定的聯(lián)系,所以為了讓大家能夠更好地了解動(dòng)態(tài)組件的內(nèi)部原理,阿寶哥會(huì)先介紹組件注冊(cè)的相關(guān)知識(shí)。

一、組件注冊(cè)

1.1 全局注冊(cè)

在 Vue 3.0 中,通過(guò)使用 app 對(duì)象的 component 方法,可以很容易地注冊(cè)或檢索全局組件。component 方法支持兩個(gè)參數(shù):

  • name:組件名稱;
  • component:組件定義對(duì)象。

接下來(lái),我們來(lái)看一個(gè)簡(jiǎn)單的示例:

  1. <div id="app"
  2.    <component-a></component-a> 
  3.    <component-b></component-b> 
  4.    <component-c></component-c> 
  5. </div> 
  6. <script> 
  7.    const { createApp } = Vue 
  8.    const app = createApp({}); // ① 
  9.    app.component('component-a', { // ② 
  10.      template: "<p>我是組件A</p>" 
  11.    }); 
  12.    app.component('component-b', { 
  13.      template: "<p>我是組件B</p>" 
  14.    }); 
  15.    app.component('component-c', { 
  16.      template: "<p>我是組件C</p>" 
  17.    }); 
  18.    app.mount('#app') // ③ 
  19. </script> 

在以上代碼中,我們通過(guò) app.component 方法注冊(cè)了 3 個(gè)組件,這些組件都是全局注冊(cè)的 。也就是說(shuō)它們?cè)谧?cè)之后可以用在任何新創(chuàng)建的組件實(shí)例的模板中。

該示例的代碼比較簡(jiǎn)單,主要包含 3 個(gè)步驟:創(chuàng)建 App 對(duì)象、注冊(cè)全局組件和應(yīng)用掛載。其中創(chuàng)建 App 對(duì)象的細(xì)節(jié),阿寶哥會(huì)在后續(xù)的文章中單獨(dú)介紹,下面我們將重點(diǎn)分析其他 2 個(gè)步驟,首先我們先來(lái)分析注冊(cè)全局組件的過(guò)程。

1.2 注冊(cè)全局組件的過(guò)程

在以上示例中,我們使用 app 對(duì)象的 component 方法來(lái)注冊(cè)全局組件:

  1. app.component('component-a', { 
  2.   template: "<p>我是組件A</p>" 
  3. }); 

當(dāng)然,除了注冊(cè)全局組件之外,我們也可以注冊(cè)局部組件,因?yàn)榻M件中也接受一個(gè) components 的選項(xiàng):

  1. const app = Vue.createApp({ 
  2.   components: { 
  3.     'component-a': ComponentA, 
  4.     'component-b': ComponentB 
  5.   } 
  6. }) 

需要注意的是,局部注冊(cè)的組件在其子組件中是不可用的。接下來(lái),我們來(lái)繼續(xù)介紹注冊(cè)全局組件的過(guò)程。對(duì)于前面的示例來(lái)說(shuō),我們使用的 app.component 方法被定義在 runtime-core/src/apiCreateApp.ts 文件中:

  1. export function createAppAPI<HostElement>( 
  2.   render: RootRenderFunction, 
  3.   hydrate?: RootHydrateFunction 
  4. ): CreateAppFunction<HostElement> { 
  5.   return function createApp(rootComponent, rootProps = null) { 
  6.     const context = createAppContext() 
  7.     const installedPlugins = new Set() 
  8.     let isMounted = false 
  9.  
  10.     const app: App = (context.app = { 
  11.       // 省略部分代碼 
  12.       _context: context, 
  13.  
  14.       // 注冊(cè)或檢索全局組件 
  15.       component(name: string, component?: Component): any { 
  16.         if (__DEV__) { 
  17.           validateComponentName(name, context.config) 
  18.         } 
  19.         if (!component) { // 獲取name對(duì)應(yīng)的組件 
  20.           return context.components[name
  21.         } 
  22.         if (__DEV__ && context.components[name]) { // 重復(fù)注冊(cè)提示 
  23.           warn(`Component "${name}" has already been registered in target app.`) 
  24.         } 
  25.         context.components[name] = component // 注冊(cè)全局組件 
  26.         return app 
  27.       }, 
  28.     }) 
  29.  
  30.     return app 
  31.   } 

當(dāng)所有的組件都注冊(cè)成功之后,它們會(huì)被保存到 context 對(duì)象的 components 屬性中,具體如下圖所示:

顧名思義 context 是表示應(yīng)用的上下文對(duì)象,那么該對(duì)象是如何創(chuàng)建的呢?其實(shí),該對(duì)象是通過(guò) createAppContext 函數(shù)來(lái)創(chuàng)建的:

  1. const context = createAppContext() 

而 createAppContext 函數(shù)被定義在 runtime-core/src/apiCreateApp.ts 文件中:

  1. // packages/runtime-core/src/apiCreateApp.ts 
  2. export function createAppContext(): AppContext { 
  3.   return { 
  4.     app: null as any
  5.     config: { // 應(yīng)用的配置對(duì)象 
  6.       isNativeTag: NO
  7.       performance: false
  8.       globalProperties: {}, 
  9.       optionMergeStrategies: {}, 
  10.       isCustomElement: NO
  11.       errorHandler: undefined, 
  12.       warnHandler: undefined 
  13.     }, 
  14.     mixins: [], // 保存應(yīng)用內(nèi)的混入 
  15.     components: {}, // 保存全局組件的信息 
  16.     directives: {}, // 保存全局指令的信息 
  17.     provides: Object.create(null
  18.   } 

分析完 app.component 方法之后,是不是覺得組件注冊(cè)的過(guò)程還是挺簡(jiǎn)單的。那么對(duì)于已注冊(cè)的組件,何時(shí)會(huì)被使用呢?要回答這個(gè)問(wèn)題,我們就需要分析另一個(gè)步驟 —— 應(yīng)用掛載。

1.3 應(yīng)用掛載的過(guò)程

為了更加直觀地了解應(yīng)用掛載的過(guò)程,阿寶哥利用 Chrome 開發(fā)者工具的 Performance 標(biāo)簽欄,記錄了應(yīng)用掛載的主要過(guò)程:

在上圖中我們發(fā)現(xiàn)了一個(gè)與組件相關(guān)的函數(shù) resolveComponent。很明顯,該函數(shù)用于解析組件,且該函數(shù)在 render 方法中會(huì)被調(diào)用。在源碼中,我們找到了該函數(shù)的定義:

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. const COMPONENTS = 'components' 
  3.  
  4. export function resolveComponent(name: string): ConcreteComponent | string { 
  5.   return resolveAsset(COMPONENTS, name) || name 

由以上代碼可知,在 resolveComponent 函數(shù)內(nèi)部,會(huì)繼續(xù)調(diào)用 resolveAsset 函數(shù)來(lái)執(zhí)行具體的解析操作。在分析 resolveAsset 函數(shù)的具體實(shí)現(xiàn)之前,我們?cè)?resolveComponent 函數(shù)內(nèi)部加個(gè)斷點(diǎn),來(lái)一睹 render 方法的 “芳容”:

在上圖中,我們看到了解析組件的操作,比如 _resolveComponent("component-a")。前面我們已經(jīng)知道在 resolveComponent 函數(shù)內(nèi)部會(huì)繼續(xù)調(diào)用 resolveAsset 函數(shù),該函數(shù)的具體實(shí)現(xiàn)如下:

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. function resolveAsset( 
  3.   type: typeof COMPONENTS | typeof DIRECTIVES, 
  4.   name: string, 
  5.   warnMissing = true 
  6. ) { 
  7.   const instance = currentRenderingInstance || currentInstance 
  8.   if (instance) { 
  9.     const Component = instance.type 
  10.     // 省略大部分處理邏輯 
  11.     const res = 
  12.       // 局部注冊(cè) 
  13.       // check instance[type] first for components with mixin or extends. 
  14.       resolve(instance[type] || (Component as ComponentOptions)[type], name) || 
  15.       // 全局注冊(cè) 
  16.       resolve(instance.appContext[type], name
  17.     return res 
  18.   } else if (__DEV__) { 
  19.     warn( 
  20.       `resolve${capitalize(type.slice(0, -1))} ` + 
  21.         `can only be used in render() or setup().` 
  22.     ) 
  23.   } 

因?yàn)樽?cè)組件時(shí),使用的是全局注冊(cè)的方式,所以解析的過(guò)程會(huì)執(zhí)行 resolve(instance.appContext[type], name) 該語(yǔ)句,其中 resolve 方法的定義如下:

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. function resolve(registry: Record<string, any> | undefined, name: string) { 
  3.   return ( 
  4.     registry && 
  5.     (registry[name] || 
  6.       registry[camelize(name)] || 
  7.       registry[capitalize(camelize(name))]) 
  8.   ) 

分析完以上的處理流程,我們?cè)诮馕鋈肿?cè)的組件時(shí),會(huì)通過(guò) resolve 函數(shù)從應(yīng)用的上下文對(duì)象中獲取已注冊(cè)的組件對(duì)象。

  1. (function anonymous() { 
  2.     const _Vue = Vue 
  3.  
  4.     return function render(_ctx, _cache) { 
  5.         with (_ctx) { 
  6.           const {resolveComponent: _resolveComponent, createVNode: _createVNode,  
  7.             Fragment: _Fragment, openBlock: _openBlock, createBlock: _createBlock} = _Vue 
  8.  
  9.             const _component_component_a = _resolveComponent("component-a"
  10.             const _component_component_b = _resolveComponent("component-b"
  11.             const _component_component_c = _resolveComponent("component-c"
  12.  
  13.             return (_openBlock(), 
  14.             _createBlock(_Fragment, null, [ 
  15.               _createVNode(_component_component_a),  
  16.               _createVNode(_component_component_b),  
  17.               _createVNode(_component_component_c)], 64)) 
  18.         } 
  19.     } 
  20. }) 

在獲取到組件之后,會(huì)通過(guò) _createVNode 函數(shù)創(chuàng)建 VNode 節(jié)點(diǎn)。然而,關(guān)于 VNode 是如何被渲染成真實(shí)的 DOM 元素這個(gè)過(guò)程,阿寶哥就不繼續(xù)往下介紹了,后續(xù)會(huì)寫專門的文章來(lái)單獨(dú)介紹這塊的內(nèi)容,接下來(lái)我們將介紹動(dòng)態(tài)組件的相關(guān)內(nèi)容。

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

在 Vue 3 中為我們提供了一個(gè) component 內(nèi)置組件,該組件可以渲染一個(gè) “元組件” 為動(dòng)態(tài)組件。根據(jù) is 的值,來(lái)決定哪個(gè)組件被渲染。如果 is 的值是一個(gè)字符串,它既可以是 HTML 標(biāo)簽名稱也可以是組件名稱。對(duì)應(yīng)的使用示例如下:

  1. <!--  動(dòng)態(tài)組件由 vm 實(shí)例的 `componentId` property 控制 --> 
  2. <component :is="componentId"></component> 
  3.  
  4. <!-- 也能夠渲染注冊(cè)過(guò)的組件或 prop 傳入的組件--> 
  5. <component :is="$options.components.child"></component> 
  6.  
  7. <!-- 可以通過(guò)字符串引用組件 --> 
  8. <component :is="condition ? 'FooComponent' : 'BarComponent'"></component> 
  9.  
  10. <!-- 可以用來(lái)渲染原生 HTML 元素 --> 
  11. <component :is="href ? 'a' : 'span'"></component> 

2.1 綁定字符串類型

介紹完 component 內(nèi)置組件,我們來(lái)舉個(gè)簡(jiǎn)單的示例:

  1. <div id="app"
  2.    <button 
  3.       v-for="tab in tabs" 
  4.       :key="tab" 
  5.       @click="currentTab = 'tab-' + tab.toLowerCase()"
  6.       {{ tab }} 
  7.    </button> 
  8.    <component :is="currentTab"></component> 
  9. </div> 
  10. <script> 
  11.    const { createApp } = Vue 
  12.    const tabs = ['Home''My'
  13.    const app = createApp({ 
  14.      data() { 
  15.        return { 
  16.          tabs, 
  17.          currentTab: 'tab-' + tabs[0].toLowerCase() 
  18.        } 
  19.      }, 
  20.    }); 
  21.    app.component('tab-home', { 
  22.      template: `<div style="border: 1px solid;">Home component</div>` 
  23.    }) 
  24.    app.component('tab-my', { 
  25.      template: `<div style="border: 1px solid;">My component</div>` 
  26.    }) 
  27.    app.mount('#app'
  28. </script> 

在以上代碼中,我們通過(guò) app.component 方法全局注冊(cè)了 tab-home 和 tab-my 2 個(gè)組件。此外,在模板中,我們使用了 component 內(nèi)置組件,該組件的 is 屬性綁定了 data 對(duì)象的 currentTab 屬性,該屬性的類型是字符串。當(dāng)用戶點(diǎn)擊 Tab 按鈕時(shí),會(huì)動(dòng)態(tài)更新 currentTab 的值,從而實(shí)現(xiàn)動(dòng)態(tài)切換組件的功能。以上示例成功運(yùn)行后的結(jié)果如下圖所示:

看到這里你會(huì)不會(huì)覺得 component 內(nèi)置組件挺神奇的,感興趣的小伙伴繼續(xù)跟阿寶哥一起,來(lái)揭開它背后的秘密。下面我們利用 Vue 3 Template Explorer 在線工具,看一下 模板編譯的結(jié)果:

  1. const _Vue = Vue 
  2.  
  3. return function render(_ctx, _cache, $props, $setup, $data, $options) { 
  4.   with (_ctx) { 
  5.     const { resolveDynamicComponent: _resolveDynamicComponent, openBlock: _openBlock,  
  6.       createBlock: _createBlock } = _Vue 
  7.     return (_openBlock(), _createBlock(_resolveDynamicComponent(currentTab))) 
  8.   } 

通過(guò)觀察生成的渲染函數(shù),我們發(fā)現(xiàn)了一個(gè) resolveDynamicComponent 的函數(shù),根據(jù)該函數(shù)的名稱,我們可以知道它用于解析動(dòng)態(tài)組件,它被定義在 runtime-core/src/helpers/resolveAssets.ts 文件中,具體實(shí)現(xiàn)如下所示:

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. export function resolveDynamicComponent(component: unknown): VNodeTypes { 
  3.   if (isString(component)) { 
  4.     return resolveAsset(COMPONENTS, component, false) || component 
  5.   } else { 
  6.     // invalid types will fallthrough to createVNode and raise warning 
  7.     return (component || NULL_DYNAMIC_COMPONENT) as any 
  8.   } 

在 resolveDynamicComponent 函數(shù)內(nèi)部,若 component 參數(shù)是字符串類型,則會(huì)調(diào)用前面介紹的 resolveAsset 方法來(lái)解析組件:

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. function resolveAsset( 
  3.   type: typeof COMPONENTS | typeof DIRECTIVES, 
  4.   name: string, 
  5.   warnMissing = true 
  6. ) { 
  7.   const instance = currentRenderingInstance || currentInstance 
  8.   if (instance) { 
  9.     const Component = instance.type 
  10.     // 省略大部分處理邏輯 
  11.     const res = 
  12.       // 局部注冊(cè) 
  13.       // check instance[type] first for components with mixin or extends. 
  14.       resolve(instance[type] || (Component as ComponentOptions)[type], name) || 
  15.       // 全局注冊(cè) 
  16.       resolve(instance.appContext[type], name
  17.     return res 
  18.   } 

對(duì)于前面的示例來(lái)說(shuō),組件是全局注冊(cè)的,所以解析過(guò)程中會(huì)從 app.context 上下文對(duì)象的 components 屬性中獲取對(duì)應(yīng)的組件。當(dāng) currentTab 發(fā)生變化時(shí),resolveAsset 函數(shù)就會(huì)返回不同的組件,從而實(shí)現(xiàn)動(dòng)態(tài)組件的功能。

此外,如果 resolveAsset 函數(shù)獲取不到對(duì)應(yīng)的組件,則會(huì)返回當(dāng)前 component 參數(shù)的值。比如 resolveDynamicComponent('div') 將返回 'div' 字符串。

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. export const NULL_DYNAMIC_COMPONENT = Symbol() 
  3.  
  4. export function resolveDynamicComponent(component: unknown): VNodeTypes { 
  5.   if (isString(component)) { 
  6.     return resolveAsset(COMPONENTS, component, false) || component 
  7.   } else { 
  8.     return (component || NULL_DYNAMIC_COMPONENT) as any 
  9.   } 

細(xì)心的小伙伴可能也注意到了,在 resolveDynamicComponent 函數(shù)內(nèi)部,如果 component 參數(shù)非字符串類型,則會(huì)返回 component || NULL_DYNAMIC_COMPONENT 這行語(yǔ)句的執(zhí)行結(jié)果,其中 NULL_DYNAMIC_COMPONENT 的值是一個(gè) Symbol 對(duì)象。

2.2 綁定對(duì)象類型

了解完上述的內(nèi)容之后,我們來(lái)重新實(shí)現(xiàn)一下前面動(dòng)態(tài) Tab 的功能:

  1. <div id="app"
  2.    <button 
  3.       v-for="tab in tabs" 
  4.       :key="tab" 
  5.       @click="currentTab = tab"
  6.      {{ tab.name }} 
  7.    </button> 
  8.    <component :is="currentTab.component"></component> 
  9. </div> 
  10. <script> 
  11.    const { createApp } = Vue 
  12.    const tabs = [ 
  13.      { 
  14.        name'Home'
  15.        component: { 
  16.          template: `<div style="border: 1px solid;">Home component</div>` 
  17.        } 
  18.      }, 
  19.      { 
  20.        name'My'
  21.        component: { 
  22.          template: `<div style="border: 1px solid;">My component</div>` 
  23.        } 
  24.    }] 
  25.    const app = createApp({ 
  26.      data() { 
  27.        return { 
  28.          tabs, 
  29.          currentTab: tabs[0] 
  30.        } 
  31.      }, 
  32.    }); 
  33.    app.mount('#app'
  34. </script> 

在以上示例中,component 內(nèi)置組件的 is 屬性綁定了 currentTab 對(duì)象的 component 屬性,該屬性的值是一個(gè)對(duì)象。當(dāng)用戶點(diǎn)擊 Tab 按鈕時(shí),會(huì)動(dòng)態(tài)更新 currentTab 的值,導(dǎo)致 currentTab.component 的值也發(fā)生變化,從而實(shí)現(xiàn)動(dòng)態(tài)切換組件的功能。需要注意的是,每次切換的時(shí)候,都會(huì)重新創(chuàng)建動(dòng)態(tài)組件。但在某些場(chǎng)景下,你會(huì)希望保持這些組件的狀態(tài),以避免反復(fù)重渲染導(dǎo)致的性能問(wèn)題。

對(duì)于這個(gè)問(wèn)題,我們可以使用 Vue 3 的另一個(gè)內(nèi)置組件 —— keep-alive,將動(dòng)態(tài)組件包裹起來(lái)。比如:

  1. <keep-alive> 
  2.    <component :is="currentTab"></component> 
  3. </keep-alive>   

keep-alive 內(nèi)置組件的主要作用是用于保留組件狀態(tài)或避免重新渲染,使用它包裹動(dòng)態(tài)組件時(shí),會(huì)緩存不活動(dòng)的組件實(shí)例,而不是銷毀它們。關(guān)于 keep-alive 組件的內(nèi)部工作原理,阿寶哥后面會(huì)寫專門的文章來(lái)分析它,對(duì)它感興趣的小伙伴記得關(guān)注 Vue 3.0 進(jìn)階 系列喲。

三、阿寶哥有話說(shuō)

3.1 除了 component 內(nèi)置組件外,還有哪些內(nèi)置組件?

在 Vue 3 中除了本文介紹的 component 和 keep-alive 內(nèi)置組件之外,還提供了 transition、transition-group 、slot 和 teleport 內(nèi)置組件。

3.2 注冊(cè)全局組件與局部組件有什么區(qū)別?

注冊(cè)全局組件

  1. const { createApp, h } = Vue 
  2. const app = createApp({}); 
  3. app.component('component-a', { 
  4.   template: "<p>我是組件A</p>" 
  5. }); 

使用 app.component 方法注冊(cè)的全局的組件,被保存到 app 應(yīng)用對(duì)象的上下文對(duì)象中。而通過(guò)組件對(duì)象 components 屬性注冊(cè)的局部組件是保存在組件實(shí)例中。

注冊(cè)局部組件

  1. const { createApp, h } = Vue 
  2. const app = createApp({}); 
  3. const componentA = () => h('div''我是組件A'); 
  4. app.component('component-b', { 
  5.   components: { 
  6.     'component-a': componentA 
  7.   }, 
  8.   template: `<div> 
  9.     我是組件B,內(nèi)部使用了組件A 
  10.     <component-a></component-a>     
  11.   </div>` 
  12. }) 

解析全局注冊(cè)和局部注冊(cè)的組件

  1. // packages/runtime-core/src/helpers/resolveAssets.ts 
  2. function resolveAsset( 
  3.   type: typeof COMPONENTS | typeof DIRECTIVES, 
  4.   name: string, 
  5.   warnMissing = true 
  6. ) { 
  7.   const instance = currentRenderingInstance || currentInstance 
  8.   if (instance) { 
  9.     const Component = instance.type 
  10.     // 省略大部分處理邏輯 
  11.     const res = 
  12.       // 局部注冊(cè) 
  13.       // check instance[type] first for components with mixin or extends. 
  14.       resolve(instance[type] || (Component as ComponentOptions)[type], name) || 
  15.       // 全局注冊(cè) 
  16.       resolve(instance.appContext[type], name
  17.     return res 
  18.   } 

3.3 動(dòng)態(tài)組件能否綁定其他屬性?

component 內(nèi)置組件除了支持 is 綁定之外,也支持其他屬性綁定和事件綁定:

  1. <component :is="currentTab.component" :name="name" @click="sayHi"></component> 

這里阿寶哥使用 Vue 3 Template Explorer 這個(gè)在線工具,來(lái)編譯上述的模板:

  1. const _Vue = Vue 
  2. return function render(_ctx, _cache, $props, $setup, $data, $options) { 
  3.   with (_ctx) { 
  4.     const { resolveDynamicComponent: _resolveDynamicComponent,  
  5.       openBlock: _openBlock, createBlock: _createBlock } = _Vue 
  6.  
  7.     return (_openBlock(), _createBlock(_resolveDynamicComponent(currentTab.component), { 
  8.       namename
  9.       onClick: sayHi 
  10.     }, null, 8 /* PROPS */, ["name""onClick"])) 
  11.   } 

觀察以上的渲染函數(shù)可知,除了 is 綁定會(huì)被轉(zhuǎn)換為 _resolveDynamicComponent 函數(shù)調(diào)用之外,其他的屬性綁定都會(huì)被正常解析為 props 對(duì)象。

四、參考資源

Vue 3 官網(wǎng) - 應(yīng)用 API

Vue 3 官網(wǎng) - 內(nèi)置組件

 

責(zé)任編輯:武曉燕 來(lái)源: 全棧修仙之路
相關(guān)推薦

2021-02-16 16:41:45

Vue項(xiàng)目指令

2021-02-26 05:19:20

Vue 3.0 VNode虛擬

2021-02-28 20:41:18

Vue注入Angular

2021-02-19 23:07:02

Vue綁定組件

2021-02-18 08:19:21

Vue自定義Vue 3.0

2021-03-04 22:31:02

Vue進(jìn)階函數(shù)

2021-03-09 22:29:46

Vue 響應(yīng)式API

2021-03-08 00:08:29

Vue應(yīng)用掛載

2020-09-16 06:12:30

Vue.js 3.0Suspense組件前端

2020-09-28 15:48:37

開源技術(shù) 軟件

2021-09-05 07:35:58

lifecycleAndroid組件原理

2010-05-11 16:22:40

2020-10-13 08:24:31

Vue3.0系列

2024-10-15 07:42:09

Vue動(dòng)態(tài)加載

2020-04-22 14:15:32

Vue 3.0語(yǔ)法前端

2009-07-27 10:08:48

Java 7動(dòng)態(tài)語(yǔ)言JVM

2025-01-22 13:05:58

2011-05-20 09:43:23

JDK7

2022-04-25 07:36:21

組件數(shù)據(jù)函數(shù)

2010-06-28 09:26:15

JDK 7Swing組件Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)