当前位置: 首页> 房产> 建材 > vue(十二) 组件二 动态组件(Component)和异步组件(defineAsyncComponent)

vue(十二) 组件二 动态组件(Component)和异步组件(defineAsyncComponent)

时间:2025/7/9 21:20:18来源:https://blog.csdn.net/chengcheng9876/article/details/139060286 浏览次数:0次

文章目录

  • 组件注册
    • 1.全局注册
    • 2.局部注册
    • 3.组件名格式
  • 动态组件
  • 异步组件
    • 1.基本使用
    • 2.加载与错误状态
    • 3.搭配Suspense 组件使用


组件注册

一个 Vue 组件在使用前需要先被“注册”,这样 Vue 才能在渲染模板时找到其对应的实现。组件注册有两种方式:全局注册和局部注册。

1.全局注册

使用 Vue 应用实例的 .component() 方法,让组件在当前 Vue 应用中全局可用。

import { createApp } from 'vue'
const app = createApp({})
app.component(// 注册的名字'MyComponent',// 组件的实现{/* ... */}
)
  1. 单文件组件,注册被导入的 .vue 文件:
    import MyComponent from './App.vue'
    app.component('MyComponent', MyComponent)
    // 可以链式调用
    app.component('ComponentA', ComponentA).component('ComponentB', ComponentB).component('ComponentC', ComponentC)
    // 全局注册的组件可以在此应用的任意组件的模板中使用:
    // <!-- 这在当前应用的任意组件中都可用 -->
    <ComponentA/>
    <ComponentB/>
    <ComponentC/>
    

注:所有的子组件也可以使用全局注册的组件,这意味着这三个组件也都可以在彼此内部使用。

  1. 存在的问题
  • 全局注册,没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。
  • 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性

2.局部注册

局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好。

  1. 使用 <script setup> 的单文件组件中,导入的组件可以直接在模板中使用,无需注册:
    import ComponentA from './ComponentA.vue'
    </script><template><ComponentA />
    </template>在这里插入代码片
    
  2. <script setup>,则需要使用 components 选项来显式注册:
    import ComponentA from './ComponentA.js'
    export default {components: {ComponentA},setup() {// ...}
    }
    
  3. components 对象里的属性,它们的 key 名就是注册的组件名,而值就是相应组件的实现。上面的例子中使用的是 ES2015 的缩写语法,等价于:
    export default {components: {ComponentA: ComponentA}// ...
    }
    //ComponentA 注册后仅在当前组件可用,而在任何的子组件或更深层的子组件中都不可用。
    

注:局部注册的组件在后代组件中不可用

3.组件名格式

使用 ComponentA作为组件名的注册格式,这是因为:

  • ComponentA是合法的 JavaScript 标识符。这使得在 JavaScript 中导入和注册组件都很容易,同时 IDE 也能提供较好的自动补全。
  • <ComponentA/> 在模板中更明显地表明了这是一个 Vue 组件,而不是原生 HTML 元素。同时也能够将 Vue 组件和自定义元素 (web components) 区分开来。

在单文件组件和内联字符串模板中,我们都推荐这样做。但是,ComponentA 的标签名在 DOM 内模板中是不可用的,详情参见 DOM 内模板解析注意事项。

Vue 支持将模板中使用 kebab-case 的标签解析为使用 ComponentA注册的组件。这意味着一个以 ComponentA为名注册的组件,在模板中可以通过 <component-a> <component-a> 引用。能够使用同样的 JavaScript 组件注册代码来配合不同来源的模板。

动态组件

  1. 动态组件的概念

多个组件通过component标签挂载在同一个组件中,通过触发动作进行动态切换。常搭配<keep-alive></keep-alive>使用,多用于tab栏的切换等场景

  1. 动态组件的使用和实现
    通过设置<component>标签的is属性来指定要渲染的组件。
// Component.vue
<template><div><buttonv-for="(item, index) in tabs":key="index"@click="currentTab = item.comName">{{ item.name }}</button><component :is="currentTab" class="tab"></component></div>
</template><script lang="ts">
import { reactive, reactive, shallowRef } from 'vue'
import ComA from './components/ComA.vue'
import ComB from './components/ComB.vue'
import { reactive, shallowRef } from 'vue'
export default {setup () {// reactive 会使数据变成响应式,此处为了节省性能开销,可以使用 shallowRef 或者 markRaw 跳过 proxy 代理const currentTab = shallowRef(ComA)const tabs = reactive([{name: 'ComA',comName: shallowRef(ComA)},{name: 'ComB',comName: shallowRef(ComB)},])return {currentTab,tabs,}}}
</script>
  1. vue 3 和vue2.0区别
  • <component :is=>标签可以动态渲染不同的组件,可以根据变量的值来动态切换不同的子组件。
  • vue 2 中is接收的是组件名称,
  • vue 3 中is接收的是组件实例。
  • 也可以使用 is attribute 来创建一般的 HTML 元素。
  • 为了节省性能开销,可以使用shallowRef或者markRaw跳过proxy代理。
  • 当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载。可以通过 <KeepAlive> 组件强制被切换掉的组件仍然保持“存活”的状态。

异步组件

1.基本使用

在大型项目中,可能需要拆分应用为更小的块,并仅在需要时再从服务器加载相关组件。Vue 提供了defineAsyncComponent 方法来实现此功能:

  1. 获取组件

    import { defineAsyncComponent } from 'vue'
    const AsyncComp = defineAsyncComponent(() => {return new Promise((resolve, reject) => {// ...从服务器获取组件resolve(/* 获取到的组件 */)})
    })
    // ... 像使用其他一般组件一样使用 `AsyncComp`
    

    defineAsyncComponent 方法接收一个返回 Promise 的加载函数。这个 Promise 的 resolve 回调方法应该在从服务器获得组件定义时调用。你也可以调用 reject(reason) 表明加载失败。

  2. ES module动态导入

    ES 模块动态导入也会返回一个 Promise,所以多数情况下会将它和 defineAsyncComponent 搭配使用。类似 Vite 和 Webpack 这样的构建工具也支持此语法 (并且会将它们作为打包时的代码分割点),因此可以用它来导入 Vue 单文件组件:

    <template><div>异步组件<AsyncComponent /></div>
    </template><script lang="ts">
    import { defineAsyncComponent, defineComponent } from 'vue'
    const AsyncComponent = defineAsyncComponent(() => import('./components/myAsyncCom.vue'))
    export default defineComponent({components: {AsyncComponent},setup () {return {}}
    })
    </script>
    <style scoped>
    </style>
    

    最后得到的AsyncComp是一个外层包装过的组件,仅在页面需要它渲染时才会调用加载内部实际组件的函数。它会将接收到的props和插槽传给内部组件,所以你可以使用这个异步的包装组件无缝地替换原始组件,同时实现延迟加载。

    与普通组件一样,异步组件可以使用app.component()全局注册:

    app.component('MyAsyncCom', defineAsyncComponent(() =>import('./components/MyAsyncCom.vue')
    ))
    

    也可以直接在父组件中直接定义它们:

    <template><div>异步组件<AsyncComponent /></div>
    </template><script lang="ts">
    import { defineAsyncComponent, defineComponent } from 'vue'
    const AsyncComponent = defineAsyncComponent(() => import('./components/myAsyncCom.vue'))
    export default defineComponent({components: {AsyncComponent},setup () {return {}}
    })
    </script>
    <style scoped>
    </style>
    

2.加载与错误状态

异步操作不可避免地会涉及到加载和错误状态,因此 defineAsyncComponent() 也支持在高级选项中处理这些状态:

const AsyncComp = defineAsyncComponent({// 加载函数loader: () => import('./Foo.vue'),// 加载异步组件时使用的组件loadingComponent: LoadingComponent,// 展示加载组件前的延迟时间,默认为 200msdelay: 200,// 加载失败后展示的组件errorComponent: ErrorComponent,// 如果提供了一个 timeout 时间限制,并超时了// 也会显示这里配置的报错组件,默认值是:Infinitytimeout: 3000
})
  • 如果提供了一个加载组件,它将在内部组件加载时先行显示。在加载组件显示之前有一个默认的 200ms 延迟——这是因为在网络状况较好时,加载完成得很快,加载组件和最终组件之间的替换太快可能产生闪烁,反而影响用户感受。
  • 如果提供了一个报错组件,则它会在加载器函数返回的 Promise 抛错时被渲染。可以指定一个超时时间,在请求耗时超过指定时间时也会渲染报错组件。

3.搭配Suspense 组件使用

异步组件可以搭配内置的 <Suspense> 组件一起使用,后面组件会对 <Suspense> 进行专门介绍。

关键字:vue(十二) 组件二 动态组件(Component)和异步组件(defineAsyncComponent)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: