详解vue组件之间的通信


Posted in Javascript onAugust 30, 2020

说明:下面我总结了比较常用的vue组件之前通信的方式,最近准备面试,所以有些总结贴上来分享

props和$emit

只有父子关系才可以用这种方式,父组件向子组件传递参数用props,子向父传递使用触发$emit自定义事件

1.props

<!-- parent.vue, 可以传递`静态`的props和`动态`的props, 静态的参数只能是个String类型的,如果是其他类型的一定要记得加`:`来表示这是一个 js 表达式而不是一个字符串 -->
<Child :name="name" :age="18" address="xxxxx"></Child>
...
data () {
 return {
  name: 'marry'
 }
}

<!-- 传一个参数所有props, 虽然目前我没有这个需求,使用不带参数的 v-bind -->
<blog-post v-bind="post"></blog-post>
post: {
 id: 1,
 title: 'My Journey with Vue'
}
//等价于下面
<blog-post
 v-bind:id="post.id"
 v-bind:title="post.title"
></blog-post>


<!-- child.vue -->
...
//以字符串数组形式列出的 prop
props: ['name', 'age', 'address']

//prop验证, 当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告
//注意:以下类型不能写成'String'这种带引号的形式
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'].indexOf(value) !== -1
  }
 }
}
//注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。

2.$emit

<!-- parent.vue -->
<Child @my-event="myEvent"></Child>
...
methods: {
 myEvent(name){
 this.name = name
 }
}

<!-- child.vue -->
<div>
 <button @click="$emit('my-event', name)"></button>
</div>
//使用自定义事件将子组件的值抛给父组件

中央事件总线 bus

用于解决跨级和兄弟组件通信问题,巧妙的使用一个公共的vue实例,利用$on, $emit, $off(移除自定义事件监听器)

方法一:

可以在main.js中,在Vue的原型上挂载一个公共的Vue实例 $bus,这样全局任何一个地方都可以使用

Vue.prototype.$bus = new Vue()

然后在需要的地方注册自定义事件和接收参数的回调函数

this.$bus.$on('changeName', name => {
 this.name = name
})

在需要改变的时候触发事件并抛出参数

this.$bus.$emit('changeName', 'wzj')

方法二:

定义一个util.js文件

import Vue from 'vue'

const bus = new Vue()
export default bus

在需要用到bus的文件中引入

import bus from '../util' //文件路径不一定

//在一个文件定义事件
bus.$on('changeName', name => {
 this.name = name
})

//另一个文件抛出参数
bus.$emit('changeName', 'wzj')

vuex

对于项目比较复杂,多组件共享状态,不同层级需要通信

详解vue组件之间的通信

核心概念:

state, getter, mutation, action, module

//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export dafault new Vuex.Store({
 state: {
 name: '',
 age: 0
 },
 getters: {
 tranName(state){
  return 'name: ' + state.name
 }
 },
 mutations: {
 changeName(state, name){
  state.name = name
 }
 },
 /*Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters */
 actions: { //异步函数,但还是要通过提交commit触发mutations函数操作state
 changeName(context, name){
  context.commit('changeName', name)
 }
 },
 modules: {}
})

在组件中使用

方法一:

//访问state属性
this.$store.state.name
//访问getters属性
this.$store.getters.tranName
//访问mutations
this.$store.commit('changeName', 'wzj')
//访问actions
this.$store.dispatch('changeName', 'wzj')

方法二:使用辅助函数映射到本地,这里只列举了简便的方式,更多查阅官网吧

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
//state 和 getters 映射到本地的computed属性中,作为计算属性使用
computed: {
 ...mapState(['name', 'age']),
 ...mapGetters(['tranName'])
}

//mutations 和 actions
methods: {
 // 将 `this.changeName()` 映射为 `this.$store.commit('changeName')`
 ...mapMutations(['changeName']) 
 // 将 `this.changeName()` 映射为 `this.$store.dispatch('changeName')`
 ...mapActions(['changeName'])
}

$attrs 和 $listeners

父组件与后代组件,用以上方法有点大材小用或者第一种有些不方便

  • $attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 ( class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。
  • $listeners 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

例子:

//app.vue
<div>
 <One name="wzj" :age="age" address="xian" @changeAge="changeAge"></One>
</div>
...
data(){
 return {
 age: 10
 }
},
methods: {
 changeAge(age){
 this.age = age
 }
}

//one.vue
<div>
 <div>姓名:{{ name }}</div>
 <div>年龄:{{ age }}</div>
 <Two v-bind="$attrs" v-on="$listeners"></Two>
 <button @click="change">点我2</button>
</div>
...
props: ['name', 'age'],

//two.vue
<div>
 <div>{{ address }}</div>
 <button @click="change">点我2</button>
</div>
...
props: ['address'], //用$attrs传递到最后的属性,在使用的时候还是要声明props
methods: {
 change(){
 this.$emit('changeAge', 30)
 }
}

理解:其实祖先组件的属性和事件还是一层层往下传,不过用$attrs 和 $listeners优化和简便了传递过程中书写,而且在传递的过程中,任何一个声明了 $listeners的组件都可以触发里面的所有事件,而声明了$attrs的组件只能使用之前未用props声明的剩下的属性。

以上就是vue组件之间的通信的详细内容,更多关于vue 组件通信的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
获取页面高度,窗口高度,滚动条高度等参数值getPageSize,getPageScroll
Sep 22 Javascript
javascript实现的基于金山词霸网络翻译的代码
Jan 15 Javascript
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
Nov 30 Javascript
JS解析json数据并将json字符串转化为数组的实现方法
Dec 25 Javascript
JavaScript原型链示例分享
Jan 26 Javascript
jQuery中parents()和parent()的区别分析
Oct 28 Javascript
Javascript 拖拽雏形(逐行分析代码,让你轻松了拖拽的原理)
Jan 23 Javascript
浅谈jQuery hover(over, out)事件函数
Dec 03 Javascript
JavaScript 日期时间选择器一些小结
Apr 02 Javascript
微信小程序实现录音功能
Nov 22 Javascript
Python版实现微信公众号扫码登陆
May 28 Javascript
JS异步宏队列微队列原理详解
Sep 09 Javascript
如何阻止移动端浏览器点击图片浏览
Aug 29 #Javascript
JavaScript事件委托实现原理及优点进行
Aug 29 #Javascript
JS如何判断对象是否包含某个属性
Aug 29 #Javascript
JS获取当前时间戳方法解析
Aug 29 #Javascript
JS PHP字符串截取函数实现原理解析
Aug 29 #Javascript
JS访问对象两种方式区别解析
Aug 29 #Javascript
js在HTML的三种引用方式详解
Aug 29 #Javascript
You might like
8个必备的PHP功能实例代码
2013/10/27 PHP
PHP中soap的用法实例
2014/10/24 PHP
利用Fix Rss Feeds插件修复WordPress的Feed显示错误
2015/12/19 PHP
Aster vs KG BO3 第二场2.18
2021/03/10 DOTA
保证JavaScript和Asp、Php等后端程序间传值编码统一
2009/04/17 Javascript
jQuery函数的等价原生函数代码示例
2013/05/27 Javascript
JQuery设置文本框和密码框得到焦点时的样式
2013/08/30 Javascript
jquery ajax跨域解决方法(json方式)
2014/02/04 Javascript
JS实现简单的顶部定时关闭层效果
2014/06/15 Javascript
让人蛋疼的JavaScript语法特性
2014/09/30 Javascript
javascript 数组的定义和数组的长度
2016/06/07 Javascript
功能强大的Bootstrap组件(结合js)
2016/08/03 Javascript
Angular父子组件通过服务传参的示例方法
2018/10/31 Javascript
ES10 特性的完整指南小结
2019/03/04 Javascript
Element实现表格分页数据选择+全选所有完善批量操作
2019/06/07 Javascript
详解Vue2.5+迁移至Typescript指南
2019/08/01 Javascript
详解vue-router 动态路由下子页面多页共活的解决方案
2019/12/22 Javascript
Vue按时间段查询数据组件使用详解
2020/08/21 Javascript
在vue中通过render函数给子组件设置ref操作
2020/11/17 Vue.js
JavaScript点击按钮生成4位随机验证码
2021/01/28 Javascript
[01:02:05]LGD vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Win7上搭建Cocos2d-x 3.1.1开发环境
2014/07/03 Python
Python方法的延迟加载的示例代码
2017/12/18 Python
python+matplotlib实现动态绘制图片实例代码(交互式绘图)
2018/01/20 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
Python获取网段内ping通IP的方法
2019/01/31 Python
Python实现结构体代码实例
2020/02/10 Python
python3通过qq邮箱发送邮件以及附件
2020/05/20 Python
泰国国际航空公司官网:Thai Airways International
2019/12/04 全球购物
大学毕业生工作的自我评价
2013/10/01 职场文书
电视购物广告词
2014/03/19 职场文书
商场开业庆典策划方案
2014/06/02 职场文书
幼师求职信
2014/06/23 职场文书
工作态度检讨书范文
2015/05/06 职场文书
活动宣传稿范文
2015/07/23 职场文书
有关保护环境的宣传标语100条
2019/08/07 职场文书