【Vue3】keep-alive 缓存组件

这篇具有很好参考价值的文章主要介绍了【Vue3】keep-alive 缓存组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

当在 Vue.js 中使用 <keep-alive> 组件时,它将会缓存动态组件,而不是每次渲染都销毁和重新创建它们。这对于需要在组件间快速切换并且保持组件状态的情况非常有用。

<keep-alive> 只能包含(或者说只能渲染)一个子组件,如果需要包含多个子组件,需要用 v-if 选择某个确定的组件进行渲染。也可以使用 <template> 或其他组件标签将它们包裹起来,再通过 v-if 选择确定的某个组件进行渲染。因此 keep-alive 标签里面有且只有一个子节点(或者说只能渲染一个子节点)。这些子组件可以通过动态组件或者其他方式进行切换。

当一个被 <keep-alive> 组件包裹的组件被切换出去时,它的状态将会被保留在内存中,而不会被销毁。当组件再次被切换回来时,它会从缓存中直接取出,并且保持之前的状态。

1. keep-alive 和 v-show 的区别

  • 作用:

<keep-alive>:用于缓存组件,以避免每次组件切换时销毁和重新创建实例。它会保留组件的状态,以便在需要时直接从缓存中取出。

v-show:用于根据条件动态显示或隐藏组件。它通过控制 display CSS 属性来决定组件是否在 DOM 中渲染。

  • 使用场景:

<keep-alive>:适用于需要在组件间快速切换并保持组件状态的场景。例如,当你有一个包含表单的编辑页面,在切换到其他页面并返回时,希望保留用户已输入的数据。

v-show:适用于根据某些条件动态显示或隐藏单个组件。例如,根据用户权限动态显示不同的导航菜单。

  • 对组件实例的影响:

<keep-alive>:保留组件的状态和实例,只是保存虚拟 DOM ,以便在需要时直接从缓存中取出。组件的生命周期钩子函数 activated 和 deactivated 也会在缓存和激活时触发。

v-show:每次切换显示或隐藏时,组件实例会保持不变,存在于真实 DOM ,并且会触发相应的生命周期钩子函数 beforeUpdate 和 updated。

2. keep-alive 使用案例

App.vue

<template>
  <el-button type="primary" @click="flag = !flag"> 切换组件</el-button>
  <!-- [] 里面名称是原本的组件名 -->
  <!-- 
    props介绍:
    :exclude="['A']"  不缓存A组件
    :include="['A']"  缓存A组件
    :max="2"  最多缓存2个,如有多个从后往前算起
   -->
  <keep-alive :exclude="['A']">
    <AVue v-if="flag"></AVue>
    <B v-else></B>
  </keep-alive>

</template>

<script setup lang="ts">
import { ref } from 'vue';
import AVue from './components/A.vue'
import B from './components/B.vue'
const flag = ref<boolean>(true)
</script>

<style scoped></style>

A.vue

<template>
  <h1 style="margin: 10px;">我是A组件</h1>
  <el-form :model="form" label-width="120px">
    <el-form-item label="Activity name">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="Activity zone">
      <el-select v-model="form.region" placeholder="please select your zone">
        <el-option label="Zone one" value="shanghai" />
        <el-option label="Zone two" value="beijing" />
      </el-select>
    </el-form-item>
    <el-form-item label="Activity time">
      <el-col :span="11">
        <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" />
      </el-col>
      <el-col :span="2" class="text-center">
        <span class="text-gray-500">-</span>
      </el-col>
      <el-col :span="11">
        <el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" />
      </el-col>
    </el-form-item>
    <el-form-item label="Instant delivery">
      <el-switch v-model="form.delivery" />
    </el-form-item>
    <el-form-item label="Activity type">
      <el-checkbox-group v-model="form.type">
        <el-checkbox label="Online activities" name="type" />
        <el-checkbox label="Promotion activities" name="type" />
        <el-checkbox label="Offline activities" name="type" />
        <el-checkbox label="Simple brand exposure" name="type" />
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="Resources">
      <el-radio-group v-model="form.resource">
        <el-radio label="Sponsor" />
        <el-radio label="Venue" />
      </el-radio-group>
    </el-form-item>
    <el-form-item label="Activity form">
      <el-input v-model="form.desc" type="textarea" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">Create</el-button>
      <el-button>Cancel</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive } from 'vue'

// do not use same name with ref
const form = reactive({
  name: '',
  region: '',
  date1: '',
  date2: '',
  delivery: false,
  type: [],
  resource: '',
  desc: '',
})

const onSubmit = () => {
  console.log('submit!')
}
</script>

B.vue

<template>
  <h1 style="margin: 10px;">我是B组件</h1>
  <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm" :size="formSize"
    status-icon>
    <el-form-item label="Activity name" prop="name">
      <el-input v-model="ruleForm.name" />
    </el-form-item>
    <el-form-item label="Activity zone" prop="region">
      <el-select v-model="ruleForm.region" placeholder="Activity zone">
        <el-option label="Zone one" value="shanghai" />
        <el-option label="Zone two" value="beijing" />
      </el-select>
    </el-form-item>
    <el-form-item label="Activity count" prop="count">
      <el-select-v2 v-model="ruleForm.count" placeholder="Activity count" :options="options" />
    </el-form-item>
    <el-form-item label="Activity time" required>
      <el-col :span="11">
        <el-form-item prop="date1">
          <el-date-picker v-model="ruleForm.date1" type="date" label="Pick a date" placeholder="Pick a date"
            style="width: 100%" />
        </el-form-item>
      </el-col>
      <el-col class="text-center" :span="2">
        <span class="text-gray-500">-</span>
      </el-col>
      <el-col :span="11">
        <el-form-item prop="date2">
          <el-time-picker v-model="ruleForm.date2" label="Pick a time" placeholder="Pick a time" style="width: 100%" />
        </el-form-item>
      </el-col>
    </el-form-item>
    <el-form-item label="Instant delivery" prop="delivery">
      <el-switch v-model="ruleForm.delivery" />
    </el-form-item>
    <el-form-item label="Activity type" prop="type">
      <el-checkbox-group v-model="ruleForm.type">
        <el-checkbox label="Online activities" name="type" />
        <el-checkbox label="Promotion activities" name="type" />
        <el-checkbox label="Offline activities" name="type" />
        <el-checkbox label="Simple brand exposure" name="type" />
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="Resources" prop="resource">
      <el-radio-group v-model="ruleForm.resource">
        <el-radio label="Sponsorship" />
        <el-radio label="Venue" />
      </el-radio-group>
    </el-form-item>
    <el-form-item label="Activity form" prop="desc">
      <el-input v-model="ruleForm.desc" type="textarea" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">
        Create
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

interface RuleForm {
  name: string
  region: string
  count: string
  date1: string
  date2: string
  delivery: boolean
  type: string[]
  resource: string
  desc: string
}

const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  name: '',
  region: '',
  count: '',
  date1: '',
  date2: '',
  delivery: false,
  type: [],
  resource: '',
  desc: '',
})

const rules = reactive<FormRules<RuleForm>>({
  name: [
    { required: true, message: 'Please input Activity name', trigger: 'blur' },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ],
  region: [
    {
      required: true,
      message: 'Please select Activity zone',
      trigger: 'change',
    },
  ],
  count: [
    {
      required: true,
      message: 'Please select Activity count',
      trigger: 'change',
    },
  ],
  date1: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a date',
      trigger: 'change',
    },
  ],
  date2: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a time',
      trigger: 'change',
    },
  ],
  type: [
    {
      type: 'array',
      required: true,
      message: 'Please select at least one activity type',
      trigger: 'change',
    },
  ],
  resource: [
    {
      required: true,
      message: 'Please select activity resource',
      trigger: 'change',
    },
  ],
  desc: [
    { required: true, message: 'Please input activity form', trigger: 'blur' },
  ],
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}

const options = Array.from({ length: 10000 }).map((_, idx) => ({
  value: `${idx + 1}`,
  label: `${idx + 1}`,
}))
</script>

【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架
【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架

3. 因注释导致的意外错误

写入注释:
【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架

报错:
【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架
因此 keep-alive 组件内不要使用注释,会被解析为子节点

解决方法:

  • keep-alive 内部不写注释

  • 使用 <template> 或其他组件标签将它们包裹起来

    • 此时 可以认为 利用了 keep-alive 标签里面有且只有一个子节点(或者说只能渲染一个子节点)
  <keep-alive :exclude="['A']">
      <template v-if="flag">
        <!-- [] 里面名称是原本的组件名 -->
        <AVue></AVue>
      </template>
      <template v-else>
        <B></B>
      </template>
  </keep-alive>

4. keep-alive 生命周期

<keep-alive> 组件提供了以下两个主要的生命周期钩子函数来管理缓存的组件:

  • activated:被缓存的组件激活时调用。

  • deactivated:被缓存的组件停用时调用。

App.vue

<template>
  <el-button type="primary" @click="flag = !flag"> 切换组件</el-button>

  <!-- 
    props介绍:
    :exclude="['A']"  不缓存A组件
    :include="['A']"  缓存A组件
    :max="2"  最多缓存2个,如有多个从后往前算起
   -->
  <keep-alive :exclude="['B']">
      <AVue v-if="flag"></AVue>
      <B v-else></B>
  </keep-alive>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import AVue from './components/A.vue'
import B from './components/B.vue'

const flag = ref<boolean>(true)
</script>

<style scoped></style>

A.vue

<template>
  <h1 style="margin: 10px;">我是A组件</h1>
  <el-form :model="form" label-width="120px">
    <el-form-item label="Activity name">
      <el-input v-model="form.name" />
    </el-form-item>
    <el-form-item label="Activity zone">
      <el-select v-model="form.region" placeholder="please select your zone">
        <el-option label="Zone one" value="shanghai" />
        <el-option label="Zone two" value="beijing" />
      </el-select>
    </el-form-item>
    <el-form-item label="Activity time">
      <el-col :span="11">
        <el-date-picker v-model="form.date1" type="date" placeholder="Pick a date" style="width: 100%" />
      </el-col>
      <el-col :span="2" class="text-center">
        <span class="text-gray-500">-</span>
      </el-col>
      <el-col :span="11">
        <el-time-picker v-model="form.date2" placeholder="Pick a time" style="width: 100%" />
      </el-col>
    </el-form-item>
    <el-form-item label="Instant delivery">
      <el-switch v-model="form.delivery" />
    </el-form-item>
    <el-form-item label="Activity type">
      <el-checkbox-group v-model="form.type">
        <el-checkbox label="Online activities" name="type" />
        <el-checkbox label="Promotion activities" name="type" />
        <el-checkbox label="Offline activities" name="type" />
        <el-checkbox label="Simple brand exposure" name="type" />
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="Resources">
      <el-radio-group v-model="form.resource">
        <el-radio label="Sponsor" />
        <el-radio label="Venue" />
      </el-radio-group>
    </el-form-item>
    <el-form-item label="Activity form">
      <el-input v-model="form.desc" type="textarea" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">Create</el-button>
      <el-button>Cancel</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive,onMounted,onUnmounted,onDeactivated,onActivated } from 'vue'

// do not use same name with ref
const form = reactive({
  name: '',
  region: '',
  date1: '',
  date2: '',
  delivery: false,
  type: [],
  resource: '',
  desc: '',
})

const onSubmit = () => {
  console.log('submit!')
}

onMounted(() => {
  console.log('初始化')
}),
onActivated(() => {
  console.log('keep-alive初始化')
})
onDeactivated(() => {
  console.log('keep-alive销毁')
})
onUnmounted(() => {
  console.log('销毁')
})
</script>

B.vue

<template>
  <h1 style="margin: 10px;">我是B组件</h1>
  <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm" :size="formSize"
    status-icon>
    <el-form-item label="Activity name" prop="name">
      <el-input v-model="ruleForm.name" />
    </el-form-item>
    <el-form-item label="Activity zone" prop="region">
      <el-select v-model="ruleForm.region" placeholder="Activity zone">
        <el-option label="Zone one" value="shanghai" />
        <el-option label="Zone two" value="beijing" />
      </el-select>
    </el-form-item>
    <el-form-item label="Activity count" prop="count">
      <el-select-v2 v-model="ruleForm.count" placeholder="Activity count" :options="options" />
    </el-form-item>
    <el-form-item label="Activity time" required>
      <el-col :span="11">
        <el-form-item prop="date1">
          <el-date-picker v-model="ruleForm.date1" type="date" label="Pick a date" placeholder="Pick a date"
            style="width: 100%" />
        </el-form-item>
      </el-col>
      <el-col class="text-center" :span="2">
        <span class="text-gray-500">-</span>
      </el-col>
      <el-col :span="11">
        <el-form-item prop="date2">
          <el-time-picker v-model="ruleForm.date2" label="Pick a time" placeholder="Pick a time" style="width: 100%" />
        </el-form-item>
      </el-col>
    </el-form-item>
    <el-form-item label="Instant delivery" prop="delivery">
      <el-switch v-model="ruleForm.delivery" />
    </el-form-item>
    <el-form-item label="Activity type" prop="type">
      <el-checkbox-group v-model="ruleForm.type">
        <el-checkbox label="Online activities" name="type" />
        <el-checkbox label="Promotion activities" name="type" />
        <el-checkbox label="Offline activities" name="type" />
        <el-checkbox label="Simple brand exposure" name="type" />
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="Resources" prop="resource">
      <el-radio-group v-model="ruleForm.resource">
        <el-radio label="Sponsorship" />
        <el-radio label="Venue" />
      </el-radio-group>
    </el-form-item>
    <el-form-item label="Activity form" prop="desc">
      <el-input v-model="ruleForm.desc" type="textarea" />
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">
        Create
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
    </el-form-item>
  </el-form>
</template>

<script lang="ts" setup>
import { reactive, ref } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'

interface RuleForm {
  name: string
  region: string
  count: string
  date1: string
  date2: string
  delivery: boolean
  type: string[]
  resource: string
  desc: string
}

const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  name: '',
  region: '',
  count: '',
  date1: '',
  date2: '',
  delivery: false,
  type: [],
  resource: '',
  desc: '',
})

const rules = reactive<FormRules<RuleForm>>({
  name: [
    { required: true, message: 'Please input Activity name', trigger: 'blur' },
    { min: 3, max: 5, message: 'Length should be 3 to 5', trigger: 'blur' },
  ],
  region: [
    {
      required: true,
      message: 'Please select Activity zone',
      trigger: 'change',
    },
  ],
  count: [
    {
      required: true,
      message: 'Please select Activity count',
      trigger: 'change',
    },
  ],
  date1: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a date',
      trigger: 'change',
    },
  ],
  date2: [
    {
      type: 'date',
      required: true,
      message: 'Please pick a time',
      trigger: 'change',
    },
  ],
  type: [
    {
      type: 'array',
      required: true,
      message: 'Please select at least one activity type',
      trigger: 'change',
    },
  ],
  resource: [
    {
      required: true,
      message: 'Please select activity resource',
      trigger: 'change',
    },
  ],
  desc: [
    { required: true, message: 'Please input activity form', trigger: 'blur' },
  ],
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid, fields) => {
    if (valid) {
      console.log('submit!')
    } else {
      console.log('error submit!', fields)
    }
  })
}

const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return
  formEl.resetFields()
}

const options = Array.from({ length: 10000 }).map((_, idx) => ({
  value: `${idx + 1}`,
  label: `${idx + 1}`,
}))
</script>

【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架
【Vue3】keep-alive 缓存组件,Vue,缓存,vue.js,前端框架文章来源地址https://www.toymoban.com/news/detail-645190.html

到了这里,关于【Vue3】keep-alive 缓存组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VUE3,自定义控制keep-alive缓存

    安装插件 npm install vite-plugin-vue-setup-extend --save 在vite.config.ts中 import VueSetupExtend from \\\'vite-plugin-vue-setup-extend\\\' ..... plugins:[         vue(),         VueSetupExtend(),         ..... ] useKeepalive.ts import { ref } from \\\"vue\\\" export const includes = refstring[]([]); // 增加缓存 export function addKeepAliveC

    2024年01月19日
    浏览(21)
  • Vue中的keep-alive缓存组件的理解

    keep-alive 是一个抽象组件,用于将其内部的组件保留在内存中,而不会重新渲染。这意味着当组件在keep-alive 内部切换时,其状态将被 保留 ,而不是被销毁和重新创建。          keep-alive用来缓存不经常变化的组件,以提高性能,当我们在不同路由之间进行切换或者是动

    2024年01月18日
    浏览(27)
  • Vue路由组件的缓存keep-alive和include属性

    功能:浏览器页面在进行切换时,原有的路由组件会被销毁。通过缓存可以保存被切换的路由组件。 例子:在页面上填好的信息当进行页面切换再转回原来的页面时,原本信息被清空了需要重新填写 功能:切换路由时,保留被切换路由组件。 格式: keep-alive router-view/ keep-

    2024年02月06日
    浏览(25)
  • Vue3 除了 keep-alive,还有哪些实现页面缓存的方法

    有这么一个需求:列表页进入详情页后,切换回列表页,需要对列表页进行缓存,如果从首页进入列表页,就要重新加载列表页。 对于这个需求,我的第一个想法就是使用keep-alive来缓存列表页,列表和详情页切换时,列表页会被缓存;从首页进入列表页时,就重置列表页数

    2024年02月06日
    浏览(30)
  • Vue使用keep-alive设置哪些组件可以被缓存,哪些不被缓存

    需求:当一个项目中,不是所有的组件页面都需要缓存起来,因为有些页面是不需要的    $route.meta.keepAlive 判断当前组件是否有keepAlive属性 在路由js文件中在配置路由规则的时候配置  

    2024年02月16日
    浏览(31)
  • vue3.0中的keep-alive

    keep-alive是vue中的一个内置组件,通常用它来包裹一个动态组件,keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。 它有两个特殊的生命周期钩子 activated 和 deactivated ,在vue3.0里面生命周期函数前面都要加上on, onActivated , onDeactivated 。当组件在使用了kee

    2023年04月08日
    浏览(27)
  • keep-alive 是 Vue 的一个内置组件,用于缓存其他组件的实例,以避免重复渲染和销毁,它可以在需要频繁切换的组件之间提供性能优化

    目录 keep-alive  使用 keep-alive 的示例代码: 手动清除组件缓存的示例代码: keep-alive 组件有以下几个优点: keep-alive 的原理: 使用 keep-alive 组件,你可以包裹需要缓存的组件,然后这些组件在切换时将会被缓存起来,而不是每次都重新创建。 使用 keep-alive 的示例代码: 我们

    2024年02月08日
    浏览(29)
  • keep-alive组件缓存

    从 a跳b,a已经销毁,b重新渲染;b跳a,b销毁a重新渲染 源组件销毁,目标组件渲染 组件缓存:组件实例等相关(  包括vnode )存储起来 重新渲染指的是:把视图重新编译成新的vnode-dom diff-渲染成真实dom 真实dom被我移除了只是从页面上移除,只是把vnode重新渲染成真实dom或者

    2024年01月21日
    浏览(31)
  • vue3中keep-alive的使用及结合transition使用

    在组件中使用(这里结合了 transition 内置动画组件 ) 在router.js中配置 keepAlive 自定义属性 VueCompilerError: expects exactly one child element or component. 不报错,但 keep-alive 内置组件的缓存没有效果,onActivated 函数也不会执行 vue中keep-alive的使用及详解

    2024年02月11日
    浏览(28)
  • 缓存滚动位置:解决keep-alive组件缓存滚动位置失败问题

    怎样在vue中缓存组件?大家都知道,使用keep-alive组件即可,但是使用keep-alive缓存页面后,发现虽然页面缓存成功了,但是列表的滚动条又自动回到了最上方。 是的, keep-alive组件是不会缓存滚动位置的 。 怎样缓存滚动位置呢?这是我们这一章讲的问题。 核心思想是在路由

    2024年02月16日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包