vue 父子组件通信详解

这是一篇详细讲解 vue 父子组件之间通信的文章,初始学习 vue 的时候,总是搞不清楚几个情况

  • 通过 props 在父子组件传值时,v-bind:data="data",props 接收的到底是哪个?
  • this.$emit 提交的事件名称,v-on:handleChange="handleChange",和父组件监听时候创建的方法名是否一样?到底哪个才是 v-on 应该监听的事件名称?

你是否也有这样的疑惑呢?如果你跟我有一样的疑惑,那么继续往下看吧 ~~

1. 创建一个父组件 Parent.vue,在 data 中添加一个 parentAge

<template>
  <div class="my-parent">
    <h3> 我是父组件 </h3>
    <p> 父组件的年龄是:{parentAge}}</p>
  </div>
</template>

<script>
export
default {
data() {
return {
parentAge:
50
};
}
};
</script>

<style>
.my
-parent {
text
-align: left;
text
-indent: 1em;
width: 1000px;
height: 500px;
border: 1px solid #
555;
}
</style>

 

2. 创建子组件,在 data 中添加一个 childAge

<template>
  <div class="my-child">
    <h3> 我是子组件 </h3>
    <p> 子组件的年龄是:{{childAge}}</p>
  </div>
</template>

<script>
export
default {
data() {
return {
childAge:
27
};
}
};
</script>

<style>
.my
-child {
margin: 20px;
width: 760px;
height: 200px;
border: 1px solid red;
}
</style>

3. 把父子组件关联起来,并通过 v-bind(即简写“:”)将父组件中的 parentAge 值,传递给子组件

v-on 绑定的属性名称 deliverParentAge 与 data 中定义的 parentAge 名称可以不一样
属性 deliverParentAge 通过 v-bind 绑定的,也是子组件中通过 props 接收的,而parentAge 是要传递给子组件的数值,它是一个值
 
<template>
  <div class="my-parent">
    <h3> 我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
    <h3> 我要通过 v-bind( 即简写":") 语法糖绑定一个属性 deliverParentAge,将父组件的值传递到子组件中 </h3>
    <!-- 下面就是我的子组件 -->
    <my-child :deliverParentAge="parentAge"></my-child>

</div>
</template>

<script>
import MyChild
from "./Child"
;
export
default {
components: {MyChild},
data() {
return {
parentAge:
49
};
}
};
</script>

4. 子组件通过 props 属性,在子组件中接收父组件传过来的值

<template>
  <div class="my-child">
    <h5> 我是子组件,我可以通过属性 props 来接收父组件传过来的年龄值是:{{deliverParentAge}}</h5>
  </div>
</template>

<script>
export
default {
data() {
return {
childAge:
27
};
},
props: {
deliverParentAge: Number
}

};
</script>

5. 现在来修改父组件的值(这个不是真的修改而是通过 this.$emit 提交一个事件,将子组件的行为告诉父组件)

<template>
  <div class="my-child">
    <h5> 我是子组件,我可以通过属性 props 来接收父组件传过来的年龄值是:{{deliverParentAge}},这是一个数字类型 </h5>
    <h5> 并且,我要告诉他,他今年生日已经过了,所以他的年龄应该 <button @click="AddAge"> 加 1</button></h5>
    下面我要通过this.$emit 方法提交一个事件 addParentAge,告诉我的父组件,他的实际年龄
  </div>
</template>

<script>
export
default {
data() {
return {
childAge:
27
};
},
props: {
deliverParentAge: Number
},
// 新建一个计算属性,将父组件原来的值加 1
computed: {
parentActualAge() {
return this.deliverParentAge + 1;
}
},
methods: {
AddAge() {
this.$emit("addParentAge", this.parentActualAge);
}
}
};
</script>

6. 父组件通过语法糖 v-on(即简写为“@”)来监听子组件提交的事件addParentAge

this.$emit 提交的事件名称 addParentAge,与方法handleAddParentAge 名称可以不一样
addParentAge 是子组件提交的事件名称,也是父组件通过 v-on 监听的事件名称,而handleAddParentAge 是父组件自定义的方法名称
 
<template>
  <div class="my-parent">
    <h3> 我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
    <h3> 我要通过 v-bind( 即简写":")语法糖绑定一个属性 parentAge,告诉子组件我的年龄值是:{{parentAge}}</h3>
    <!-- 下面就是我的子组件 -->
    <my-child :deliverParentAge="parentAge"
            @addParentAge="handleAddParentAge"></my-child>
    <h3> 通过监听子组件提交的事件 addParentAge,我知道到了自己的实际年龄应该是:{{parentAge+1}},并通过方法 handleAddParentAge,在控制台打印出我的真实年龄 </h3>

</div>
</template>

<script>
import MyChild
from "./Child";
export
default {
components: {MyChild},
data() {
return {
parentAge:
49
};
},
methods: {
handleAddParentAge(actualAge) {
console.log(
"父组件的实际年龄是:", actualAge);
}
}
};
</script>

 

现在来看控制台打印出来的内容

7. 现在将子组件 data 中的值,提交给父组件来看看

<template>
  <div class="my-child">
    <h5> 我是子组件,我可以通过属性 props 来接收父组件传过来的年龄值是:{{deliverParentAge}},这是一个数字类型 </h5>
    <h5> 现在我要告诉父组件,我的年龄是 {{childAge}}, 这样他就可以知道,我们 <button @click="DiffAge"> 相差 </button> 多少岁 </h5>
    <h5> 并且,我要告诉他,他今年生日已经过了,所以他的年龄应该 <button @click="AddAge"> 加 1</button></h5>
    下面我要通过 this.$emit 方法提交一个事件 addParentAge,告诉我的父组件,他的实际年龄
  </div>
</template>

<script>
export
default {
data() {
return {
childAge:
27
};
},
props: {
deliverParentAge: Number
},
computed: {
parentActualAge() {
return this.deliverParentAge + 1;
}
},
methods: {
AddAge() {
this.$emit("addParentAge", this.parentActualAge);
},
DiffAge() {
this.$emit("differAge", this.childAge);
}

}
};
</script>

8. 父组件通过 v-on 监听子组件提交的事件differAge

<template>
  <div class="my-parent">
    <h3> 我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
    <h3> 我要通过 v-bind( 即简写":")语法糖绑定一个属性 parentAge,告诉子组件我的年龄值是:{{parentAge}}</h3>
    <!-- 下面就是我的子组件 -->
    <my-child :deliverParentAge="parentAge"
            @differAge="handleDifferAge"
              @addParentAge="handleAddParentAge"></my-child>
    <h3> 通过监听子组件提交的事件 addParentAge,我知道到了自己的实际年龄应该是:{{parentAge+1}},并通过方法 handleAddParentAge,在控制台打印出我的真实年龄 </h3>
    <h3> 通过监听子组件提交的事件 differAge,并通过方法 handleDifferAge,在控制台打印出子组件的年龄 </h3>

</div>
</template>

<script>
import MyChild
from "./Child";
export
default {
components: {MyChild},
data() {
return {
parentAge:
49
};
},
methods: {
handleAddParentAge(actualAge) {
console.log(
"父组件的实际年龄是:", actualAge);
},
handleDifferAge(child) {
console.log(
"我们的年龄差是:", this.parentAge + 1 - child);
}

}
};
</script>

现在来看看页面展示的效果和控制台打印出来的信息

 

下面贴上完整的代码

// Parent.vue
<template>
  <div class="my-parent">
    <h3> 我是父组件,我想告诉我的子组件,我的年龄值是:{{parentAge}}</h3>
    <h3> 我要通过 v-bind( 即简写":")语法糖绑定一个属性 parentAge,告诉子组件我的年龄值是:{{parentAge}}</h3>
    <!-- 下面就是我的子组件 -->
    <my-child :deliverParentAge="parentAge"
              @differAge="handleDifferAge"
              @addParentAge="handleAddParentAge"></my-child>
    <h3> 通过监听子组件提交的事件 addParentAge,我知道到了自己的实际年龄应该是:{{parentAge+1}},并通过方法 handleAddParentAge,在控制台打印出我的真实年龄 </h3>
    <h3> 通过监听子组件提交的事件 differAge,并通过方法 handleDifferAge,在控制台打印出子组件的年龄 </h3>

</div>
</template>

<script>
import MyChild
from "./Child";
export
default {
components: {MyChild},
data() {
return {
parentAge:
49
};
},
methods: {
handleAddParentAge(actualAge) {
console.log(
"父组件的实际年龄是:", actualAge);
},
handleDifferAge(child) {
console.log(
"我们的年龄差是:", this.parentAge + 1 - child);
}
}
};
</script>

<style lang="stylus" scoped>
.my
-parent {
text
-align: left;
text
-indent: 1em;
width: 1000px;
height: 500px;
border: 1px solid #
555;
}
</style>

// Child.vue
<template>
  <div class="my-child">
    <h5> 我是子组件,我可以通过属性 props 来接收父组件传过来的年龄值是:{{deliverParentAge}},这是一个数字类型 </h5>
    <h5> 现在我要告诉父组件,我的年龄是 {{childAge}}, 这样他就可以知道,我们 <button @click="DiffAge"> 相差 </button> 多少岁 </h5>
    <h5> 并且,我要告诉他,他今年生日已经过了,所以他的年龄应该 <button @click="AddAge"> 加 1</button></h5>
    下面我要通过 this.$emit 方法提交一个事件 addParentAge,告诉我的父组件,他的实际年龄
  </div>
</template>

<script>
export
default {
data() {
return {
childAge:
27
};
},
props: {
deliverParentAge: Number
},
computed: {
parentActualAge() {
return this.deliverParentAge + 1;
}
},
methods: {
AddAge() {
this.$emit("addParentAge", this.parentActualAge);
},
DiffAge() {
this.$emit("differAge", this.childAge);
}
}
};
</script>

<style>
.my
-child {
margin: 20px;
width: 760px;
height: 200px;
border: 1px solid red;
}
</style>

希望对你有用,欢迎提问与指正,一起学习前端呀!