父子组件间的通信(在这里父组件就是你自定义的标签,子组件就是父组件template里面的内容),父组件通过props选项向子组件传递参数或数据,子组件接收到参数后根据参数的不同来执行不同的操作。也就是说,在组件中使用props选项来声明需要从父组件接受的数据(通俗点说就是,组件在注册的时候通过props选项声明子组件(template所指)需要从父组件中接受的数据),props选项的值可以是字符串数组或者对象:
值是字符串数组:
HTML部分:
JS部分:
Vue.component("my-component",{
props:["message","array"],
// 子组件
template:"{{message}}{{message}}",
})
注意:
HTML部分:
JS部分:
Vue.component("my-component",{
props:["message","array"],
// 子组件
template:"{{message}}{{message}}",
data:function(){
return {
tips:"我来自data选项"
}
}
})
var myApp = new Vue({
el:"#container",
data:{
msg:"来自父组件上的数据",
dataArray:[1,2,3,4],
initMsg:"初始化数据"
}
})
2.同一个组件在复用的时候是相互独立的
通过上例我们可以发现,无论是组件中data函数的返回值还是从父组件中传递过来的数据,子组件都能操作,那么他们之间有何区别呢:
我个人感觉主要是作用域:props声明的数据可能来自于Vue实例中的data选项,而data函数返回值,其作用域仅仅在于组件内部,是自己的私有数据。因此可以在data函数中将props数据作为返回值保存起来,这样以后你就可以随意操纵数据了,也就避免了直接操纵父组件数据,从而影响父组件。
其实在Vue2.x中,通过props传递数据是单向的,也就是说,当父组件数据的变化会引起子组件数据的变化,但是反之不行,这也意味着,其实在子组件中无论你怎么操作从props传递过来的数据,父组件的状态都不会改变
为了验证这个想法,看下面的例子
HTML部分:
{{initMsg}}
JS部分:
Vue.component("our-component",{
props:["mero"],
template:"{{mero}}",
methods:{
changeMSG:function(){
alert(1)//this表示当前的组件our-component(可以视组件的地位和Vue实例的地位差不多)
this.mero = "我被改变啦!"
}
}
})
var myApp = new Vue({
el:"#container",
data:{
msg:"来自父组件上的数据",
dataArray:[1,2,3,4],
initMsg:"初始化数据"
}
})
结果:
初始化的时候是这样的:
当触发点击事件的时候,变成了这样:
可以看到,span元素内的值一直都没有变化,也就说明实例中的initMsg没有发生改变,由于v-bind是双向绑定的,所以父组件中对应的属性没有发生改变(虽然我们看不到),但即使是这样也要注意:为了安全起见,从父组件中传递过来的数据,要在组件的data选项中将其保存起来,或者利用计算属性
说完了父组件向子组件传递数据,那么子组件要向父组件传递数据该怎么办?其实子组件向父组件通信通过$emit()实现;
大意为子组件使用了一个事件,比如click然后产生了一个效果(组件中methods选项中的函数做的事),然后将这样的效果命名放入父组件(this.$emit(自定义事件名,[参数1]),[参数2]……),注意事件名要小写字母,不要用驼峰命名法)中,当做一个事件来触发,每当这样的效果发生一次时,这样父组件的事件也被触发了(v-on给父组件绑定以上自定义事件),即可以产生另一种效果(一般操作的是Vue实例中的数据,随意操作,可以传参参数子组件中的数据,也可以不传),这样可以加强这两个效果的紧密联系,并且这样有趣又好用的方式也可以用在自己想要的地方。这样当绑定在子组件上的事件触发的时候,父组件上的事件也会触发并执行一系列方法。
例如:
HTML部分
当前的值是:{{total}}
@decreasefunc="changeTotal"
>
JS部分:
// 自定义组件;
Vue.component("my-component",{
template:"\
\
\
\
",
data:function(){
return{
counter:0
}
},
methods:{
increaseTotal:function(){
this.counter++;
console.log(this.counter)
// 同下
this.$emit("increasefunc",this.counter);
},
decreaseTotal:function(){
this.counter--;
console.log(this.counter);
// 定义自定义事件名,第一个参数是事件名,第二个参数及以后是要传递的数据
// 也可以不传递参数,事件名自定义
this.$emit("decreasefunc",this.counter)
}
}
})
var myApp = new Vue({
el:"#container",
data:{
total:0
},
methods:{
changeTotal:function(total){
// 形参total用来保存从子组件传递过来的数据的,也可以不传参,
this.total++;
}
}
})
以上当点击绑定在子组件上的click事件的时候,就会通过this.$emit()方法“告诉”父组件:子组件点击了(事件被触发了),那么此时绑定在父组件上的对应的自定义事件也会触发,并执行相应的函数changeTotal函数,实现了子组件和父组件事件的单向紧耦合