# 1. 动态组件 用 if else 实现
# Home
vue | // Home.vue |
| <template> |
| <div> |
| Home组件 |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "home", |
| } |
| </script> |
| |
| <style scoped> |
| |
| </style> |
# About
vue | // About.vue |
| <template> |
| <div> |
| About组件 |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "about", |
| } |
| </script> |
| |
| <style scoped></style> |
# Category
vue | // Category.vue |
| <template> |
| <div> |
| Category组件 |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "category", |
| } |
| </script> |
| |
| <style scoped></style> |
# App
vue | // App.vue |
| <template> |
| <div> |
| <button v-for="item in tabs" :key="item" |
| @click="itemClick(item)" |
| :class="{active: currentTab === item}"> |
| {{ item }} |
| </button> |
| |
| <template v-if="currentTab === 'home'"> |
| <home></home> |
| </template> |
| <template v-else-if="currentTab === 'about'"> |
| <about></about> |
| </template> |
| <template v-else> |
| <category></category> |
| </template> |
| </div> |
| </template> |
| |
| <script> |
| import Home from './Home.vue'; |
| import About from './About.vue'; |
| import Category from './Category.vue'; |
| |
| export default { |
| components: { |
| Home, |
| About, |
| Category |
| }, |
| data() { |
| return { |
| tabs: ["home", "about", "category"], |
| currentTab: "home" |
| } |
| }, |
| methods: { |
| itemClick(item) { |
| this.currentTab = item; |
| }, |
| } |
| } |
| </script> |
| |
| <style scoped> |
| .active { |
| color: red; |
| } |
| </style> |
参考结果:
# 2. 动态组件 component
# App
vue | // App.vue |
| <template> |
| <div> |
| <button v-for="item in tabs" :key="item" |
| @click="itemClick(item)" |
| :class="{active: currentTab === item}"> |
| {{ item }} |
| </button> |
| |
| |
| <component :is="currentTab" |
| name="Neko" |
| :age="18"> |
| </component> |
| </div> |
| </template> |
| |
| <script> |
| import Home from './Home.vue'; |
| import About from './About.vue'; |
| import Category from './Category.vue'; |
| |
| export default { |
| components: { |
| Home, |
| About, |
| Category |
| }, |
| data() { |
| return { |
| tabs: ["home", "about", "category"], |
| currentTab: "home" |
| } |
| }, |
| methods: { |
| itemClick(item) { |
| this.currentTab = item; |
| } |
| } |
| } |
| </script> |
| |
| <style scoped> |
| .active { |
| color: red; |
| } |
| </style> |
参考结果:
# 3.keep-alive 的基本使用
# Home
vue | // Home.vue |
| <template> |
| <div @click="divClick"> |
| Home组件: {{ name }} - {{ age }} |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "home", |
| props: { |
| name: { |
| type: String, |
| default: "" |
| }, |
| age: { |
| type: Number, |
| default: 0 |
| } |
| }, |
| emits: ["pageClick"], |
| methods: { |
| divClick() { |
| this.$emit("pageClick"); |
| } |
| } |
| } |
| </script> |
| |
| <style scoped></style> |
# About
vue | // About |
| <template> |
| <div> |
| About组件 |
| <button @click="counter++">{{ counter }}</button> |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "about", |
| data() { |
| return { |
| counter: 0 |
| } |
| }, |
| |
| created() { |
| console.log("about created"); |
| }, |
| unmounted() { |
| console.log("about unmounted"); |
| }, |
| activated() { |
| console.log("about activated"); |
| }, |
| deactivated() { |
| console.log("about deactivated"); |
| } |
| } |
| </script> |
| |
| <style scoped></style> |
# Category
vue | // Category.vue |
| <template> |
| <div> |
| Category组件 |
| <button @click="counter++">{{ counter }}</button> |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| name: "category", |
| data() { |
| return { |
| counter: 0 |
| } |
| } |
| } |
| </script> |
| |
| <style scoped></style> |
# App
vue | // App.vue |
| <template> |
| <div> |
| <button v-for="item in tabs" :key="item" |
| @click="itemClick(item)" |
| :class="{active: currentTab === item}"> |
| {{ item }} |
| </button> |
| |
| |
| |
| include:只有名称匹配的组件会被缓存 |
| exclude: 任何名称匹配的组件都不会被缓存 |
| max: 最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁 |
| 匹配会先检查组件自身的 name 选项 |
| --> |
| <keep-alive include="home,about"> |
| <component :is="currentTab" |
| name="Neko" |
| :age="18" |
| @pageClick="pageClick"> |
| </component> |
| </keep-alive> |
| </div> |
| </template> |
| |
| <script> |
| import Home from './pages/Home.vue'; |
| import About from './pages/About.vue'; |
| import Category from './pages/Category.vue'; |
| |
| export default { |
| components: { |
| Home, |
| About, |
| Category |
| }, |
| data() { |
| return { |
| tabs: ["home", "about", "category"], |
| currentTab: "home" |
| } |
| }, |
| methods: { |
| itemClick(item) { |
| this.currentTab = item; |
| }, |
| pageClick() { |
| console.log("page内部发生了点击"); |
| } |
| } |
| } |
| </script> |
| |
| <style scoped> |
| .active { |
| color: red; |
| } |
| </style> |
参考结果:控制台没有打印 Category 的 created 生命周期,是因为没有使用该函数
# 4. 异步组件 suspense
# AsyncCategory
vue | // AsyncCategory.vue |
| <template> |
| <div> |
| <h2>{{ message }}</h2> |
| </div> |
| </template> |
| |
| <script> |
| export default { |
| data() { |
| return { |
| message: "Hello Category" |
| } |
| } |
| } |
| </script> |
| |
| <style scoped></style> |
# Loading-
vue | // Loading.vue |
| <template> |
| <div> |
| Loading |
| </div> |
| </template> |
| |
| <script> |
| export default {} |
| </script> |
| |
| <style scoped></style> |
# App
vue | // App.vue |
| <template> |
| <div> |
| App组件 |
| <suspense> |
| <template #default> |
| <async-category></async-category> |
| </template> |
| <template #fallback> |
| <loading></loading> |
| </template> |
| </suspense> |
| </div> |
| </template> |
| |
| <script> |
| import { defineAsyncComponent } from 'vue'; |
| |
| import Loading from './Loading.vue'; |
| |
| |
| const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue")) |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| export default { |
| components: { |
| AsyncCategory, |
| Loading |
| } |
| } |
| </script> |
| |
| <style scoped></style> |
参考结果:
官方: