子组件获取父组件的值

如果子组件想获取父组件的值,
那么首先在子组件通过pros属性,得到父组件的值
其次在子标签里面添加 如:msg=‘’msg 来读取父组件的值
最后在子模板里面就可以调用了

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<input type="text" v-model="message" />
		<!-- 这里的 :msg一定时pros的属性名 -->
		<child_cmp :msg="message"></child_cmp>
			<child_cmp :msg="msg"></child_cmp>
		</div>
		<template id="container">
		
			<div>我调用父组件的结果为:{{msg}}</div>
			
		</template>
	</body>
	
	
	
	<script src="../js/vue.js"></script>
	
	<script>
		// Vue.component("child_cmp",{
		// 	template:container,
		// 	props:['msg']
		// })
		const app = new Vue({
			el:"#app",
			data:{
				msg:"子组件获取父组件的值",
				message:""
			},
			components:{
				'child_cmp':{
					template:container,
					props:['msg']
				}
			}
		}
		)
		
	</script>
</html>

子组件向父组件传值

需用通过自定义组件来完成
自定义事件的流程:
在子组件中,通过$emit()来触发事件。
在父组件中,通过v-on来监听子组件事件。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
			<!-- 通过子组件发送的方法名,在为其设置相应点击事件 -->
		<child_cmp @increment="changeToal" @decrement="changeToal"></child_cmp>
		<div>{{total}}</div>
		</div>
		
		
		<template id="container">
			<div>
				
		<button v-on:click="increment">+1</button>
		<button v-on:click="decrement" >-1</button>
		</div>
		</template>
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
	
		const app = new Vue({
			el:"#app",
			data:{
				total:0
			},
			methods:{
				//counter是由子组件发送出来的
				changeToal(counter){
					this.total =counter
				}
			},
			//子组件
			components:{
				'child_cmp':{
					template:container,
					data(){
						return{
							counter:0
						}
					},
					methods:{
						increment(){
							this.counter++;
							//发送 一个方法为increment,同时把counter传递出去
							this.$emit("increment",this.counter)
						},
						decrement(){
							this.counter--;
								//发送 一个方法为decrement,同时把counter传递出去
							this.$emit("decrement",this.counter)
						}
					}
				}
			}
		}
		)
		
	</script>
</html>

说明

有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问跟组件。
父组件访问子组件:使用 c h i l d r e n 或 children或 childrenrefs reference(引用)
子组件访问父组件:使用$parent

父子组件的访问方式: $children
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
			<child_cmp></child_cmp>
				<button v-on:click="showparent">获取子组件的信息</button>
		</div>
		</template>
		<!-- 子组件模板 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>

		</div>
		</template>
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		methods:{
			showparent(){
			
				console.log(this.$children[0]);}
			
		}
	});
	//注册子组件
	Vue.component('child_cmp',{
		template:child_com
	})
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

c h i l d r e n 的 缺 陷 : 通 过 children的缺陷: 通过 childrenchildren访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs
$refs的使用:
r e f s 和 r e f 指 令 通 常 是 一 起 使 用 的 。 首 先 , 我 们 通 过 r e f 给 某 一 个 子 组 件 绑 定 一 个 特 定 的 I D 。 其 次 , 通 过 t h i s . refs和ref指令通常是一起使用的。 首先,我们通过ref给某一个子组件绑定一个特定的ID。 其次,通过this. refsref使refIDthis.refs.ID就可以访问到该组件了。

父子组件的访问方式: $refs
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
			<child_cmp ref="child1"></child_cmp>
				<child_cmp2 ref="child2"></child_cmp2>
				<button v-on:click="showparent">获取子组件的信息</button>
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>

		</div>
		</template>
		
		<!-- 子组件模板2 -->
		<template id="child_com2">
			<div>
			<h1>我是子组件222</h1>
		
		</div>
		</template>
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		methods:{
			showparent(){
			
				console.log(this.$refs.child1.message),
					console.log(this.$refs.child2.message);
					}
			
		}
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		data(){
			return{
				message:0
			}
		}
	})
	//注册子组件2
	Vue.component('child_cmp2',{
		template:child_com2,
		data(){
			return{
				message:222222
			}
		}
	})
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

父子组件的访问方式: $parent

如果我们想在子组件中直接访问父组件,可以通过 p a r e n t 注 意 事 项 : 1. 尽 管 在 V u e 开 发 中 , 我 们 允 许 通 过 parent 注意事项: 1.尽管在Vue开发中,我们允许通过 parent1.Vueparent来访问父组件,但是在真实开发中尽量不要这样做。
2.子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。
3.如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。
4.另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
			<child_cmp ref="child1"></child_cmp>
				
				<button v-on:click="showparent">获取子组件的信息</button>
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>
			<button v-on:click="showparent">展示父组件中的数据</button>

		</div>
		</template>
		
	
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		
		methods:{
			showparent(){
			
				console.log(this.$refs.child1.message)
					
					}
			
		},
		data(){
			return{
				parent:"我是父组件丫"
			}
		}
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		data(){
			return{
				message:0
			}
		},
		methods:{
			showparent(){
				console.log(this.$parent.parent)
			}
		}
	})


//实例化
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

slot插槽用法
组件的插槽:
组件的插槽也是为了让我们封装的组件更加具有扩展性。
让使用者可以决定组件内部的一些内容到底展示什么。
如何封装合适呢?抽取共性,保留不同。
最好的封装方式就是将共性抽取到组件中,将不同暴露为插槽。
一旦我们预留了插槽,就可以让使用者根据自己的需求,决定插槽中插入什么内容。
是搜索框,还是文字,还是菜单。由调用者自己来决定。

普通插槽

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
			<child_cmp></child_cmp>
				<child_cmp>
					<div>我是父组件修改之后的插槽</div>
					</child_cmp>
				
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>
		<slot>我是默认插槽</slot>

		</div>
		</template>
		
	
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		
		
	})


//实例化
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

具名插槽slot

在具名插槽中,如果不指定slot=“”,就不会显示内容

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
			<child_cmp>
				<!-- <div >左插槽</div>
				<div >中间插槽</div>
				<div >右插槽</div> -->
				</child_cmp>
				<child_cmp>
					<div slot="left">左插槽</div>
					<div slot="midd">中间插槽</div>
					<div slot="right">右插槽</div>
					</child_cmp>
				
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>
			<!-- 三个具名插槽 -->
		<slot name="left"></slot>
<slot name="midd"></slot>
<slot name="right"></slot>
		</div>
		</template>
		
	
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		
		
	})


//实例化
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

编译作用域
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。

下面代码的isshow使用过程是相当于在父组件中出现的

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
		
				<child_cmp v-show="isshow">
					</child_cmp>
				
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>
			<!-- 三个具名插槽 -->
		<slot name="left"></slot>
<slot name="midd"></slot>
<slot name="right"></slot>
		</div>
		</template>
		
	
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		data(){
			return{
				isshow:true
			}
		}
		
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		data(){
			return{
				isshow:false
			}
		}
		
	})


//实例化
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>

作用域插槽

在父组件使用我们的子组件时,从子组件中拿到数据:
我们通过<template slot-scope="slotProps">获取到slotProps属性
在通过slotProps.data就可以获取到刚才我们传入的data了

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id="app">
		<parent_cmp></parent_cmp>
		</div>
		
		<!-- 父组件模板 -->
		<template id="parent_com">
			<div>
		<!-- //列表形式展示 -->
				<child_cmp>
					<!-- 在父组件使用我们的子组件时,从子组件中拿到数据 -->
					<template slot-scope="slotProps">
						<ul>
							<li v-for="inf in slotProps.data">{{inf}}</li>
						</ul>
					</template>
					</child_cmp>
				<!-- //横着展示 -->
				
				<child_cmp>
					<!-- 在父组件使用我们的子组件时,从子组件中拿到数据 -->
					<template slot-scope="slotProps">
						
							<span v-for="inf in slotProps.data">{{inf+" : "}}</span>
						
					</template>
					</child_cmp>
		</div>
		</template>
		<!-- 子组件模板1 -->
		<template id="child_com">
			<div>
			<h1>我是子组件</h1>
			<slot :data="study"></slot>
		</div>
		</template>
		
	
	</body>
	
	
	
	<script src="../js/vue.js"></script>

	<script>
		//注册父组件
	Vue.component('parent_cmp',{
		template:parent_com,
		
		
	});
	//注册子组件1
	Vue.component('child_cmp',{
		template:child_com,
		data(){
			return{
				study:['Java','C','Vue']
			}
		}
		
	})


//实例化
		const app = new Vue({
			el:"#app",
			data:{
				
			},
		}
		)
		
	</script>
</html>