vue的动态组件和异步组件及keep-alive

vue的动态组件和异步组件

一、动态组件

动态组件是使用 component 组件,通过一个特殊的attribute is 来实现

下面通过一个例子去解释动态组件怎么用
在这里插入图片描述
如上图所示,比如我们现在想要实现了一个功能:点击一个tab-bar,切换不同的组件显示

这个案例我们可以通过三种不同的实现思路来实现

  • 方式一:通过v-if来判断,显示不同的组件
  • 方式二:动态组件的方式
  • 方式三:使用路由router-link和router-view

v-if显示不同的组件

<template>
  <div>
    <button
      v-for="item in tabs"
      :key="item"
      @click="itemClick(item)"
      :class="{active: currentTab === item}"
    >{
    
    {
    
    item}}</button>

    <!-- 1.v-if的判断实现 -->
    <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 './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;
    }
  }
}
</script>

<style scoped>
.active {
    
    
  color: red;
}
</style>

动态组件的实现

<template>
  <div>
    <button
      v-for="item in tabs"
      :key="item"
      @click="itemClick(item)"
      :class="{active: currentTab === item}"
    >{
    
    {
    
    item}}</button>
    <!-- 2.动态组件 -->
    <component :is="currentTab"></component>
  </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;
    }
  }
}
</script>

<style scoped>
.active {
    
    
  color: red;
}
</style>

注意:上面is后的currentTab的值需要是什么内容呢?

  • 可以是通过component函数注册的组件
  • 在一个组件对象的components对象中注册的组件

动态组件的传值

如果是动态组件我们可以给它们传值和监听事件吗?

  • 和基本组件的传值是一样的,只是我们需要将属性和监听事件放到component上来使用
    在这里插入图片描述

二、keep-alive

  • 我们对上面的案例中About组件进行改造
  • 在其中增加了一个按钮,点击可以递增的功能
    在这里插入图片描述
  • 比如我们将counter点到10,那么在切换到home再切换回来about时,状态是否可以保持呢?
  • 答案是否定的
  • 这是因为默认情况下,我们在切换组件后,about组件会被销毁掉,再次回来时会重新创建组件
  • 但是,在开发中某些情况我们希望继续保持组件的状态,而不是销毁掉,这个时候我们就可以使用一个内置组件:keep-alive
    在这里插入图片描述
    keep-alive属性
  • include - string | RegExp | Array。只有名称匹配的组件会被缓
    存;
  • exclude - string | RegExp | Array。任何名称匹配的组件都不
    会被缓存
  • max - number | string。最多可以缓存多少组件实例,一旦达
    到这个数字,那么缓存组件中最近没有被访问的实例会被销毁
  • include 和 exclude prop 允许组件有条件地缓存
  • 二者都可以用逗号分隔字符串、正则表达式或一个数组来表示
  • 匹配首先检查组件自身的 name 选项
    在这里插入图片描述
    缓存组件的生命周期
对于缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期函数的
  • 但是有时候我们确实希望监听到何时重新进入到了组件,何时离开了组件
  • 这个时候我们可以使用activated deactivated 这两个生命周期钩子函数来监听
    在这里插入图片描述

三、异步组件

  • Webpack的代码分包
  • 默认的打包过程
  • 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过模块化直接依赖的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中)
  • 这个时候随着项目的不断庞大app.js文件的内容过大,会造成首屏的渲染速度变慢
  • 打包时,代码的分包
  • 所以,对于一些不需要立即使用的组件,我们可以单独对它们进行拆分,拆分成一些小的代码块chunk.js
  • 这些chunk.js会在需要时从服务器加载下来,并且运行代码,显示对应的内容
  • 那么webpack中如何可以对代码进行分包呢?
    在这里插入图片描述
    Vue中实现异步组件
  • 如果我们的项目过大了,对于某些组件我们希望通过异步的方式来进行加载(目的是可以对其进行分包处理),那么Vue中给我们提供了一个函数:defineAsyncComponent
  • defineAsyncComponent接受两种类型的参数
  • 类型一:工厂函数,该工厂函数需要返回一个Promise对象
  • 类型二:接受一个对象类型,对异步函数进行配置
  • 工厂函数类型的写法
    在这里插入图片描述- 对象类型一的写法
    在这里插入图片描述
    异步组件和Suspense
  • Suspense是一个内置的全局组件,该组件有两个插槽
  • default:如果default可以显示,那么显示default的内容
  • fallback:如果default无法显示,那么会显示fallback插槽的内容
<template>
  <div>
    App组件
    <home></home>

    <suspense>
      <template #default>
        <async-category></async-category>
      </template>
      <template #fallback>
        <loading></loading>
      </template>
    </suspense>

  </div>
</template>

<script>
  import {
    
     defineAsyncComponent } from 'vue';

  import Home from './Home.vue';
  import Loading from './Loading.vue';

  // import AsyncCategory from './AsyncCategory.vue';
  const AsyncCategory = defineAsyncComponent(() => import("./AsyncCategory.vue"))

  // const AsyncCategory = defineAsyncComponent({
    
    
  //   loader: () => import("./AsyncCategory.vue"),
  //   loadingComponent: Loading,
  //   // errorComponent,
  //   // 在显示loadingComponent组件之前, 等待多长时间
  //   delay: 2000,
  //   /**
  //    * err: 错误信息,
  //    * retry: 函数, 调用retry尝试重新加载
  //    * attempts: 记录尝试的次数
  //    */
  //   onError: function(err, retry, attempts) {
    
    

  //   }
  // })

  export default {
    
    
    components: {
    
    
      Home,
      AsyncCategory,
      Loading
    }
  }
</script>

<style scoped>

</style>

猜你喜欢

转载自blog.csdn.net/qq_41880073/article/details/124026940
今日推荐