局部组件
页面上模块非常多,又不想冗杂地写在同一个页面内,就可以把它拆成一个局部组件。
Card.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <template> <div class="card"> <header> <div>标题</div> <div>副标题</div> </header> <section> 内容 </section> </div> </template>
<style scoped lang="scss"> $border: #ccc; .card { border: 1px solid $border; width: 400px; header { display: flex; justify-content: space-between; padding: 5px; border-bottom: 1px solid $border; } section { padding: 5px; min-height: 300px; } } </style>
|
App.vue:
1 2 3 4 5 6 7 8 9
| <template> <div> <Card></Card> </div> </template>
<script setup lang="ts"> import Card from './components/expame/Card.vue' </script>
|
全局组件
在当前系统中出现频率较高的组件,可以被封装成全局组件。
Card.vue同上。
App.vue:
1 2 3 4 5
| <template> <div> <Card></Card> </div> </template>
|
main.ts:
1 2 3 4 5 6 7 8 9 10 11 12
| import { createApp } from 'vue'
import App from './App.vue'
import CardVue from './components/expame/Card.vue'
const app = createApp(App)
app.component("Card", CardVue)
app.mount('#app')
|
递归组件
对组件内容进行复用。
App.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <template> <div> <Tree :data="data"></Tree> </div> </template>
<script setup lang="ts"> import { reactive } from 'vue' import Tree from "@/components/expame/Tree.vue"
interface TreeList { name: string, checked: boolean, children?: TreeList[] }
const data = reactive<TreeList[]>([ { name: "1", checked: true, }, { name: "2", checked: false, }, { name: "3", checked: true, children: [ { name: "3.1", checked: false, children: [ { name: "3.1.1", checked: false, }, { name: "3.1.2", checked: false, }, { name: "3.1.3", checked: true, } ] }, { name: "3.2", checked: false, } ] } ]) </script>
|
Tree.vue:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| <template> <!-- 使用.stop阻止冒泡 --> <!-- $是Vue提供的关键词,可以接收事件对象 --> <div @click.stop="clickTap(item, $event)" v-for="(item, index) in data" :key="index" class="tree"> <input v-model="item.checked" type="checkbox"> <span>{{ item.name }}</span> <!-- 当该层递归还有子级时才进入下一层 -->
<!-- Vue3中,可以直接使用文件名当作递归组件的名称 --> <!-- 但这样如果不想用这个名字,就只能更改文件名 --> <Tree v-if="item?.children?.length" :data="item.children"></Tree> <!-- 还可以导出该组件并起个别名,使用别名递归 --> <!-- 但这样需要再写一个script --> <!-- <Test v-if="item?.children?.length" :data="item.children"></Test> -->
<!-- 也可以安装unplugin-vue-define-options插件 --> </div> </template>
<script setup lang="ts">
interface TreeList { name: string, checked: boolean, children?: TreeList[] }
defineProps<{ data?: TreeList[] }>()
const clickTap = <T extends Event> (item: TreeList, e: T)=> { // 默认存在冒泡,点击递归子级时会冒泡到递归父级 console.log(item, e) } </script>
<!-- <script lang="ts"> // 暴露导出该组件,并起个别名,这样就可以在该组件中以别的名字递归了 export default { name: "Test" } </script> -->
<style scoped lang="scss"> .tree { margin-left: 10px; } </style>
|