Vue从入门到实战:动态组件

来自CloudWiki
跳转至: 导航搜索

在页面应用程序中,经常会遇到多标签页面,

在Vue.js中,可以通过动态组件来实现

组件的动态切换是通过在<component>元素上使用is属性来实现

Vue21021101.png

三个标签是三个按钮,下面的内容部分由组件来实现,

三个按钮对应三个组件,按钮响应click事件,点击不同按钮时切换不同的组件,

组件切换通过<component>元素和其上的<a>属性来实现。

定义组件

	Vue.component('tab-introduce', { 
				data(){
					return {
						content: 'Vue.js无难事'
					}
				},
				template: '<div><input v-model="content"></div>'
			})
			Vue.component('tab-comment', { 
				template: '<div>这是一本好书</div>' 
			})
			Vue.component('tab-qa', { 
				template: '<div>有人看过吗?怎么样?</div>' 
			})

定义根实例

在根实例中定义了两个数据属性和一个计算属性,

主要是为了便于使用v-for指令循环渲染button按钮,以及动态切换组件。

			var vm = new Vue({
			  el: '#app',
			  data: {
			    currentTab: 'introduce',
			    tabs: [
			    	{title: 'introduce', displayName: '图书介绍'}, 
			    	{title: 'comment', displayName: '图书评价'},
				   	{title: 'qa', displayName: '图书问答'}
			    ]
			  },
			  computed: {
			    currentTabComponent: function () {
			      return 'tab-' + this.currentTab
			    }
			  }
			})

在DOM中渲染

		<div id="app">
			<button
			  v-for="tab in tabs"
			  :key="tab.title"
			  :class="['tab-button', { active: currentTab === tab.title }]"
			  @click="currentTab = tab.title">
			  {{ tab.displayName }}
			</button>
			<!-- <keep-alive> -->
				<component
				  v-bind:is="currentTabComponent"
				  class="tab">
				</component>
			<!-- </keep-alive> -->
		</div>

当点击某个标签按钮时,更改数据属性currentTab的值,这将导致计算属性currentTabComponent的值更新,

<component>元素的is属性使用v-bind指令绑定到一个已注册组件的名字上。

用keep-alive改进

如果希望组件在切换的时候,可以保持组件的状态,可以用一个<keep-alive>元素将动态组件包裹起来。

 			<keep-alive>
				<component
				  v-bind:is="currentTabComponent"
				  class="tab">
				</component>
			</keep-alive>

完整代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>动态组件</title>
		<style>
			div {
				width: 400px;
			}
			.tab-button {
			  padding: 6px 10px;
			  border-top-left-radius: 3px;
			  border-top-right-radius: 3px;
			  border: solid 1px  #ccc;
			  cursor: pointer;
			  background: #f0f0f0;
			  margin-bottom: -1px;
			  margin-right: -1px;
			}
			.tab-button:hover {
			  background: #e0e0e0;
			}
			.tab-button.active {
			  background: #cdcdcd;
			}
			.tab {
			  border: solid 1px #ccc;
			  padding: 10px;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<button
			  v-for="tab in tabs"
			  :key="tab.title"
			  :class="['tab-button', { active: currentTab === tab.title }]"
			  @click="currentTab = tab.title">
			  {{ tab.displayName }}
			</button>
			<keep-alive>
				<component
				  v-bind:is="currentTabComponent"
				  class="tab">
				</component>
			</keep-alive>
		</div>
	  <script src="vue.js"></script>
		<script>
			Vue.component('tab-introduce', { 
				data(){
					return {
						content: 'Vue.js无难事'
					}
				},
				template: '<div><input v-model="content"></div>'
			})
			Vue.component('tab-comment', { 
				template: '<div>这是一本好书</div>' 
			})
			Vue.component('tab-qa', { 
				template: '<div>有人看过吗?怎么样?</div>' 
			})

			var vm = new Vue({
			  el: '#app',
			  data: {
			    currentTab: 'introduce',
			    tabs: [
			    	{title: 'introduce', displayName: '图书介绍'}, 
			    	{title: 'comment', displayName: '图书评价'},
				   	{title: 'qa', displayName: '图书问答'}
			    ]
			  },
			  computed: {
			    currentTabComponent: function () {
			      return 'tab-' + this.currentTab
			    }
			  }
			})
		</script>
	</body>
</html>