Vue3系列8--全局组件,局部组件,递归组件
1 配置全局组件
当一个组件使用频率非常高的时候,可以考虑设置其为全局组件,方便其他地方调用。
案例------我这儿封装一个Card组件想在任何地方去使用:
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 | <template> <div class = "card" > <div class = "card-header" > <div>主标题</div> <div>副标题</div> </div> <div v- if = "content" class = "card-content" > {{ content }} </div> </div> </template> <script setup lang= "ts" > type Props = { content?: string } defineProps<Props>() </script> <style scoped lang= "less" > @border: #ccc; .card { border: 1px solid; &:hover { box-shadow: 0 0 20px @border; //放在上面的效果 } &-header { display: flex; justify-content: space-between; padding: 10px; border-bottom: 1px solid @border; } &-content { padding: 10px; } } </style> |
使用方法:在main.ts 引入我们的组件跟随在createApp(App) 后面 切记不能放到mount 后面这是一个链式调用用,其次调用 component 第一个参数组件名称 第二个参数组件实例。
1 2 3 4 5 | import { createApp } from 'vue' import App from './App.vue' import './assets/css/reset/index.less' import Card from './components/Card/index.vue' createApp(App).component( 'Card' ,Card).mount( '#app' ) |
使用方法:直接在其他vue页面 立即使用即可 无需引入
1 2 3 | <template> <Card></Card> </template> |
2 配置局部组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <template> <div class = "wraps" > <layout-menu :flag= "flag" @on-click= "getMenu" @on-toogle= "getMenuItem" :data= "menuList" class = "wraps-left" ></layout-menu> <div class = "wraps-right" > <layout-header> </layout-header> <layout-main class = "wraps-right-main" ></layout-main> </div> </div> </template> <script setup lang= "ts" > import { reactive,ref } from "vue" ; import layoutHeader from "./Header.vue" ; import layoutMenu from "./Menu.vue" ; import layoutMain from "./Content.vue" ; |
就是在一个组件内(A) 通过import 去引入别的组件(B) 称之为局部组件,应为B组件只能在A组件内使用 所以是局部组件,如果C组件想用B组件 就需要C组件也手动import 引入 B 组件。
3 配置递归组件
原理跟我们写js递归是一样的 自己调用自己 通过一个条件来结束递归 否则导致内存泄漏
案例递归树:在父组件配置数据结构 数组对象格式 传给子组件
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 | <template><br> <div><br> <Tree :data= "data" ></Tree><br> </div><br></template><br><br><script> import Tree from '../../components/Tree/index.vue' type TreeList = { name: string; icon?: string; children?: TreeList[] | []; }; const data = 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" , }, ]);</script> |
子组件接收值 第一个script
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | type TreeList = { name: string; icon?: string; children?: TreeList[] | []; }; type Props<T> = { data?: T[] | []; }; defineProps<Props<TreeList>>(); const clickItem = (item: TreeList) => { console.log(item) } |
子组件增加一个script 定义组件名称为了 递归用 :
1 2 3 4 5 | <script lang= "ts" > export default { name: "TreeItem" } </script> |
TreeItem 其实就是当前组件 通过import 把自身又引入了一遍 如果他没有children 了就结束:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <template> <div style= "margin-left: 10px;" > <!-- {{data}} --> <div :key= "index" v- for = "(item, index) in data" >{{ item.name }} <TreeItem v- if = "item?.children?.length" :data= "item.children" ></TreeItem> </div> </div> </template> <script setup lang= "ts" > import TreeItem from './index.vue' type TreeList = { name: string, icon?: string, children?: TreeList[] | [] } type Props = { data?: TreeList[] } defineProps<Props>() </script> |
4 动态组件
什么是动态组件 就是:让多个组件使用同一个挂载点,并动态切换,这就是动态组件。在挂载点使用component标签,然后使用v-bind:is=”组件”
用法如下:引入组件
1 2 3 | import A from './A.vue' import B from './B.vue' import C from './C.vue' |
1 | <component :is= "current.comName" ></component> |
通过is 切换 A B 组件,使用场景,tab切换 居多
注意事项
1.在Vue2 的时候is 是通过组件名称切换的 在Vue3 setup 是通过组件实例切换的
2.如果你把组件实例放到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 代理.
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 | type Tabs = { name: string, comName: any } const data = reactive<Tabs[]>([ { name: "我是组件A" , comName: markRaw(A) }, { name: "我是组件B" , comName: markRaw(B) }, { name: "我是组件C" , comName: markRaw(C) }, ]) type Com = Pick<Tabs, "comName" > let current = reactive<Com>({ comName: data[0].comName }) const switchTabs = (item: Tabs) => { current.comName = item.comName } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了