13 - Vue 学习笔记 -注册组件语法糖、模板分离写法、组件访问数据

注册组件语法糖

之前的注册组件的方式,可能有些繁琐。
Vue 为了简化整个过程,提供了注册的语法糖。
主要是省去了调用 Vue.extend() 的步骤,而是可以直接使用一个对象代替。

<div id="app">
	<cpn1></cpn1>
	<cpn2></cpn2>
</div>

<script src="../js/vue.js"></script>
<script>
	// 1. 全局组件注册的语法糖
	// 1. 创建组件构造器
	// const cpn1 = Vue.extend();
	// 2. 注册组件
	// 全局组件
	Vue.component('cpn1', {
		template: `
			<div>
				<h2>我是标题1</h2>
				<p>我是内容,哈哈哈</p>
			</div>
		`
	});
	
	const app = new Vue({
		el: "#app",
		data: {
			message: "hello"
		},
		components: {
			// 局部组件
			cpn2: {
				template: `
					<div>
						<h2>我是标题2</h2>
						<p>我是内容,嘻嘻嘻</p>
					</div>
				`
			}
		}
	});
</script>

模板分离的写法

我们会发现,我们使用了语法糖后,代码中出现了大量的 HTML 代码,特别不方便阅读。所以我们需要把模板抽离出来,写在外面,让代码好阅读。

<div id="app">
	<cpn></cpn>
	<cpn2></cpn2>
</div>

<!-- 1. script 标签,类型必须是 text/x-template -->
<script type="text/x-template" id="cpn">
	<div>
		<h2>我是标题1</h2>
		<p>我是内容,哈哈哈</p>
	</div>
</script>

<!-- 2. template 标签 -->
<template id="cpn2">
	<div>
		<h2>我是标题2</h2>
		<p>我是内容,嘻嘻嘻</p>
	</div>
</template>

<script src="../js/vue.js"></script>
<script>
	// 1. 注册一个全局组件
	Vue.component('cpn', {
		template: '#cpn'
	})
	const app = new Vue({
		el: "#app",
		data: {
			message: "hello"
		},
		components: {
			cpn2: {
				template: '#cpn2'
			}
		}
	});
</script>
  1. 使用 script 标签 type 属性为 text/x-template
  2. 使用 template 标签。

都需要通过 id 来找到到模板!
还有一点需要注意,在定义模板时,我们需要一个明确的根元素,否则 Vue 可能会报错,也就是我们需要用一个标签把模板内容包裹起来,在上面就是 div 标签。

组件访问 Vue 实例数据

组件可以访问 Vue 实例数据嘛?
<div id="app">
	<cpn></cpn>
</div>

<script src="../js/vue.js"></script>
<script>
	const app = new Vue({
		el: "#app",
		data: {
			message: "hello"
		},
		components: {
			cpn: {
				// Vue 会报错提示找不到 message
				template: `
					<div>
						<h2>{{message}}</h2>
						<p>我是内容,嘻嘻嘻</p>
					</div>
				`
			}
		}
	});
</script>

通过上面代码,我们可以发现组件是不能直接访问到 Vue 实例里面的数据,
结论:Vue 组件应该有自己保存数据的地方。

通过 data 访问数据

我们可以给组件也添加 data 属性,如下

components: {
	cpn: {
		// Vue 会报错提示找不到 message
		template: `
			<div>
				<h2>{{message}}</h2>
				<p>我是内容,嘻嘻嘻</p>
			</div>
		`,
		data: {
			message: 'hello'
		}
	}
}

但是,会发现 Vue 给我们报错了
The "data" option should be a function that returns a per-instance value in component definitions.
原来,组件中的 data 不是一个对象,而是一个函数,然后通过函数返回实例对象,所以我们进行修改。

data() {
	// 返回实例对象
	return {
		message: 'hello'
	}
}

就会发现,可以正常访问到 message 了,所以我们知道了。

  • 组件对象也有一个 data 属性(也可以有 methods 等属性,后面会用到)
  • 只是这个 data 属性必须是一个函数。
  • 而且这个函数返回一个对象,对象内部保存着数据。
为什么 data 必须是一个函数

我们通过一个案例来引出,我们先把之前做的计数器,封装成一个组件

<div id="app">
	<h2>当前计数:{{counter}}</h2>
	<button @click="add">+</button>
	<button @click="sub">-</button>
</div>

<script src="../js/vue.js"></script>
<script>
	const app = new Vue({
		el: "#app",
		data: {
			counter: 0
		},
		method: {
			add: function () {
				this.counter++;
			},
			sub: function () {
				this.counter--;
			}
		}
	});
</script>

封装后:

<!-- 组件实例对象 -->
<div id="app">
	<cpn></cpn>
	<cpn></cpn>
	<cpn></cpn>
</div>

<template id="cpn">
	<div>
		<h2>当前计数:{{counter}}</h2>
		<button @click="add">+</button>
		<button @click="sub">-</button>
	</div>
</template>

<script src="../js/vue.js"></script>
<script>
	// 1. 注册组件
	Vue.component('cpn', {
		template: `#cpn`,
		data() {
			return {
				counter: 0
			}
		},
		methods: {
			add() {
				this.counter++;
			},
			sub() {
				this.counter--;
			}
		}
	})
	
	const app = new Vue({
		el: "#app",
		data: {
			message: "hello"
		}
	});
</script>

我们实例了3个 cpn 实例,那么我们思考一个问题,这3个实例是不是都有 counter 属性,他们之间的 counter 属性是同一个嘛?或者说,他们的 data 对象是同一个嘛?

很显然,如果他们的 data 对象是同一个,那么我们对其中一个组件进行按了 + 号,其他的值也会发生改变,我们测试就会发现很显然不是一个 data

并且,我们是通过一个函数,返回了一个 data 对象,每次返回的都不是同一个对象,这也可以验证。
所以我们知道了为什么 data 是用函数返回一个对象,而不是直接使用对象。

这就好像类有静态成员和非静态成员,每个实例出来的对象共享的是静态成员,而非静态成员是每个对象自己特有的属性,他们的值不一定相同,也互不影响。如果组件中的 data 不是返回一个对象,那么很显然,每个组件共享一个 counter 这显然不是我们想要的组件。

组件应该是可以复用的,每一个实例出来的组件都是独立的互不影响的,所以 data 是使用函数返回一个对象。可以保证每个组件维护自己的 counter 而不干扰其他组件的 counter

类 —> 组件
类的成员变量 —> 组件的 data
类的方法 —> 组件的函数
类的实例 —> 实例组件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值