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