全局组件
创建组件 GlobalComponent.vue
<template>
<h1>this is globalComponent</h1>
</template>
在 main.ts 中引入组件
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import GlobalComponent from "./component/glocalComponent"
const app = createApp(App)
app.component("GlobalComponent",GlobalComponent)
app.mount("#app")
递归组件
子组件 Helloworld.vue
<template>
<ul v-for="(item,index) in data" :key="index">
<li>{{ item.name }}</li>
<HelloWorld v-if="item.children?.length!=0" :data="item.children"></HelloWorld>
</ul>
</template>
<script setup lang="ts">
type TreeList = {
name: string;
children?: TreeList[] | [];
}
type Props<T> = {
data?: T[] | [];
};
defineProps<Props<TreeList>>()
</script>
父组件调用
<template>
<div> this is app</div>
<HelloWorld :data="listData"></HelloWorld>
</template>
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
const listData = [
{
name:"1",
children:[
{name:'1-1'},
{name:'1-2'},
{name:'1-3'},
{name:'1-4'},
]
},
{
name:'2',
children:[
{
name:"2-1",
children:[
{name:'2-1-1'}
]
},
{
name:"2-2"
}
]
},
{
name:"3"
}
]
</script>
打印效果
配置递归组件起别名
在原先的基础上新创建 script
<script>
export default {
name:'xxx' // 在递归过程中可以直接调用 xxx
}
</script>
动态组件
使用 component 标签通过属性 is 动态渲染组件
<template>
<div> this is app</div>
<button @click="handleClick">切换</button>
<component :is="xxx"></component>
</template>
<script setup lang="ts">
import ComA from "./components/comA.vue"
import ComB from "./components/comB.vue"
import {reactive,ref,markRaw} from "vue"
const ComponentName = reactive({
"ComA":markRaw(ComA),
"ComB":markRaw(ComB),
});
const xxx = ref(ComponentName['ComA'])
const handleClick = ()=>{
xxx.value = ComponentName["ComB"]
}
</script>
动态渲染的组件实例会被 proxy 劫持, 造成不必要的性能浪费, 可使用 markRaw(Component) 包裹组件, 会添加 “__ skip __”属性, vue3 遇到改属性会跳过劫持
异步组件
suspense 在官网还未正式发布
suspense 组件,使用场景可用于骨架屏效果
子组件声明
<template>
<h1>this is Component {{ data }}</h1>
</template>
<script setup lang="ts">
import {ref} from "vue"
const response = ()=>{
return new Promise((resolve)=>{
setTimeout(()=>{
resolve("helloWorld Component")
},5000)
})
}
const data = ref<string>("");
const res = await response();
data.value = res as string;
</script>
父组件使用
<template>
<HelloWorld></HelloWorld>
<suspense>
<template #default>
<AsyncComponent></AsyncComponent>
</template>
<template #fallback>
<div>loging...</div>
</template>
</suspense>
</template>
<script setup lang="ts">
import {defineAsyncComponent} from "vue"
import ComA from "./components/comA.vue"
import ComB from "./components/comB.vue"
const AsyncComponent = defineAsyncComponent(()=>import("./components/HelloWorld.vue"))
</script>
异步组件的完整写法
const AsyncComponent = defineAsyncComponent({
loader:()=>import("./components/HelloWorld.vue") , // 异步加载函数
loadingComponent:ComA, // 加载时使用的组件
delay:200, // 展示加载组件前的延迟, 默认200毫秒
errorComponent:ComB,// 加载失败后的展示组件
timeout:1 // 设定超时时间,加载超时会展示失败组件
})