Vue 父子组件间通信

vue的局部组件的使用

渲染组件-父使用子组件

  • 1: 创建子组件(对象)

    • var Header = { template:'模板' , data是一个函数,methods:功能,components:子组件们 }
  • 2: 在父组件中声明,根属性components:{ 组件名:组件对象 }

  • 3: 在父组件要用的地方使用 <组件名></组件名>

    • 在不同框架中,有的不支持大写字母,用的时候

      • 组件名 MyHeader
      • 使用 my-header
  • 总结: 有父,声子,挂子,用子

	<div id="app">
		
	</div>
	<script type="text/javascript" src="./vue.min.js"></script>
	<script type="text/javascript">
		// 全局组件
		// 第一个参数是组件的名字 第一个参数是options
		Vue.component('Vbtn',{
			template:`

				<button>按钮</button>
			`
		});

		var Vcontent = {
			template:`

				<div>
					我是内容组件
					<Vbtn />
					<Vbtn />
					<Vbtn />
				</div>
			`
		};


		var Vaside = {
			template:`

				<div>
					我是侧边栏组件
					<Vbtn />
					
				</div>
			`
		};

		var Vheader = {
			data(){
				return {

				}
			},
			template:`

				<div>
					我是头部组件
					
				</div>
			`,
			methods:{

			}
		};

		// 1.声子
		var App = {
			template:`
				<div>
					<Vheader />
					<div>
						<Vaside />
						<Vcontent />
					</div>

				</div>
			`,
			components:{
				Vheader,
				Vaside,
				Vcontent
			}
		};
		
		new  Vue({
			el:'#app',
			data(){
				return {

				}
			},
			components:{
				// 2.挂子
				App
			},
			// 3.用子
			template:`<App />`
		});
	</script>
通过prop往子组件通信

父子组件传值(父传子)

  • 1:父用子的时候通过属性Prop传递

  • 2:子要声明props:[‘属性名’] 来接收

  • 3:收到就是自己的了,随便你用

    • 在template中 直接用
    • 在js中 this.属性名 用
  • 总结:父传,子声明,就是子的了

  • 小补充: 常量传递直接用,变量传递加冒号

        <div id="app">
		
	</div>
	<script type="text/javascript" src="./vue.min.js"></script>
	<script type="text/javascript">
		// 全局组件
		// 第一个参数是组件的名字 第一个参数是options
		// 1.Parent  2.Child
		Vue.component('Child',{
			created(){
				console.log(this.childData);
			},
			template:`
				<div>
					<p>我是一个孩子组件{{childData}}</p>
					<input type="text" v-model = 'childData'/>

				</div>
			`,
			props:['childData']
		});
		// 父===> 子
		// 1.先给父组件中绑定自定义的属性
		// 2.在子组件中使用props接收父组件传递的数据
		// 3.可以在子组件中任意使用

		Vue.component('Parent',{
			data(){
				return {
					msg:"我是父组件的数据"
				}
			},
			template:`
				<div>
					<p>我是一个父组件</p>
					<Child  :childData ='msg' />

				</div>
			`
		});
		// 1.声子
		var App = {
			template:`
				<div>
					<Parent />
				</div>
			`
			
		};
		
		new  Vue({
			el:'#app',
			data(){
				return {

				}
			},
			components:{
				// 2.挂子
				App
			},
			// 3.用子
			template:`<App />`
		});
	</script>

总结父传子

  • 父用子 先声子,挂子,用子
  • 父传子 父传子(属性),子声明(收),子直接用(就是自己的一样)
通过事件向子组件发送消息

子传父

  • 1.子要绑定原生事件,在原生事件函数中通过this.$emit(‘自定义的事件名’,arg1);触发父组件中子组件自定义的事件名
  • 2.父组件中的子组件v-bind:自定义事件的名字 = 'fn'绑定自定义的事件
  • 3.父组件 就可以触发fn的函数 数据就可以从子组件中传过来了
	<div id="app">
		
	</div>
	<script type="text/javascript" src="./vue.min.js"></script>
	<script type="text/javascript">
		Vue.component('Child',{
			template:`
				<div>
					<p>我是一个孩子组件</p>
					<input type="text" v-model = 'childData' @input = 'changeValue(childData)'/>

				</div>
			`,
			props:['childData'],
			methods:{
				changeValue(val){
					// 自定义的事件 一定通过this.$emit()去触发
					// $emit(自定义的事件名,消息)
					this.$emit('childHandler1',val)
				}
			}
		});
		// 子 ===》 父
		// 1.在父组件绑定 自定义的事件  
		// 2.在子组件中 触发原生的事件 在函数中使用 $emit触发自定义的childHandler

		Vue.component('Parent',{
			data(){
				return {
					msg:"我是父组件的数据"
				}
			},
			template:`
				<div>
					<p>我是一个父组件</p>
					<Child  :childData ='msg' @childHandler1 = 'childHandler'/>

				</div>
			`,
			methods:{
				childHandler(val){
					console.log(val);
				}
			}
		});
		// 1.声子
		var App = {
			template:`
				<div>
					<Parent />
				</div>
			`
			
		};
		
		new  Vue({
			el:'#app',
			data(){
				return {

				}
			},
			components:{
				// 2.挂子
				App
			},
			// 3.用子
			template:`<App />`
		});
	</script>
props$emit

父组件向子组件传递数据是通过prop传递的,子组件传递数据给父组件是通过$emit触发事件来做到的。

在下面的例子中,有父组件App和子组件Child。

  1. 父组件传递了message数据给子组件,并且通过v-on绑定了一个getChildData事件来监听子组件的触发事件;
  2. 子组件通过props得到相关的message数据,最后通过this.$emit触发了getChildData事件。
	<div id="app"></div>
	<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
	<script type="text/javascript">
		Vue.component('Child',{
			data(){
				return {
					aaa:this.message
				}
			},
			template:`
				<div>
					<input type="text"  v-model="aaa" @input="passData(aaa)"/>
				</div>
			`,
			props:['message'],
			methods:{
				passData(val){
					this.$emit('getChildData',val);
				}
			}
		});
		var App = {
			data(){
				return {
					msg:'我是父组件的内容'
				}
			},
			methods:{
				getChildData(val){
					console.log(`我是子组件传进来的${val}`);
				}
			},
			template:`<div>
				<p>这是一个父组件</p>
				<Child :message = 'msg' @getChildData = "getChildData"></Child>

			</div>`
		}

		new Vue({
			el:"#app",
			data(){
				return {

				}
			},
			components:{
				App
			},
			template:`<App />`
		});
                
	</script>
$attrs$listeners

第一种方式处理父子组件之间的数据传输有一个问题: 如果父组件A下面有子组件B, 组件B下面有组件C, 这时如果组件A想传递数据给组件C怎么办呢?
如果采用第一种方法, 我们必须让组件A通过prop传递消息给组件B, 组件B在通过prop传递消息给组件C; 要是组件A和组件C之间有更多的组件, 那采用这种方式就很复杂了。 Vue 2.4 开始提供了$attrs$listeners来解决这个问题, 能够让组件A之间传递消息给组件C。

<div id="app"></div>
   <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
   <script type="text/javascript">
  
     Vue.component('C', {
       data() {
           return {

           }
       },
       template: `
   			<div>
   				<div @click = 'cClickHandler'>{{$attrs.messagec}}</div>
   			</div>
   		`,
       methods: {
          cClickHandler(){
          	alert(1);
          	this.$emit('getCData','我是c的数据')
          }
       }
   });
     Vue.component('B', {
       data() {
           return {

           }
       },
       template: `
   			<div>
   				<C v-bind="$attrs" v-on = '$listeners'></C>
   			</div>
   		`,
       methods: {
          
       }
   });

   Vue.component('A', {
       data() {
           return {

           }
       },
       // props:['message'],
       template: `
   			<div>
   				<B v-bind="$attrs" v-on = '$listeners'></B>
   				<!--<input type="text" v-model = '$attrs.messagec' />-->
   			</div>
   		`,
       methods: {
          
       }
   });
   var App = {
       data() {
           return {
               msg: '我是父组件的内容',
               messagec:'hello c'
           }
       },
       methods: {
         
       },
       template: `<div>
   			<p>这是一个父组件</p>
   			<A :messagec = 'messagec' v-on:getCData="getCData" ></A>

   		</div>`,
   methods:{
   	// 执行c组件的触发的函数
   	getCData(val){
   		console.log(val);
   	}
   }
   };

   new Vue({
       el: "#app",
       data() {
           return {

           }
       },
       components: {
           App
       },
       template: `<App />`
   });
   </script>
</body>

上面两种方式处理的都是父子组件之间的数据传递,而如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。

 <div id="app"></div>
   <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
   <script type="text/javascript">
   
     // 中央事件总线
     var bus = new Vue();
  
     Vue.component('brother2', {
       data() {
           return {
               msg:"hello brother1"
           }
       },
       template: `
   			<div>
                                             <p>我是老大</p>
   				<input type="text" v-model = 'msg' @input = 'passData(msg)' />
   			</div>
   		`,
       methods: {
          passData(val){
           // //触发全局事件globalEvent
           bus.$emit('globalEvent',val)
          }
       }
   });

   Vue.component('brother1', {
       data() {
           return {
               msg:"hello brother1",
               brother2Msg:''
           }
       },
       template: `
   			<div>
   				<p>我是老二</p>
   				<p>老大传递过来的数据:{{brother2Msg}}</p>
   			</div>
   		`,
       
          mounted(){
               // 绑定全局事件globalEvent事件,
              bus.$on('globalEvent',(val)=>{
                   bus.brother2Msg = val;
              })
          }
   });
   var App = {
       data() {
           return {
               msg: '我是父组件的内容',
               messagec:'hello c'
           }
       },
       methods: {
         
       },
       template: `<div>
   			<brother1></brother1>
                 <brother2></brother2>


   		</div>`,
   methods:{
   	// 执行c组件的触发的函数
   	getCData(val){
   		console.log(val);
   	}
   }
   }

   new Vue({
       el: "#app",
       data() {
           return {

           }
       },
       components: {
           App
       },
       template: `<App />`
   });
   </script>

父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。

  <div id="app"></div>
   <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
   <script type="text/javascript">
   	Vue.component('Child',{
   		data(){
   			return {
   				msg:''
   			}
   		},
   		template:`
   		<div>我是孩子{{msg}}</div>
   		`,
   		 inject:['for'],
   		 created(){
   		 	this.msg = this.for;
   		 }
   	});

   	Vue.component('Parent',{
   		template:`
   		<div>
   			<p>我是父亲</p>
   			<Child />
   		</div>
   		
   		`
   		
   	});
   	var App = {
   		data(){
   			return {

   			}
   		},
   		provide:{
   			for:'他爹'
   		},
   		template:`
   		<div>
   			<h2>我是入口组件</h2>
   			<Parent />
   		</div>
   		`
   	}

   	new Vue({
   		el:"#app",
   		template:`<App />`,
   		data(){
   			return {

   			}
   		},
   		components:{
   			App
   		}
   	});
   </script>
    <div id="app"></div>
    <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
    <script type="text/javascript">
    	Vue.component('Child',{
    		data(){
    			return {
    				msg:''
    			}
    		},
                  props:{
                    value:String, //v-model会自动传递一个字段为value的prop属性
                 },
                  methods:{
                    changeValue(){
                        alert(1);
                        this.$emit('input',this.value);通过如此调用可以改变父组件上v-model绑定的值
                    }
                  },
    		template:`
			<div>
                                <input type="text" v-model = 'value'  @change = 'changeValue'/>
                            </div>
    		`
    	});

    	Vue.component('Parent',{
                  data(){
                    return {
                        msg:'我是父组件的数据'
                    }
                  },
    		template:`
			<div>
				<p>我是父亲</p>
				<Child v-model ='msg' @input = 'input'/>
			</div>
			
    		`,
                methods:{
                    input(val){
                        console.log(val);
                    }
                }
    		
    	});
    	var App = {
    		data(){
    			return {

    			}
    		},
    		template:`
			<div>
				<h2>我是入口组件</h2>
				<Parent />
			</div>
    		`
    	}

    	new Vue({
    		el:"#app",
    		template:`<App />`,
    		data(){
    			return {

    			}
    		},
    		components:{
    			App
    		}
    	});
    </script>
    <div id="app"></div>
    <script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
    <script type="text/javascript">
    
    Vue.component('Child', {
                props: {
                    value: String, //v-model会自动传递一个字段为value的prop属性
                },
                data() {
                    return {
                        mymessage: this.value
                    }
                },
                methods: {
                    changeValue() {
                        console.log(this.mymessage);
                        this.$parent.message = this.mymessage; //通过如此调用可以改变父组件的值
                        console.log(this.$parent);
                    }
                },
                template: `
            <div>
                <input type="text" v-model="mymessage" @change="changeValue"> 
            </div>
            `
    })
    Vue.component('Parent',{
        template:` <div >
                    <p>我是父亲组件{{message}}</p>
                    <button @click = "changeChildValue" > test < /button > 
                    <Child ></Child> 
                    </div>
                `,
        methods:{
            changeChildValue(){
                this.$children[0].mymessage = 'hello';
            }
        },

        data(){
            return {
                message:'hello'
            }
        }
    })
    var App = {
            data(){
                return {

                }
            },
            template:`
            <div>
                <h2>我是入口组件</h2>
                <Parent />
            </div>
            `
        }

   var vm = new Vue({
        el:'#app',
        components:{
            App
        },
        template:`
            <App></App>
                `
    })
   console.log(vm);

    </script>
具名插槽
	<div id = 'app'></div>
	<script type="text/javascript" src="./vue.min.js"></script>
	<script type="text/javascript">
		Vue.component('myLi',{
			template:`

				<li>
					预留的第一个坑
					<slot name = 'two'></slot>

					预留的第二坑
					<slot name = 'three'></slot>	

				</li>
			`
		});
		
		var App = {
			template:`
				<div>
					<ul>
						<myLi>
							<h2 slot='two'>我是第一个坑</h2>
							<h3 slot= 'three'>我是第二个坑</h3>
							
						</myLi>
					  
					</ul>

				</div>
			`
		}
		new Vue({

			el:"#app",
			components:{
				App
			},
			template:`<App />`
		});
	</script>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dev _

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值