Vue之深入理解组件

1. 父子组件传值

父组件通过属性向子组件传值

		<div id='root'>
		=>如果count加上冒号,则双引号里面是js表达式,传给的是数字
		=>如果不加冒号,就是一个字符串
			<counter :count="0" @change='toCount'></counter>
			<counter :count="0" @change='toCount'></counter>
			<div>{{total}}</div>
		</div>
			var counter1={
				props:['count'],=>子组件接收父组件传值count
				data:function(){=>在组件中,data中必须是一个方法
					return {
						number:this.count
					}
	=>子组件不能去修改父组件传递过来的count(单向数据流),原因在于,防止从子组件意外改变父级组件的状态
	=>修改了值之后可能会对其它组件造成影响,因此,把count传值给自身的data(在这里是number,即count的一个副本)
				},
				template:'<div>{{number}}\
				<button @click=\'handleClick\'>click</button>\
				</div>'
			}

子组件通过事件触发的形式向父组件传值

===在子组件中定义一个方法:向外触发事件change
				methods:{
					handleClick:function(){
						this.number+=2;
						this.$emit('change',2)
						=>向外触发了一个事件,名叫change,并传了一个参数2
					}
===父组件中监听change事件
			<counter :count="0" @change='toCount'></counter>
			<counter :count="0" @change='toCount'></counter>
===在父组件中定义toCount方法
				methods:{   	=>父组件接收到的参数2传给n
					toCount:function(n){
						this.total+=n
					}
				}

2. 组件参数校验

是指子组件从父组件接收到的参数需要符合一定的条件

				props:{
					content:[Number,String]
					=>传递过来的content必须是一个数字或者一个字符串
					
					=>更复杂的形式:
					content:{
						type:String, =>传递过来的content必须是一个String
						required:true,=>传递过来的content是必须要传的
						default:'default value',=>若required为false,则默认值就是default的值
						validator:function (value) {
							return(value.length>10)//传递过来的长度必须大于10
						}
					}
				}

3. 非props特性

props特性: 1.从父组件接收的props属性在dom结构中不会显示 2.子组件接收之后可以通过插值表达式或this.content的形式去取得content里的内容

非props特性: 1.并不在子组件中用props接收 2.在dom结构中会作为一个dom元素的属性

4. 给组件绑定原生事件

			Vue.component("child",{
			=>在此处,即模板内绑定的事件才是原生事件,子组件监听自身元素的事件
				template:'<div @click=\'handleClick\'>Child</div>',
				methods:{
					handleClick:function(){
						alert('child click');						
						this.$emit('clickthis')
			=>该语句向外触发事件,在父组件监听后产生一个自定义事件
					}
				}
			});
		<div id="root">
			<child @clickthis="handleThis"></child>
			=>父组件监听到自定义事件
		</div>

如何在父组件中直接监听到原生事件?

		<div id="root">
			<child @click.native="handleThis"></child>
			=>使用v-on的 .native 修饰符
		</div>
		
		<script>
			Vue.component("child",{
				template:'<div>Child</div>'
			});
			var vm=new Vue({
				el:'#root',
				methods:{
					handleThis:function(){
						alert('this')
					}
				}
			})
		</script>

5. 非父子组件传值

在这里插入图片描述
父子组件传值:1-2之间,2-3之间的数据传递
非父子组件传值:1-3之间,2-2之间,3-3之间的数据传递

利用总线机制(Bus)/发布-订阅模式/观察者模式 解决非父子组件传值

		<div id="root">
			<child content="我是第一个组件"></child>
			<child content="我是第二个组件"></child>
		</div>
		
		<script>
			Vue.prototype.bus=new Vue();
=>在Vue的prototype上绑定一个属性bus,使得每个实例/组件中都含有bus属性
			
			Vue.component("child",{
				props:{
					content:String
				},
				data:function(){
					return{
						selfContent:this.content
					}
				},
				template:'<div @click="handleClick">{{selfContent}}</div>',
				methods:{
					handleClick:function(){
						this.bus.$emit('change',this.selfContent)
						=>向外触发事件,并传递一个参数,即自身的selfContent
					}
				},
				mounted:function(){
					var this_=this;
					=>防止this的作用域发生改变
					this.bus.$on('change',function(msg){
					=>监听事件,修改传递过来的msg值
						this_.selfContent=msg;
						
					})
				}
			});
			var vm=new Vue({
				el:'#root'
			})
		</script>

6. 在Vue中使用插槽

		<div id="root">
			<child>  =>并没有插入任何内容,就会显示插入的<slot>
			</child>
		</div>
		
		<script>
			Vue.component("child",{
				template:'<div>\
							<p>hello </p>\
							<slot>默认内容</slot>\
						  </div>'
				=>元素作为组件模板之中的内容分发插槽。 元素自身将被替换。 
				
			})
			
			var vm=new Vue({
				el:'#root'
			})
		</script>

经过浏览器的渲染之后会是下面的效果:
在这里插入图片描述
如果在组件中插入任意的标签后,模板中的<slot>标签就会被替换为插入的内容:

			<child>
				<p>world!</p>
				<p>I am Vue.js</p>
			</child>

渲染结果会是这样:
在这里插入图片描述
具名插槽

元素有一个特殊的特性:name。这个特性可以用来定义额外的插槽.
一个不带 name 的 出口会带有隐含的名字“default”
具名插槽也可以有默认值

如果这样定义模板:

Vue.component("child",{
	template:'<div class="container">\
				<slot name="header"></slot>\
				<slot></slot>\
				<slot name="footer"></slot>\
	 		 </div>'
})

在组件中这样使用:

			<child>
				<p slot="header">this is a header</p>
				<p>this is a main body</p>
				<p slot="footer">this is a footer</p>
			</child>

在这里插入图片描述
当然也可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称,会渲染出相同效果:

<child>
	<template v-slot:header>
		<p>this is a header</p>
	</template>
	<template>
		<p>this is a main body</p>
	</template>
	<template v-slot:footer>
		<p>this is a footer</p>
	</template>
</child>

作用域插槽

当子组件做循环或者某一部分dom结构应该由外部传递进来时可以使用作用域插槽

		<div id="root">
			<child>
				<template slot-scope="thisSlot">
					=>item的数据就放于thisSlot中
					<!-- <li>{{thisSlot.item}}</li> -->
					<h1>{{thisSlot.item}}</h1>
				</template>
			</child>
		</div>	
		<script>
			Vue.component("child",{
				data:function(){
					return {
						list:[1,2,3,4]
					}
				},
				template:
				`<div>
					<ul>
						<slot
							v-for="item of list"
							:item=item
						></slot>
					<ul>
				</div>`
				
				=> :item=item指的是向slot里面传递item数据				
			});			
			var vm=new Vue({
				el:'#root'
			})
		</script>

7. 动态组件与v-once指令

在不同组件之间进行动态切换,可以使用component,渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。

	<body>
			<div id="root">
				<component v-bind:is="show"></component>
				<button @click="handleChange">Change</button>
			</div>			
			<script>			
				Vue.component('child-one',{
					template:'<div v-once>child one show</div>'					
				});
				Vue.component('child-two',{
					template:'<div v-once>child two show</div>'
				});				
				var vm =new Vue({
					el:'#root',
					data:{
						show:'child-one'
					},
					methods:{
						handleChange:function(){
							this.show=this.show==='child-one'
							?'child-two':'child-one'
						}
					}					
				})
			</script>
		</body>

v-once指令只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值