>[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://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)
- 官網給的工具
- 聲明vue2 和 vue3
- 指令速覽
- Mustache -- 語法
- v-once -- 只渲染一次
- v-text -- 插入文本
- v-html -- 渲染html
- v-pre -- 顯示原始的Mustache標簽
- v-cloak -- 遮蓋
- v-memo(新)-- 緩存指定值
- v-if/v-show -- 條件渲染
- v-for -- 循環
- v-bind -- 知識
- v-bind -- 修飾符
- v-on -- 點擊事件
- v-model -- 雙向綁定
- 其他基礎知識速覽
- 快速使用
- 常識知識點
- key -- 作用 (后續要更新)
- computed -- 計算屬性
- watch -- 偵聽
- 防抖和節流
- vue3 -- 生命周期
- vue-cli 和 vite 項目搭建方法
- vite -- 導入動態圖片
- 組件
- 單文件組件 -- SFC
- 組件通信 -- porp
- 組件通信 -- $emit
- 組件通信 -- Provide / Inject
- 組件通信 -- 全局事件總線mitt庫
- 插槽 -- slot
- 整體使用案例
- 動態組件 -- is
- keep-alive
- 分包 -- 異步組價
- mixin -- 混入
- v-model-- 組件
- 使用計算屬性
- v-model -- 自定義修飾符
- Suspense -- 實驗屬性
- Teleport -- 指定掛載
- 組件實例 -- $ 屬性
- Option API VS Composition API
- Setup -- 組合API 入口
- api -- reactive
- api -- ref
- 使用ref 和 reactive 場景
- api -- toRefs 和 toRef
- api -- readonly
- 判斷性 -- API
- 功能性 -- API
- api -- computed
- api -- $ref 使用
- api -- 生命周期
- Provide 和 Inject
- watch
- watchEffect
- watch vs. watchEffect
- 簡單使用composition Api
- 響應性語法糖
- css -- 功能
- 修改css -- :deep() 和 var
- Vue3.2 -- 語法
- ts -- vscode 配置
- attrs/emit/props/expose/slots -- 使用
- props -- defineProps
- props -- defineProps Ts
- emit -- defineEmits
- emit -- defineEmits Ts
- $ref -- defineExpose
- slots/attrs -- useSlots() 和 useAttrs()
- 自定義指令
- Vue -- 插件
- Vue2.x 和 Vue3.x 不同點
- $children -- 移除
- v-for 和 ref
- attribute 強制行為
- 按鍵修飾符
- v-if 和 v-for 優先級
- 組件使用 v-model -- 非兼容
- 組件
- h -- 函數
- jsx -- 編寫
- Vue -- Router
- 了解路由和vue搭配
- vueRouter -- 簡單實現
- 安裝即使用
- 路由懶加載
- router-view
- router-link
- 路由匹配規則
- 404 頁面配置
- 路由嵌套
- 路由組件傳參
- 路由重定向和別名
- 路由跳轉方法
- 命名路由
- 命名視圖
- Composition API
- 路由守衛
- 路由元信息
- 路由其他方法 -- 添加/刪除/獲取
- 服務器配置映射
- 其他
- Vuex -- 狀態管理
- Option Api -- VUEX
- composition API -- VUEX
- module -- VUEX
- 刷新后vuex 數據同步
- 小技巧
- Pinia -- 狀態管理
- 開始使用
- pinia -- state
- pinia -- getter
- pinia -- action
- pinia -- 插件 ??
- Vue 源碼解讀
- 開發感悟
- 練手項目