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开头的排除
- :exclude=”[组件1, 组件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>
先进先出原则 ,如果缓存队列有十几个,当超过最大缓存的数量后,会把第一次进来的挤掉