Vue之动态组件详解

  • Post author:
  • Post category:vue




Vue动态组件



一.背景

Vue 中提供有一个内置的组件叫做 component 。这个组件就是动态组件。它需要设置 is 属性。is 属性的值就是需要渲染的组件的名字

​ 动态组件在我们实际开发中是很有用的,比如我们要实现选项卡切换的操作,对应的选项卡内容是不同的组件,这时我们就可以考虑使用动态组件.

​ 我们知道,动态渲染组件的方式还很多种,比如使用v-if判断,v-show实现组件样式的显示与隐藏,但是呢,一般我们要考虑到性能的问题



1.v-if动态加载

v-if操作,如果我们有很多组件需要动态的加载,那么每一个组件都要去判断,如果成百上千个,那你的代码里基本上就全是v-if了,其实这还不算什么,

最主要的是v-if操作,一直从创建到销毁,会有dom开销,频繁切换的话,性能肯定很大的问题

额外扩展一句:使用v-if和v-once配合使用,可以达到v-show的性能要求

实际上使用动态组件时,也会有性能开销,毕竟动态组件的原理也是这样,切换过程中,也是组件的创建到销毁操作,不过动态组件可以通过keep-alive来实现状态保持,也就是缓存



2.v-show动态加载

v-show操作,虽然减少了频繁切换的性能开销,但是v-show实际上的原理只是做样式 的显示与隐藏,也就是说,在最开始加载的时候会全部加载,如果组件不大,可以这么做,但是如果组件很庞大的话,初始加载,那肯定也是不友好的

那这里,Vue中就给我们提供了一个内置组件:component也就是动态组件,可以解决这些问题



二.动态组件


动态组件就是几个组件放在一个挂载点下,然后根据父组件的某个变量来决定显示哪个


在挂载点使用 component 标签,然后使用 is =“组件名”,它会自动去找匹配的组件名,根据对应的显示;



1.动态组件实现

html:

		<section class="main">
            <component :is="current"></component>
        </section>
        <nav class='nav'>
            <a  @click="current='index'" href="javascript:">首页</a>
            <a  @click="current='find'" href="javascript:">发现</a>
            <a  @click="current='my'" href="javascript:">我的</a>
        </nav>

js:

Vue.component('index', {
            template: `
                <div>我是首页内容</div>
            `,
            beforeCreate() {
                console.log('beforeCreate index');
            },

            beforeDestroy() {
                console.log("beforeDestroy index");
            }
        });

        Vue.component('find', {
            template: `
                <div>我是发现内容</div>
            `,
            beforeCreate() {
                console.log('beforeCreate find');
            },

            beforeDestroy() {
                console.log("beforeDestroy find");
            }
        });

        Vue.component('my', {
            template: `
                <div>我是我的内容</div>
            `,
            beforeCreate() {
                console.log('beforeCreate my');
            },

            beforeDestroy() {
                console.log("beforeDestroy my");
            }
        });

        const vm = new Vue({
            el: '#app',
            data: {
                current: 'index'
            }
        });

上述代码就实现了一个动态组件加载的代码,其实理解起来很简单,需要动态加载 的组件共同维护data中的current数据,然后通过需要切换的按钮给绑定事件,去修改这个current为当前哪一个组件即可.

但是我们会发现一些问题,当我们每次切换的时候,组件的生命周期钩子函数也会相应触发,也就是说动态组件切换时也会有创建销毁的性能开销,vue给我们提供了下面的解决办法:keep-alive



2.keep-alive 状态保持


Vue 中提供了一个 keep-alive 内置组件。可以实现组件的缓存。

当在这些动态组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题.在动态组件上使用keep-alive,来实现组件缓存,

 			<keep-alive>
                <component :is="current"></component>
            </keep-alive>

使用keep-alive 将component动态组件包裹起来

  			Vue.component('index', {
            template: `
                <div>
                    我是首页内容
                    <p>{{name}}</p>
                    <button @click="name='zhangsan'">修改名字</button>
                </div>
            `,
            beforeCreate() {
                console.log('beforeCreate index');
            },

            beforeDestroy() {
                console.log("beforeDestroy index");
            },
            //当组件被keep-alive缓存时,会调用这个钩子函数(激活时)
            activated() {
                console.log("activated  index");
                
            },
            //当组件被keep-alive缓存时,会调用这个钩子函数(失活时)
            deactivated() {
                console.log("deactivated  index");
            },
            data() {
                return {
                    name: 'liuqiao'
                }
            }
        });

        Vue.component('find', {
            template: `
                <div>我是发现内容</div>
            `,
            beforeCreate() {
                console.log('beforeCreate find');
            },

            beforeDestroy() {
                console.log("beforeDestroy find");
            }
        });

        Vue.component('my', {
            template: `
                <div>我是我的内容</div>
            `,
            beforeCreate() {
                console.log('beforeCreate my');
            },

            beforeDestroy() {
                console.log("beforeDestroy my");
            }
        });

        const vm = new Vue({
            el: '#app',
            data: {
                current: 'index'
            }
        });

上述代码中,我要在index组件中修改name属性,然后切换到其他组件,再切换回来时,keep-aliver已经帮我保存了之前的操作状态,这就是keep-alive的作用



2.1 被keep-alive缓存组件特点
  • 切换组件时,当前组件不会触发销毁的生命周期钩子。也就是说不会销毁了。

  • 切换回来时,也不会重新创建。(既然都没有被销毁,哪里来的重新创建呢)

  • 会多出两个生命周期的钩子函数

    • activated 缓存激活 第一次会触发,组件能被看到时


      一般跟created钩子函数做一样的事情:请求数据

    • deactivated 缓存失活 不能被看到


      一般跟beforeDestory做一样的事情:清除定时器,移除全局事件监听

  • 可以在 vue devtools 上看见组件的缓存情况



2.2 keep-alive的更多属性设置


2.2.1 include 包含

使用方式

  • include=“组件1,组件2”
  • :include=[“组件1,组件2”] 数组形式,include前必须要有冒号
  • :include=’/^hello/’ 正则匹配,方式以hello开头的
   <keep-alive include="index,find">
         <component :is="current"></component>
   </keep-alive>

只会缓存这两个组件,其它的不被缓存



2.2.2 exclude排除

使用方式

  • exclude=“组件1,组件2” 注意 逗号前后不要有空格

  • :exclude=[“组件1,组件2”] 数组形式,exclude前必须要有冒号

  • :exclude=’/^hello/’ 正则匹配,方式以hello开头的排除

    1. :exclude=”[组件1, 组件2]”
    2. :exclude=”/^hello/”

使用方式与include相反

   <keep-alive exclude="index,find">
         <component :is="current"></component>
   </keep-alive>

除了这两个组件,其它的都被缓存



2.2.3 max 允许最大缓存的数量,默认无限制
   <keep-alive :max="5">
         <component :is="current"></component>
   </keep-alive>

先进先出原则 ,如果缓存队列有十几个,当超过最大缓存的数量后,会把第一次进来的挤掉



版权声明:本文为liuqiao0327原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。