父子组件
在一个组件内定义另一个组件,称之为父子组件。
但是要注意的是:1.子组件只能在父组件内部使用(写在父组件tempalte中);
2.默认情况下,子组件无法访问父组件上的数据,每个组件实例的作用域是独立的;
例如:
JS部分
var compo1 = new Vue({
el:"#container1",
data:{
goods:"洗衣液",
car:"Benzi"
},
components:{
"your-compo":{//父组件,在这里"your-compo"只是组件id
template:"#aps",
data:function(){
return {
food:"面条"
}
},
components:{
"yourson-compo":{//子组件,同上
template:"#apsSon",
data:function(){
//some codes
}
}
}
}
}
})
HTMl部分
<div id="container1">
<your-compo></your-compo>//父组件
</div>
<!-- 父组件模板 -->
<template id="aps">
<div>
<h3>{{food}}</h3>
<yourson-compo></yourson-compo>//在父组件中嵌入子组件
</div>
</template>
<!-- 子组件模板 -->
<template id="apsSon">
<div>
<h1>我是模拟出来的第二个子组件</h1>
</div>
</template>
子组件只能在父组件内部使用,这里的内部指的是父组件模板template内部,也就是说要写在父组件template中,
默认情况下,组件之间的作用域是独立的。组件间的数据通信:
但是即便是这样,组件之间还是要实现通信的,那么父子组件间是怎么通信的呢?Vue有着自己的一套解决方案:
1.子组件访问父组件的数据
a)将父组件的数据通过v-bind绑定到子组件的自定义属性上;
b)在子组件内部,通过props选项声明你要接收的数据,也就是接收来自父组件上的数据(props选项可以是对象或者数组);
i:如果props选项是数组,里面就是由那些自定义属性组成的字符串数组;
ii:如果props选项是对象,那么此时可以配置高级的设置,如类型判断,数据校验,设置默认值,是否必传等,具体见官网上的例子所示;
JS部分
var app = new Vue({ //根组件
el: "#container",
data: {
name: "张三"
},
components: {
"my-comp": { //父组件
template: "#fatherComp",
data: function() {
return {
greeting: "我是父组件my-comp",
user: {
id: "9527",
name: "唐伯虎"
},
car: "Benzi",
animal: "",
plant: ""
}
},
components: {
"my-compson": { //子组件一
template: "#sonComp",
data: function() {
return {
animal: {
classes: "Dog",
height: 120
},
plant: "玫瑰花"
}
},
props: ["greeting", "user", "car"] //子组件通过props来接收数据,props可以是数组,也可以是对象
}
}
}
}
})
如果这里的props是个对象,那么就如下这样
"my-compson1": {
template: "#sonComp1",
props: { //props也可以是对象
greeting: Number, //规定greeting必须是数值类型,
user: {
type: Object, //
default: function() { //对象或者数组的默认值必须使用函数的形式来返回,
return {
id: "9900",
name: "如花"
}
}
},
car: {
type: String,
default: "BMW", //当没有传,但却必须要使用自定义属性car的时候,显示default值
required: true //在组件的自定义属性中必传car属性,由于此时没有传,所以显示默认值
}
}
}
HTML部分
<div id="container" v-cloak>
<my-comp></my-comp>
</div>
<div id></div>
<!-- 父组件引用模板 -->
<template id="fatherComp">
<div>
<h3>{{greeting}}</h3>
<h3>{{user.id}}{{user.name}}</h3>
<hr>
<!-- 父组件通过v-bind将数据绑定到子组件 -->
<my-compson :greeting="greeting" :user = "user" :car = "car" @sondata ="getData"></my-compson>
</div>
</template>
<!-- 子组件一引用模板 -->
<template id="sonComp">
<div>
<h5>{{greeting}},{{user.id}},{{user.name}},{{car}}</h5>
<!-- 子组件自带的数据 -->
<h1>{{animal.height}}</h1>
</div>
</template>
总结:父组件向子组件传递数据是通过v-bind将父组件数据绑定到子组件上,子组件内部通过props选项来接收数据
注:组件的数据来源data,props,计算属性
2.父组件访问子组件中的数据
a)在子组件中使用vm.$emit("自定义事件名","子组件数据一","子组件数据二",...)方法(在这里vm指的是当前子组件本身),来扔出一个自定义事件和数据,事件名自定义;
b)在父组件中使用(写有)子组件的地方侦听子组件扔出来的事件名(一旦侦听到,就会触发相应的函数),并在父组件中定义一个函数用来获取并保存数据;例如:
JS部分
var app = new Vue({ //根组件
el: "#container",
data: {
name: "张三"
},
components: {
"my-comp": { //父组件
template: "#fatherComp",
data: function() {
return {
greeting: "我是父组件my-comp",
user: {
id: "9527",
name: "唐伯虎"
},
car: "Benzi",
animal: "",
plant: ""
}
},
methods: { //在父组件中定义一个函数用来保存子组件发送过来的数据
getData: function(ele1, ele2) {
this.animal = ele1; //第一个参数就代表传递过来的第一个子组件数据
this.plant = ele2 //同理,以此类推
}
},
components: {
"my-compson": { //子组件一
template: "#sonComp",
data: function() {
return {
animal: {
classes: "Dog",
height: 120
},
plant: "玫瑰花"
}
},
methods: {
emitData: function() {
//这里的this指的是当前子组件实例
this.$emit("sondata", this.animal, this.plant) //扔出一个自定义事件sondata和子组件的数据,多个数据用","号隔开
}
}
}
}
}
}
})
HTML部分
<div id="container" v-cloak>
<my-comp></my-comp>
</div>
<div id></div>
<!-- 父组件引用模板 -->
<template id="fatherComp">
<div>
<!-- 刚开始animal和plant都是空值,当点击子组件的按钮的时候就会拿到子组件上的数据并进行展示-->
<h1>{{animal}},{{plant}}</h1>
<hr>
<!-- 父组件在使用子组件的地方侦听子组件扔出来的事件名,这里是sondata,并执行了保存数据的函数 -->
<my-compson :greeting="greeting" :user = "user" :car = "car" @sondata ="getData"></my-compson>
</div>
</template>
<!-- 子组件一引用模板 -->
<template id="sonComp">
<div>
<h5>{{greeting}},{{user.id}},{{user.name}},{{car}}</h5>
<!-- 子组件自带的数据 -->
<h1>{{animal.height}}</h1>
<button type="button" @click = "emitData">扔出来一个自定义事件和子组件的数据</button>
</div>
</template>
总结:子组件通过一个事件(如click等)给父组件发送消息:"我扔出来一个自定义事件和一些数据",父组件侦听到自定义事件,并执行在该自定义事件下的函数来接收并保存数据