🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
>[success] # 动态组件 -- is 1. `component` 标签和`is` 属性进行搭配可以实现动态组件 2. 使用 html的 tag 标签想渲染 `vue` 组件 `is`attribute 的值中加上`vue:`,因为`web componet` 中 `is ` 是一个特殊的属性因此在vue3 不在像 2 一样可以在普通tag 标签上使用`is` 3. `v-is` 作为三系列的新指令标签在`vue3.1`已经被废弃了 4. `is` 不仅仅可以渲染是`vue `组件也可以是 类似`input `这种原生元素 >[danger] ##### 案例 ![](https://img.kancloud.cn/4b/37/4b37f91945f32f300670491fb6321aba_514x245.png) * [案例](https://sfc.vuejs.org/#eNqlVUtPFEEQ/ivFXEYjsxP1Nu4Sn4kHTTx4czjMzvTCwE7PprtngWxIMMEXiph4gotoQiQxaqKJIYHon9mdhX9h9WMeoAiJB9ip6urvq/q6unpg3ej1Gv2MWJ7V5CGLe2LKp3HSS5mAu2lCoMPSBOyGKw0ZaJfLD1IueLmurOMBN1g4G/crCGObIACfkkUVGJFOkHUFDKQ3THE3JVRwTztAJTKpPxWN+TZ40lhWrigQwYWLxS5GRMZoYSFwxhjCPgzaHtgS0jY4ACJoI9sj4wVbscgPQ2FP68hlxeVT9Sv/XBfy77ujp68WSFtljgTj/dXh/g9VSjfgHB7gfxGHNzMhUgpkURAacbj78P497brTJQluK6qnXLAsFCmrKuFZj6B5TVtiNuYNLpa6pNEOwvkZlmY0ghb4FiORb/m0FhZE0Z0+gt+LOdIiiG+F3Tic961JQPzWVCUPlnKbBQvA1akHNFyCAE8yELHMutMhoeATpZaYZooJdNOZC5evXL1o5NEpVgKFGRdpYgrkDTznmBLMoaclcdpKAJnMMZEmYVDo5GFZRZTGb7pln6IhSIJggqAF0Izivha95VsRSVLfUn5cMRgmfeg7nZRhEB48xFSdv1TOrHrzZEkv1p0F8CMbF0zq2CMDCEKBPeLVGgxarZYEheXpGsJ1JT0i1ANlWBljsgUYDPR2pSOm72q6opoJxzn8tTn+uD5a281XHucvD/LXO8O99eHB1uGHT/net/zdW8eRCgmjihfL1G28ep59qeJHUYuyVB5TTRejazT55pejla3x1qoIZiDffjb+/HO0tj3cW5NIMHqxPj5YGW18He7vaFZ0g74Ax/kVvdwjr9iZrOUMgKMn66M3z3E71FkUtgquIhWDRke80v+fqFq3umB/Aa8ooJgDerfGzXffjw42KnR9ljrhkzdh6pbsEbhPJmpnrnrbSNR0ay3vU2vS0tPWSYJeY46nFCe5utO+WcDGLgepOgJp+9asED3uuS7vhHIgz/FGymZc/GqwjIoYhz3hidNm6QInDIHxktYwXHT2CXNQlYgwwv6FeSL0D9xiZGApxSMjX6PTb7bumeppqAQ/RShELp+n80Pr9+0c2LV37fzoxeN4Jv7ybxletSw=) ~~~html <script> import Home from './Home.vue' import Posts from './Posts.vue' import Archive from './Archive.vue' export default { components: { Home, Posts, Archive }, data() { return { currentTab: 'Home', tabs: ['Home', 'Posts', 'Archive'] } } } // 注册web compent组件 class PlasticButton extends HTMLButtonElement { constructor() { super(); this.style.background = "red" this.addEventListener("click", () => { // Draw some fancy animation effects! console.log(123) }); } } customElements.define("plastic-button", PlasticButton, { extends: "button" }); </script> <template> <div class="demo"> <button v-for="tab in tabs" :key="tab" :class="['tab-button', { active: currentTab === tab }]" @click="currentTab = tab" > {{ tab }} </button> <!--这种动态拼接不会被渲染--> <div :is="'vue:'+currentTab" class="tab"></div> <!--普通的tag 标签加上vue: 前缀可以渲染vue 组件--> <div is="vue:Home" class="tab"></div> <!--component 配合 is 可以渲染--> <component is="Home"></component> <!--component 配合 is 可以渲染--> <component :is="currentTab"></component> <!-- web component 渲染模式--> <button is="plastic-button">Click Me!</button> </div> </template> ~~~ >[danger] ##### v-model 在使用上区别 如果在`<component>`标签上使用`v-model`,模板编译器会将其扩展为`modelValue`prop 和`update:modelValue`事件监听器,就像对任何其他组件一样。但是,这与原生 HTML 元素不兼容,例如`<input>`或`<select>`。因此,在动态创建的原生元素上使用`v-model`将不起作用,**可以手动将`v-model`拆分为 attribute 和事件** ~~~ <script setup> import { ref } from 'vue' const tag = ref('input') const username = ref('') </script> <template> <!-- 由于 'input' 是原生 HTML 元素,因此这个 v-model 不起作用 --> <component :is="tag" v-model="username" /> </template> ~~~ >[info] ## 官网对应位置 [is](https://cn.vuejs.org/api/built-in-special-attributes.html#ref) [# 内置特殊元素](https://cn.vuejs.org/api/built-in-special-elements.html) [## 动态组件](https://cn.vuejs.org/guide/essentials/component-basics.html#dynamic-components)