在日常开发中,我们经常会在一个组件中嵌套另外一个组件,那么如果我们父组件要向子组件传值该怎么办?子组件向父组件通信又该怎么办?本文将详细举例说明这些问题。

父向子通信

问题描述

现在我们有个需求,我们要分别显示父和子的信息,我们当然可以在一个组件中直接显示全部信息,但是万一以后又来一个需求:我们要在母和子的信息,那其实这里就存在冗余了,所以我们把子组件单独封装成一个新的组件。那么这里就会出现一个问题,子组件的信息该如何从父组件传过去呢?

解决方案

使用vue提供的prop属性,下面边看代码边分析:
父组件定义

<template><div class="father">这里是父组件,我们会在这里展示父的信息{{ fatherName }}{{ fatherAge }}<son/></div>
</template><script>import son from "@/components/son";export default {name: "father",components: {son},data() {return {fatherName: "张三",fatherAge: 12}}}
</script>
<style lang="css">.father{border: 1px solid black;}
</style>

子组件定义

<template><div class="son">这里是子组件,我们会在这里展示子的信息</div>
</template><script>export default {name: "son"}
</script><style scoped>.son{margin: 10px;border: 1px solid red;}
</style>

使用:attribute属性向子组件传入值

<template><div class="father">这里是父组件,我们会在这里展示父的信息{{ fatherName }}{{ fatherAge }}<son :sonInfo="sonInfo"/></div>
</template><script>
import son from "@/components/son";export default {name: "father",components: {son},data() {return {fatherName: "张三",fatherAge: 12,sonInfo: {sonName: "王小虎",sonAge: 6}}}
}
</script>
<style lang="css">
.father {border: 1px solid black;
}
</style>

子组件通过props属性接收父组件传过来的值,这里的名字要和父组件传的值对应

<template><div class="son">这里是子组件,我们会在这里展示子的信息{{ sonInfo.sonName }}{{ sonInfo.sonAge }}</div>
</template><script>
export default {name: "son",props: ["sonInfo"]
}
</script><style scoped>
.son {margin: 10px;border: 1px solid red;
}
</style>

测试

扩展

上述的例子解决了父子组件传值的基本问题,当然prop的用法还有很多,我们可以在vue2官网上看到

Prop的大小写

camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名

Vue.component('blog-post', {// 在 JavaScript 中是 camelCase 的props: ['postTitle'],template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

Prop 类型

我们之前使用以字符串数组形式列出的 prop

 props: ["sonInfo"]

我们也可以给每一个prop指定对应的值

props: {title: String,//字符串likes: Number,//数字isPublished: Boolean,//布尔commentIds: Array,//数组author: Object,//对象callback: Function,//函数contactsPromise: Promise //异步延迟对象
}

传递静态或动态 Prop

之前我们传递的是动态的Prop,可以动态赋值

 <son :sonInfo="sonInfo"/>

我们也可以传递静态的

<son :sonInfo="sonInfo" sex="1"/>
  props: ["sonInfo", "sex"]

单向数据流

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

官方这段话表明了,我们对于父组件传过来的值最不要直接修改,官方例举了两个常用的变更案例
1.这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用

props: ['initialCounter'],
data: function () {return {counter: this.initialCounter}
}

2.这个 prop 以一种原始的值传入且需要进行转换

props: ['size'],
computed: {normalizedSize: function () {return this.size.trim().toLowerCase()}
}

类型校验

之前我们使用字符串数组形式列出的 prop,父组件不知道子组件prop值的类型,可能传值的时候传错,所以我们可以给值指定类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你

Vue.component('my-component', {props: {// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)propA: Number,// 多个可能的类型propB: [String, Number],// 必填的字符串propC: {type: String,required: true},// 带有默认值的数字propD: {type: Number,default: 100},// 带有默认值的对象propE: {type: Object,// 对象或数组默认值必须从一个工厂函数获取default: function () {return { message: 'hello' }}},// 自定义验证函数propF: {validator: function (value) {// 这个值必须匹配下列字符串中的一个return ['success', 'warning', 'danger'].includes(value)}}}
})

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告

子向父通信

问题描述

既然父可以向子传值,那么子是否可以通信父呢?当然可以,这时候我们要借助vue的emit和emit和emit和on,下面我们看代码:

解决方案

子组件

<template><div class="son">这里是子组件<button @click="emit">使用emit向父组件通信</button></div>
</template><script>
export default {name: "son",methods:{emit(){this.$emit('sayHi',"tom")}}
}
</script><style scoped>
.son {margin: 10px;border: 1px solid red;
}
</style>

父组件

<template><div class="father">这里是父组件<son sex="1" @sayHi="sayHi"/></div>
</template><script>
import son from "@/components/son";export default {name: "father",components: {son},data() {return {}}, methods: {sayHi(name) {console.log("sayHi:"+name)}}
}
</script>
<style lang="css">
.father {border: 1px solid black;
}
</style>

测试
点击按钮,控制台输出sayHi tom

分析

这里首先介绍一下vue提供的两个重要函数emit和on

on

监听当前实例上的自定义事件。事件可以由 $emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
上述例子的 @sayHi="sayHi"就是在监听sayHi事件,这里采用了简写形式,完整形式是v-on:sayHi=“sayHi”,我们平时用的比较多的就是监听点击事件,而这里我们就是监听了我们自定义的事件

emit

触发当前实例上的事件。附加参数都会传给监听器回调。
当我们监听了自定义事件,我们就可以在子组件中触发事件,this.$emit(‘sayHi’,“tom”),这样就会调用监听的回调函数,并且将附加参数tom传入回调函数

非父子通信

除了上述的父子组件通信,我们最后还可以在非父子组件之间传值,某些场景下会用到。下面看代码:
事件总线

import Vue from "vue";
export default new Vue;

组件B

<template><div>组件B{{ value }}</div>
</template><script>
import bus from "@/components/bus";export default {name: "ComponentB",data() {return {value: "oldVal"}}, created() {bus.$on("changeVal", newVal => {this.value = "newVal"})}
}
</script><style scoped></style>

组件A

<template><div>组件A<button @click="communicate">组件A->组件B</button></div>
</template><script>
import bus from "@/components/bus";
export default {name: "ComponentA",methods:{communicate(){bus.$emit("changeVal","newVal")}}
}
</script><style scoped></style>

测试
组件B的值由oldVal->newVal

分析

这里引入了事件总线(event bus)的概念,事件总线:事件发送者将事件消息发送到一个事件总线上,事件订阅者向事件总线订阅和接收事件,然后再处理接收到的事件
而我们这里的事件总线的载体就是一个Vue的实例对象,因为在emit和on都是Vue的一个实例方法。
当然我们还可以使用$attrs / listeners来实现类似效果,这里就不多做介绍了,有兴趣的读者可以自行了解
但是如果学过Vuex的话,利用Vuex来传值会很方便,Vuex之后会慢慢讲,不急。学习是个漫长的过程,慢慢来

由于作者能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!

Vue2-父子组件传值相关推荐

  1. vue2父子组件传值

    1.父传子 父传子:主要是在父组件引入子组件,将要传值的值绑定指定的属性上如 然后在子组件用props接收即可在页面展示 1.父组件 <template><div class=&qu ...

  2. Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值

    Vue2.0 传值方式: 在Vue的框架开发的项目过程中,经常会用到组件来管理不同的功能,有一些公共的组件会被提取出来.这时必然会产生一些疑问和需求?比如一个组件调用另一个组件作为自己的子组件,那么我 ...

  3. Vue3中父子组件传值

    vue3父子组件传值其实和vue2写法差不多 父传子 Props,子传父 emit 父组件代码 <template><div><child :msg="msg& ...

  4. vue中父子组件先后渲染_vue父子组件传值(子传父,非父子组件传值)

    1. 子组件向父组件传值 子组件: <template><div>子组件:<span>{{childValue}}</span><!-- 定义一个 ...

  5. 在基于nuxt的移动端页面中引用mint UI的popup组件之父子组件传值

    最近在做移动端的wap页面,考虑到要做SEO,所以选定了nuxt+vue+mint ui. 有一个需求是这样的,点击头部菜单栏,出现一个气泡,点击返回首页. 由于一些页面没有统一引用mint的mt-h ...

  6. 父子组建传值_浅谈Vue父子组件和非父子组件传值问题

    本文介绍了浅谈Vue父子组件和非父子组件传值问题,分享给大家,具体如下: 1.如何创建组件 1.新建一个组件,如:在goods文件夹下新建goodsList.vue goodsList组件 expor ...

  7. Vue 进阶组件实战应用 -- 父子组件传值的应用实例(子父组件传值的两种触发方式)

    基础的子组件和父组件通信已经搞定了,可以看此博客 父子组件传值基础应用 需求 现在需求是在一个父页面引用子组件,不只是要实现基本的父子组件传值.并且子组件给父组件传值的触发条件要在父页面触发. 目前小 ...

  8. 实战 | Element UI 父子组件传值与事件绑定(逆向)

    这是小小本周的第四篇,本篇将会倒过来讲解Element UI 父子组件传值与事件绑定. 父子组件传值 新建父组件和子组件 新建父组件 代码如下 <template><div id=& ...

  9. 实战 | Element UI 父子组件传值与事件绑定(正向)

    这是小小的本周的第三篇,本篇将会讲解关于Element UI 父子组件传值与事件绑定. 父子组件传值 新建父组件和子组件 新建父组件 代码如下 <template><div id=& ...

  10. ionic 父子组件传值

    ionic 父子组件传值 一.父组件==>子组件传值 父组件ts public parentVal="我是父组件的值"; 父组件html <child [parentV ...

最新文章

  1. LigerUI——天外飞仙
  2. python连接oracle批量写入_oracle大数据量python导入实践-1w/s
  3. setTimeOut函数和setInterval函数
  4. 并查集(disjoint set)的实现及应用
  5. java基础之冒泡排序
  6. Linux sqlplus权限不足,sqlplus登录用户提示权限不足
  7. 让 .Net 更方便的导入导出 Excel
  8. 高通的快充协议_高通:后续骁龙旗舰将标配100W快充
  9. 如何固定最小宽度_如何使用更新的HTML和CSS函数创建响应式设计
  10. ul 原点显示_web前端开发学习教程,CSS HTML - ul li列表原点如何相连
  11. -bash: composer: command not found解决办法
  12. 99%学习前端开发都会遇到的问题,百分之百都没绝对意识
  13. 软件测试中一个BUG的生命周期
  14. c++ 工厂模式_Java面试专题之五:设计模式学习,详细分析工厂方法模式
  15. GO程序设计语言学习笔记
  16. 华为防火墙IPSec详解与配置实验
  17. 分享一个AUTO uninstaller|AUTOCAD 安装失败解决方案
  18. Python:Python语言的简介(语言特点/pyc介绍/Python版本语言兼容问题(python2 VS Python3))、安装、学习路线(数据分析/机器学习/网页爬等编程案例分析)之详细攻略
  19. LifeSmart云起局域网直接控制向往背景音乐
  20. 基于Stanford Parser 及OpenNLP Shallow Parser构建句子语法解析树

热门文章

  1. 【无标题】vuex 是什么,vuex中五大核心及作用?
  2. Centos卸载安装rpm
  3. 移动机器人里程计校准的方法
  4. imu 里程计融合_轮式里程计(Wheel Odometry)以及惯性导航(IMU)数据
  5. 又到520了,来画一朵抽搐的玫瑰花吧
  6. 反距离权重插值(IDW)的python实现
  7. Java与或非逻辑符号
  8. 2022年最新Java后端开发技术架构总结
  9. flash无法找到类接口和图片失真问题。
  10. Android动画之前先闪一下,开机动画(闪动的ANDROID字样的动画图片)