全局组件、局部组件
// 全局注册组件
import hello from './components/HelloWorld.vue'
app.component('hello',hello)
// 局部注册:在组件中引入即可使用
import hello from "../../components/HelloWorld.vue";
<hello :msg="msg"></hello>
递归组件
// 父组件
<template>
<div class="side">
<Tree :data="data"></Tree>
</div>
</template>
<script setup lang='ts'>
import Tree from "../components/tree.vue"
const data = reactive([
{
title: '01',
children: [{
title: '1-1',
children: [
{
title: '1-1-1',
}, {
title: '1-1-2',
}, {
title: '1-1-3',
}
]
},
{
title: '1-2',
children: [{
title: '1-2-1',
}]
},
{
title: '1-3',
}
]
},
{
title: '02',
children: [{
title: '2-1',
children: [
{
title: '2-1-1',
}, {
title: '2-1-2',
}
]
},
{
title: '2-2',
},
{
title: '2-3',
children: [{
title: '2-3-1',
}]
}
]
},
{
title: '03',
},
])
</script>
<style lang='less' scoped>
.side {
min-width: 200px;
height: calc(100vh - 60px);
background: rgb(163, 245, 218);
}
</style>
// 子组件
<template>
<div v-for="item in data" :key="item.title" class="ml-20">
{{ item.title }}
<TreeItem v-if="item?.children?.length" :data="item.children">
</TreeItem>
</div>
</template>
<script setup lang='ts'>
defineProps({
data: Object
})
</script>
<script lang="ts">
export default {
name: 'TreeItem' // 给自己起一个name,递归使用
}
</script>
<style lang='less' scoped>
</style>
动态组件
import A from './A.vue'
import B from './B.vue'
<component :is="A"></component>
==注意事项 ==
- 在Vue2 的时候is 是通过组件名称切换的, 在Vue3 setup 是通过组件实例切换的
- 如果你把组件实例放到Reactive, Vue会给你一个警告
runtime-core.esm-bundler.js:38 [Vue 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`.
Component that was made reactive:
- 这是因为reactive 会进行proxy 代理, 而我们组件代理之后毫无用处 ,节省性能开销, 推荐我们使用shallowRef 或者 markRaw 跳过proxy 代理。
const tab = reactive([{
name: "A组件",
comName: markRaw(A)
}, {
name: "B组件",
comName: markRaw(B)
}])
异步组件(性能优化)
-
在大型应用中,需要加载的资源较多,导致加载时间过长,所以我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。
-
而Vue 提供的异步组件就实现了这个功能,使用 Vue 中的工厂函数的方式定义组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染时才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
-
用webpack提供的import语法,实现文件的分割加载
-
异步组件打包后会单独打包成一个js文件,从而会减少index…js包的体积,会加快项目首屏加载速度,减少白屏时间,提升用户体验。
-
静态引入:父组件和子组件会一起渲染,异步引入组件父使用的时候才加载,会减少内存的使用,提升性能。
-
使用步骤:
-
异步引入组件
import {defineAsyncComponent} from 'vue' const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
-
使用
Suspense
包裹组件,并配置好default
与fallback
-
等待异步组件时渲染一些额外内容,让应用有更好的用户体验
<template> <div class="app"> <h3>我是App组件</h3> <Suspense> //标签里边是异步组件 <template v-slot:default> <Child/> </template> <template v-slot:fallback> //组件未加载出来显示 <h3>加载中.....</h3> </template> </Suspense> </div> </template>