Vue2之父子组件通信

1. 父子组件的数据来源

父组件数据在new Vue实例中,data数据形式对象、函数都可以;
子组件数据在Vue.component中,data数据形式必须用函数

2. 父子组件单向绑定

父向子传值(props)

父级 prop 的更新会向下流动到子组件中,但是反过来则不行,避免子组件意外变更父级组件的状态。
注意:父组件通过props单向传递给子组件,子组件只能读不能修改

静态赋值 vs 动态赋值

<!--静态赋值-->
<child-item title='hello'></child-item>
<!--动态赋值(变量,表达式)-->
<child-item v-bind:title='title'></child-item>
<child-item v-bind:title="name+':'+title"></child-item>

动态prop示例

<!--创建一个容器包裹模板内容-->
<div id='root'>
	<div v-show="doc.show">{{doc.title}}</div>
	<!--父组件通过自定义属性向子组件传值-->
	<child-item v-bind:title='doc.title'></child-item>
</div>
<script type="text/javascript">
	// 注册组件,先于vue实例
	Vue.component('child-item',{
	    // 接受父组件传来的值
		props:['title'],
		// 子组件内容
		template:`
			<div>
				<h2>子组件布局</h2>
				<h2>{{title}}</h2>
			</div>
		`
	});
	// 实例vue,操作容器
	new Vue({
		el:'#root',
		data:{
			doc:{
	            title:'你好',
	            show:true
	    	}
    	}
	});
</script>

父组件向子组件传入对象所有的property,可使用不带参数的 v-bind

<!--子组件-->
<child-item v-bind='doc'></child-item>
<script>
	Vue.component('child-item',{
		// 每一个property作为prop传入
		props:['title','show'],
		template:`
			<div>
				<h2>子组件布局</h2>
				<h2 v-show='show'>{{title}}</h2>
			</div>
		`
	});
</script>
<!--等价于
<child-item v-bind:doc='doc'></child-item>
<script>
	Vue.component('child-item',{
		// 每一个property作为prop传入
		props:['doc'],
		template:`
			<div>
				<h2>子组件布局</h2>
				<h2 v-show='doc.show'>{{doc.title}}</h2>
			</div>
		`
	});
</script>
-->

子向父传值

自定义事件(通过$emit触发)

父组件通过v-on监听子组件实例,子组件可以通过调用内建的$emit方法并传入事件名称来触发一个事件,同时$emit的第二个参数是子组件向父组件传递的值,父组件通过$event接收。
若父组件通过方法update接收且无参数,默认update($event)

<div id='root'>
		<div v-show="doc.show">这是父组件内容:{{doc.title}}</div>
		<!--父组件通过$event接收参数,除了写表达式也可以写方法接收并处理参数-->
		<child-item v-bind:doc='doc' v-on:update:show="doc.show=$event"></child-item>
		<!--等价于 <child-item v-bind:doc='doc' v-on:update:show="update"></child-item>-->
	</div>
	<script type="text/javascript">
		Vue.component('child-item',{
			// 接受父组件传来的值
			props:['doc'],
			template:`
				<div>
					<h2>子组件布局</h2>
					<h2>{{doc.title}}</h2>
					<button v-on:click="handle">点击隐藏父组件内容</button>
				</div>
			`,
			methods:{
				handle(){
					// 用于子组件向父组件触发事件,提供第二个参数(抛出的值)
					this.$emit('update:show',!this.doc.show)
				}
			}
		});
		new Vue({
			el:'#root',
			data:{
				doc:{
					title:'你好',
					show:true
				}
			},
			methods:{
			    /* 接收子组件传递过来的值
                update1(val){
                    this.show=val
                }*/
			}
		});
</script>

3. 父子组件双向绑定

v-model

通常用于表单元素的双向绑定,例如输入框、复选框等。它也可以用于子组件的双向绑定

v-model 实际上就是 props:value$emit('input')组合语法糖:

  1. v-bind 绑定 value 属性的值 - props:value;
  2. v-on 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中 - $emit(‘input’);
<custom-input v-model="searchText"></custom-input>
<!-- 等价于 -->
<custom-input
	v-bind:value="searchText"
	v-on:input="searchText = $event">
</custom-input>

单个值示例

<div id="modeltest">
        <custom-input v-model="searchText"></custom-input>
</div>
<script type="text/javascript">
	Vue.component('custom-input',{
      	props: ['value'],
        template: `
        	<input
               	v-bind:value="value"
               	v-on:input="$emit('input',$event.target.value)"
            >
        `
       });
	var vm = new Vue({
           el: '#modeltest',
           data: {
               searchText:'请输入相关值'
           }
       });
</script>

这个组件内的 <input> 必须:

  • 将其 value attribute 绑定到一个名叫 valueprop
  • 在其 input 事件被触发时,将新的值通过自定义的 input事件抛出

对象示例

<div id='root'>
	<div v-show="doc.show">{{doc.title}}</div>
	<child-item v-model='doc'></child-item>
</div>
<script type="text/javascript">
	Vue.component('child-item',{
		props:['value'],
		template:`
			<div>
				<h2>子组件布局</h2>
				<h2>{{value.title}}</h2>
				<input
                	v-bind:value="value.title"
                	v-on:input="$emit('input',
					{...value,// 展开原对象
                    title: $event.target.value // 仅更新 title
					})"
                >
				<button @click="handle">点我隐藏</button>
			</div>
		`,
		methods:{
			handle(){
				this.$emit('input', {
            		...this.value,           // 展开原对象
            		show: !this.value.show   // 修改 show 属性
        		});
			}
		}
	});
	new Vue({
		el:'#root',
		data:{
			doc:{
	            title:'你好',
	            show:true
	    	}
    	}
	});
</script>

注意:父组件传递对象时,子组件需要返回完整对象结构,不可以直接写成"$emit(‘input’, $event.target.value)",会破坏对象结构,即doc对象变成了字符串

.sync修饰符

用于简化update:myPropName的模式,也是父子组件之间的双向绑定的语法糖,适用同步多个prop的值
注意:使用.sync时,$emit所调用的事件名必须是update:属性名

<child-item v-bind.sync="show" ></childe-item>
<!--等价于-->
<child-item v-bind:show="show" v-on:update:show="update"></childe-item> 

示例

<div id='root'>
	<div v-show="doc.show">{{doc.title}}</div>
	<child-item v-bind.sync='doc'></child-item>
</div>
<script type="text/javascript">
	Vue.component('child-item',{
	    // 把 doc 对象整个传入,那么其中的每一个 property (如 title) 都作为一个独立的 prop 传进来
		props:['title','show'],
		template:`
			<div>
				<h2>子组件布局</h2>
				<h2>{{title}}</h2>
				<button @click="handle1">点我展示/隐藏父组件</button>
				<button @click="handle2">点我修改title</button>
			</div>
		`,
		methods:{
			handle1(){
				this.$emit('update:show',!this.show)
			},
			handle2(){
				this.$emit('update:title',this.title=='hello'?'你好':'hello')
            }
		}
	});
	new Vue({
		el:'#root',
		data:{
			doc:{
	            title:'你好',
	            show:true
	    	}
    	}
	});
</script>

带有 .sync 修饰符的 v-bind 不能和表达式一起使用,如v-bind:title.sync=”doc.title + ‘!’”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值