vue3之全局组件、局部组件、递归组合
vue3之全局组件
Card.vue 组件
<template>
<div class="card">
<div class="card-header">
<div>主标题</div>
<div>副标题</div>
</div>
<div class="card-content" v-if="content">{{ content }}</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
type Prosp = {
mainTitle?: String
subTitle?: String
content?: String
}
defineProps<Prosp>()
</script>
<style lang="scss" scoped>
$border: #ccc;
.card {
border: 1px solid $border;
&-hover {
box-shadow: 0 0 10px $border;
}
&-header {
display: flex;
justify-content: space-between;
padding: 10px;
border-bottom: 1px solid $border;
}
&-content {
padding: 10px;
}
}
</style>
main.ts 挂载全局组件
import { createApp } from 'vue'
import App from './App.vue'
import "./assets/css/reset.css"
import Card from './components/card/Card.vue'
createApp(App).component('Card',Card).mount('#app')
使用组件
<template>
<div class="main">
<div class="main-items" v-for="item in 10" :key="item">
<Card :content="`我是${item}个内容`"></Card>
</div>
</div>
</template>
<script setup lang="ts"></script>
<style lang="scss" scoped>
.main {
flex: 1;
margin: 14px;
border: 1px solid #ccc;
overflow: auto;
}
</style>
- 效果:
vue3之 局部组件
Test.vue
<template>
<div>我是test {{ test }}</div>
</template>
<script setup lang="ts">
type Props = {
test: String
}
withDefaults(defineProps<Props>(), {
test: '我是测试的哦',
})
</script>
<style lang="scss" scoped></style>
使用组件
<template>
<div class="main">
<Test />
</div>
</template>
<script setup lang="ts">
import Test from './childCom/Test.vue'
</script>
<style lang="scss" scoped>
.main {
flex: 1;
margin: 14px;
border: 1px solid #ccc;
overflow: auto;
}
</style>
- 效果
递归组件
<template>
<div class="menu">
menu
<Tree :treeData="treeData" @on-click="TreeClick"></Tree>
</div>
</template>
<script setup lang="ts">
import Tree from './tree/Tree.vue'
import { reactive } from 'vue'
type TreeList = {
name: String
icon?: ''
children?: TreeList[] | []
}
const treeData = reactive<TreeList[]>([
{
name: 'no-1',
children: [
{
name: 'no-1-1',
children: [
{
name: 'no-1-1-1',
},
],
},
],
},
{
name: 'no-2',
children: [
{
name: 'no-2-1',
},
],
},
{
name: 'no-3',
},
])
const TreeClick = (item: TreeList) => {
console.log('父item', item)
}
</script>
<style lang="scss" scoped>
.menu {
width: 200px;
height: 100%;
border: 1px solid #ccc;
}
</style>
<template>
<!-- style="margin-left: 10px" 控制子组件的 层次显示 -->
<div class="tree" style="margin-left: 10px">
<div @click.stop="clickItem(item)" v-for="(item, idx) in treeData" :key="idx">
{{ item.name }}
<TreeItem @on-click="clickItem" v-if="item?.children?.length" :treeData="item.children"></TreeItem>
</div>
</div>
</template>
<script setup lang="ts">
import TreeItem from './Tree.vue'
type TreeList = {
name: String
icon?: ''
children?: TreeList[] | []
}
type Props = {
treeData?: TreeList[]
}
defineProps<Props>()
const emit = defineEmits(['on-click'])
const clickItem = (item: TreeList[]) => {
emit('on-click', item)
}
</script>
<script lang="ts">
export default {
name: 'TreeItem',
}
</script>
<style lang="scss" scoped>
.tree {
}
</style>
- 效果
动态组件
<template>
<div class="main">
<div class="tab">
<div :class="['tab-item', currentTab.curName == item.curName ? 'tab-active' : '']" @click="tabChange(item.curName)" v-for="item in tabData" :key="item.name">{{ item.name }} -- {{ item.Com }}</div>
</div>
<component :is="currentTab.curName"></component>
</div>
</template>
<script setup lang="ts">
import A from './childCom/A.vue'
import B from './childCom/B.vue'
import C from './childCom/C.vue'
import { reactive, ref, markRaw } from 'vue'
type Tabs = {
name: String
curName: any
Com: String
}
type Com = Pick<Tabs, 'curName'>
const tabData = reactive<Tabs[]>([
{
name: '我是组件A',
curName: markRaw(A),
Com: 'A',
},
{
name: '我是组件B',
curName: markRaw(B),
Com: 'B',
},
{
name: '我是组件C',
curName: markRaw(C),
Com: 'C',
},
])
let currentTab = reactive<Com>({
curName: tabData[0].curName,
})
const tabChange = (curName: Pick<Tabs, 'curName'>) => {
currentTab.curName = curName
}
</script>
<style lang="scss" scoped>
.main {
flex: 1;
margin: 14px;
border: 1px solid #ccc;
overflow: auto;
.tab {
display: flex;
&-item {
width: 33%;
height: 30px;
line-height: 30px;
border: 1px solid #ccc;
text-align: center;
}
&-active {
color: red;
}
}
}
</style>
- 效果