5、组件基础、组件注册、全局组件和局部组件、组件模板抽离

基本示例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="components-demo">
			<button-counter></button-counter>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<script>
			/* 定义一个名为button-counter的组件 */
			Vue.component('button-counter', {
				data: function() {
					return {
						count: 0
					}
				},
				template: '<button v-on:click="count++">You click me {{count}} times.</button>'
			})
			
			new Vue({
				el:'#components-demo'
			})
		</script>
	</body>
</html>

组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 <button-counter>。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用。

因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

组件的复用

你可以将组件进行任意次数的复用:

<div id="components-demo">
    <button-counter></button-counter>
    <button-counter></button-counter>
    <button-counter></button-counter>
</div>

注意当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。
在这里插入图片描述

data必须是一个函数

当我们定义这个 <button-counter> 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:

data: {
  count: 0
}

取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

在这里插入图片描述

组件的组织

通常一个应用会以一棵嵌套的组件树的形式来组织:
在这里插入图片描述

例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册局部注册

至此,我们的组件都只是通过 Vue.component 全局注册的。

全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。(Vue根实例的组件树)

组件注册

组件名

在注册一个组件的时候,我们始终需要给它一个名字。

Vue.component('my-component-name', { /* ... */ })

该组件名就是 Vue.component 的第一个参数。

组件名的大小写

定义组件名的方式有两种:

使用 kebab-case

Vue.component('my-component-name', { /* ... */ })

当使用 kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>

使用 PascalCase

Vue.component('MyComponentName', { /* ... */ })

当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name><MyComponentName> 都是可接受的。注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。

所以尽量在使用时采用短横线分隔命名法。

全局注册

Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })

new Vue({ el: '#app' })
<div id="app">
  <component-a></component-a>
  <component-b></component-b>
  <component-c></component-c>
</div>

这三个组件在各自内部也都可以相互使用。(每个组件必须只有一个根元素

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="components-demo">
			<my-component-a></my-component-a>
			<my-component-b></my-component-b>
			<my-component-c></my-component-c>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<script>
			Vue.component('my-component-a', {
				template:'<h3><my-component-c></my-component-c></h3>'
			});
			Vue.component('my-component-b', {
				template:'<my-component-a></my-component-a>'
			});
			Vue.component('my-component-c', {
				template:'<span>c</span>'
			})
			new Vue({
				el:'#components-demo'
			})
		</script>
	</body>
</html>

在这里插入图片描述

局部注册

你可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

对于 components 对象中的每个 property 来说,其 property 名就是自定义元素的名字,其 property 值就是这个组件的选项对象。

注意局部注册的组件在Vue根实例的子组件中不可用

如果你希望 ComponentAComponentB 中可用,则你需要这样写:

var ComponentA = { /* ... */ }

var ComponentB = {
  components: {
    'component-a': ComponentA
  },
  // ...
}

或者如果你通过 Babel 和 webpack 使用 ES2015 模块,那么代码看起来更像:

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  },
  // ...
}

注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="components-demo">
			<component-a></component-a>
		</div>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<script>
			var ComponentB = {
				template: '<div>局部组件B</div>'
			}
			var ComponentA = {
				data: function() {
					return {
						msg: '局部组件A'
					}
				},
				components:{
					'component-b':ComponentB
				},
				template:'<div>{{msg}}<component-b></component-b></div>'
			}
			new Vue({
				el:'#components-demo',
				components:{
					'component-a': ComponentA
				}
			})
		</script>
	</body>
</html>

组件模板抽离

在组件中写template模板的HTML代码是一件十分麻烦的事,特别不方便。

Vue提供了两种方案写HTML代码

  • 使用script标签(不常用)
  • 使用template标签
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Title</title>
	</head>
	<body>
		<div id="app">
			<my-component></my-component>
		</div>

		<!-- 使用template标签 -->
		<template id="my-component-template">
			<div>
				<h2>我是全局组件标题</h2>
				<p>我是内容</p>
			</div>
		</template>

		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<script>
			/* 注册全局组件:组件与模板分离 */
			Vue.component('my-component', {
				template: '#my-component-template',
			});

			const app = new Vue({
				el: '#app',
			})
		</script>
	</body>
</html>

猜你喜欢

转载自blog.csdn.net/ShawnYue_08/article/details/107860017