Vue学习-------------(17)组件进阶使用

组件数据的存放

  • data属性必须是一个函数
  • 而且这个函数返回一个对象,对象内部保存着数据

将计数器封装为组件

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn></cpn>
	</div>

	<template id="ccc">
		<div>
			<h2>当前计数:{{counter}}</h2>
			<button @click="increment">+</button>
			<button @click="decrement">-</button>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		Vue.compotent('ccc' ,{
			template: '#ccc',
			data() {
				return{
					counter: 0
				}
			},
			methods: {
				increment() {
					this.counter++
				},
				decrement() {
					this.counter--
				}
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
		})
</body>
</html>

组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响。

 

父子组件的通信:

  • 通过props向子组件传递数据
  • 通过事件向父组件发送消息

Vue实例和子组件的通信与父组件和子组件的通信过程是一样的

props用法:

  • 在组件中,使用选项props来声明需要从父组件接收的数据
  • props的值有两种方式:
    • 方式一:字符串数组,数组中的字符串就是传递时的名称
    • 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn :cmovies="movies" :cmessage="message"></cpn>
	</div>

	<template id="ccc">
		<div>
			<h2>{{cmovies}}</h2>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		const cpn = {
			template: '#ccc',
			//数组写法:
			//props: ['cmovies', 'cmessage'],
			//对象写法:
			props: {
				//类型限制:
				//cmovies: Array ,
				//cmessage: String,
				//设置默认值:
				cmessage: {
					type: String,
					default: 'aaaaaaaaaaaa',
					required: true    //加上这个属性就必须给cmessage传值
				}
				//类型是对象或者数组时,默认值必须是一个函数
				cmovies: {
					type: Array,
					default() {
						return []
					}
				}
			},
			data() {
				return{
				}
			},
			methods: {
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
			data: {
				movies: ['海贼王', '海尔兄弟'],
				message: '你好啊'
			},
			compotents: {
				cpn        //字面量增强写法
			}
		})
</body>
</html>

  

 自定义事件:

  • 当子组件需要向父组件传递数据时,就要用到自定义事件
  • 之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件

自定义事件流程:

  • 在子组件中,通过$emit()来触发事件
  • 在父组件中,通过v-on来监听子组件事件
<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn @item-click="cpnClick"></cpn>
	</div>

	<template id="ccc">
		<div>
			<button v-for="item in categories" @click="btnClick(item)">
				{{item.name}}
			</button>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		const cpn = {
			template: '#ccc',
			data() {
				return{
					categories[
						{id: 'aaa', name: '热门推荐'},
						{id: 'bbb', name: '手机数码'},
						{id: 'ccc', name: '家用家电'},
						{id: 'ddd', name: '电脑办公'}
					]
				}
			},
			methods: {
				btnClick(item) {
					//发射事件:自定义事件
					this.$emit('item-click', item)
				}
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
			data: {
			},
			compotents: {
				cpn        //字面量增强写法
			},
			methods: {
				cpnClick(item) {
					console.log(item)
				}
			}
		})
</body>
</html>

  

有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件

  • 父组件访问子组件:使用$children或者$refs
  • 子组件访问父组件:使用$parent

$children的使用(实际开发中不常用):

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn></cpn>
		<cpn></cpn>
		<cpn></cpn>
		<button @click="btnClick">按钮</button>
	</div>

	<template id="ccc">
		<div>
			<p>我是子组件</p>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		const cpn = {
			template: '#ccc',
			data() {
				return{
					name: '我是子组件的name'
				}
			},
			methods: {
				showMessage() {
					console.log("showMessage")
				}
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
			data: {
			},
			compotents: {
				cpn        //字面量增强写法
			},
			methods: {
				btnClick() {
					console.log(this.$children);
					for(let c of this.$children) {
						console.log(c.name);
						c.showMessage();
					}
				}
			}
		})
</body>
</html>

  

$refs的使用:

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn></cpn>
		<cpn ref="aaa"></cpn>
		<cpn></cpn>
		<button @click="btnClick">按钮</button>
	</div>

	<template id="ccc">
		<div>
			<p>我是子组件</p>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		const cpn = {
			template: '#ccc',
			data() {
				return{
					name: '我是子组件的name'
				}
			},
			methods: {
				showMessage() {
					console.log("showMessage")
				}
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
			data: {
			},
			compotents: {
				cpn        //字面量增强写法
			},
			methods: {
				btnClick() {
					console.log(this.$refs);
					console.log(this.$refs.aaa.name);
					}
				}
			}
		})
</body>
</html>

  

$parent的使用(开发中不常使用,且不建议使用):

<!DOCTYPE HTML>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Untitled</title>
</head>
<body>
	<div id="app">
		<cpn></cpn>
	</div>

	<template id="ccc">
		<div>
			<p>我是子组件</p>
			<button @click="btnClick"></button>
		</div>
	</template>
	
	<script src="../js/vue.js"></script>
	<script>
		const cpn = {
			template: '#ccc',
			methods: {
				btnClick() {
					console.log("this.$parent")       //访问跟组件:$root
				}
			}
		})
		//root组件
		const app = new Vue({
			el: '#app' ,
			data: {
			},
			compotents: {
				cpn        //字面量增强写法
			},
			methods: {
			}
		})
</body>
</html>

  

posted @ 2021-03-17 11:49  455994206  阅读(55)  评论(0)    收藏  举报