Vue.js 提供了一个特殊的元素 <component>
用来动态地挂载不同的组件 使用 is
属性来选择要挂载的组件。
<component v-bind:is="currentTabComponent">component>
在上述示例中,currentTabComponent 可以包括
<div id="app">
<button @click="changeView('A')">切换到组件Abutton>
<button @click="changeView('B')">切换到组件Bbutton>
<button @click="changeView('C')">切换到组件Cbutton>
<component :is="currentView">component>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
let vm = new Vue({
el: "#app",
data: {
currentView: 'comA'
},
components: {
comA: {
template: '组件A'
},
comB: {
template: '组件B'
},
comC: {
template: '组件C'
}
},
methods: {
changeView(component) {
this.currentView = 'com' + component;
}
}
});
script>
<div id="app">
<component :is="currentView">component>
div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
let Home = {
template:'我是组件'
}
let vm = new Vue({
el: "#app",
data: {
currentView: Home
}
});
script>
我们之前曾经在一个多标签的界面中使用 is
属性来切换不同的组件
<component v-bind:is="currentTabComponent">component>
当在这些组件之间切换的时候,我们有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题。
我们来看一个案例:
在这个案例中,如果我们选择了一篇文章,点击 “我的” 标签,然后再切换回 文章组件,是不会继续展示之前选择的文章的。这是因为你每次切换新标签的时候,Vue 都创建了一个新的组件实例。
重新创建动态组件的行为通常是非常有用的,但是在这个案例中,我们更希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个
元素将其动态组件包裹起来。
<keep-alive>
<component v-bind:is="currentTabComponent">component>
keep-alive>
修改后的效果如下:
现在这个 文章组件 标签保持了它的状态 (被选中的文章) 甚至当它未被渲染时也是如此。
keep-alive
是vue的一个内置组件,主要用于保留组件状态或避免重新渲染。
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
注意这个
要求被切换到的组件都有自己的名字,不论是通过组件的 name 选项还是局部/全局注册。
本案例的完整代码如下,大家可以直接复制粘贴到自己本地的一个html文件来运行测试:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>testtitle>
<style>
.article {
display: flex;
}
.left {
width: 100px;
border: 1px solid red;
}
.right {
width: 200px;
border: 1px solid blue;
}
li {
cursor: pointer;
}
.selected {
color: red;
}
style>
head>
<body>
<div id="app">
<button @click="changeView('comA')">文章button>
<button @click="changeView('comB')">我的button>
<keep-alive>
<componet :is="currentView">componet>
keep-alive>
div>
<template id="cpn1">
<div class="article">
<div class="left">
<ul>
<li v-for="(item,index) in articles" @click="articleClick(index)"
:class="{selected:currentIndex === index}">{
{item.name}}
li>
ul>
div>
<div class="right">
{
{content}}
div>
div>
template>
<template id="cpn2">
<div>
<h2>我的界面h2>
div>
template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
<script>
let comA = {
template: '#cpn1',
data() {
return {
articles: [
{
name: '文章1', content: '内容1'},
{
name: '文章2', content: '内容2'},
{
name: '文章3', content: '内容3'}
],
currentIndex: '',
content: '请选择一篇文章'
}
},
created() {
console.log('文章组件被创建');
},
destroyed() {
console.log('文章组件被销毁');
},
methods: {
articleClick(index) {
this.content = this.articles[index].content;
this.currentIndex = index;
}
}
}
let comB = {
template: '#cpn2'
}
let vm = new Vue({
el: "#app",
data: {
currentView: 'comA'
},
components: {
comA,
comB
},
methods: {
changeView(component) {
this.currentView = component;
}
}
});
script>
body>
html>
动态组件 | vue官网
keep-alive | vue官网