Vue3 uses keep-alive components, including dynamic components

Vue3 uses keep-alive components, including dynamic components

Components do not use keep-alive

  • Father
<template>
  <div>
    Father
    <el-button @click="tabChange">change page</el-button>
    <Child :msg="cutTab" v-if="cutTab"></Child>
    <Child2 :msg="cutTab" v-else></Child2>
  </div>
</template>

<script setup lang="ts" name="Father">
const cutTab = ref(false);

const tabChange = () => {
  cutTab.value = !cutTab.value;
}
</script>
  • Child
<template>
  <div class="c1">
    Child +
    {
   
   { props.msg }}
    <el-input v-model="input" placeholder="Please input" />
  </div>
</template>

<script setup lang="ts" name="Child">
const props = defineProps({
  msg: {
    type: Boolean,
    default: false,
  },
})
const input = ref('')
</script>
  • Child2
<template>
  <div class="c2">
    Child2 +
    {
   
   { props.msg }}
    <el-input v-model="input" placeholder="Please input" />
  </div>
</template>

<script setup lang="ts" name="Child2">
const props = defineProps({
  msg: {
    type: Boolean,
    default: false,
  },
})
const input = ref('')
</script>

used in the component

  • include: include
  • exclude: exclude

v-if switch

    <keep-alive>
      <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2>
    </keep-alive>
    <keep-alive include="Child2">
      <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2>
    </keep-alive>

component dynamic component switching

Unexpected error due to annotation
  • <KeepAlive> expects exactly one child component
    <keep-alive include="Child2">
      <!-- <Child :msg="cutTab" v-if="cutTab"></Child>
      <Child2 :msg="cutTab" v-else></Child2> -->
      <component :is="com"></component>
    </keep-alive>

keep-aliveDo not use comments in components, they will be parsed as child nodes

  • Add div to wrap
    <keep-alive include="Child2">
      <div>
        <!-- <Child :msg="cutTab" v-if="cutTab"></Child>
        <Child2 :msg="cutTab" v-else></Child2> -->
        <component :is="com"></component>s
      </div>
    </keep-alive>
  • remove comment
    <keep-alive include="Child2">
      <component :is="com"></component>
    </keep-alive>
Use of dynamic components

[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'.

In Vue 3, if you use ref or reactive to wrap a component into a reactive object, it may cause unnecessary performance overhead. Because this will make Vue try to track component changes, but the component instance does not actually need to be tracked. A component itself should not be reactive, only its props and state should be reactive.

Therefore, when you need to refer to a component, you should use shallowRefor markRaw, which can avoid making the entire component responsive, and only track changes in the reference

  • Use markRaw
const com = ref(markRaw(Child2));

const comChange = () => {
  if(com.value === Child2){
    com.value = markRaw(Child);
  }else{
    com.value = markRaw(Child2);
  }
}
  • Use shallowRef
const com = shallowRef(Child2);

const comChange = () => {
  if(com.value === Child2){
    com.value = Child;
  }else{
    com.value = Child2;
  }
}
complete example
<template>
  <div>
    Father
    <el-button @click="comChange">change component</el-button>
    <keep-alive include="Child2">
      <component :is="com"></component>
    </keep-alive>
  </div>
</template>

<script setup lang="ts" name="Father">
import Child from "@/views/Child.vue";
import Child2 from "@/views/Child2.vue";

const cutTab = ref(false);
const com = ref(markRaw(Child2));

const comChange = () => {
  if(com.value === Child2){
    com.value = markRaw(Child);
  }else{
    com.value = markRaw(Child2);
  }
}

</script>

It can be seen that only Child2components are cached, Childdestroyed and generated

Routing does not use keep-alive

  • components
<template>
  <div>
    Father
    <div class="nav">
      <router-link to="/Father/Child">去Child页面</router-link>
      <el-divider direction="vertical" />
      <router-link to="/Father/Child2">去Child2页面</router-link>
    </div>
    <router-view></router-view>
  </div>
</template>
  • route-index.ts
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'

const routes = [
  {
    path: '/Father',
    name: 'Father',
    component: () => import('@/views/Father.vue'),
    children: [
      {
        path: 'Child',
        name: 'Child',
        component: () => import('@/views/Child.vue'),
      },
      {
        path: 'Child2',
        name: 'Child2',
        component: () => import('@/views/Child2.vue'),
      }
    ],
  }, 
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

used in routing

  • Vue Router 4(the routing library that comes with Vue 3) introduces a new API for routing-level routing <keep-alive>. This is the API <router-view>of the componentv-slot

    • It should be noted that v-ifdo not add to keep-aliveit, it will be destroyed directly keep-alive, it needs to be added componentto
    • To achieve partial refresh of the page, the life cycle executed when the page enters is:created->mounted->activated
<template>
  <div>
    Father
    <div class="nav">
      <router-link to="/Father/Child">去Child页面</router-link>
      <el-divider direction="vertical" />
      <router-link to="/Father/Child2">去Child2页面</router-link>
    </div>
    <router-view v-slot="{ Component }">
      <keep-alive >
        <component :is="Component" v-if="$route.meta.keepAlive"/>
      </keep-alive>
      <component :is="Component" v-if="!$route.meta.keepAlive"/>
    </router-view>
  </div>
</template>
  • route-index.ts

    • Add an attribute to the corresponding route metato set whether the page should use the cache
...
const routes = [
  {
    path: '/Father',
    name: 'Father',
    component: () => import('@/views/Father.vue'),
    children: [
      {
        path: 'Child',
        name: 'Child',
        component: () => import('@/views/Child.vue'),
      },
      {
        path: 'Child2',
        name: 'Child2',
        meta: {
          keepAlive: true,  // 需要被keep-alive
        },
        component: () => import('@/views/Child2.vue'),
      }
    ],
  }, 
]
...

keep-alive life cycle

Some keep-alivecomponents will have two more life cycles, after mountedand unMountedbefore

onActivated(() => {
  console.log('Component is activated')
})

onDeactivated(() => {
  console.log('Component is deactivated')
})

Guess you like

Origin blog.csdn.net/qq_23858785/article/details/130598658