详解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 相关文章推荐
javascript在一段文字中的光标处插入其他文字
Aug 26 Javascript
JavaScript对象、属性、事件手册集合方便查询
Jul 04 Javascript
JavaScript高级程序设计(第3版)学习笔记5 js语句
Oct 11 Javascript
jquery防止重复执行动画避免页面混乱
Apr 22 Javascript
在Node.js中实现文件复制的方法和实例
Jun 05 Javascript
JavaScript判断数字是否为质数的方法汇总
Jun 02 Javascript
判断数组的最佳方法(推荐)
Oct 11 Javascript
整理一下常见的IE错误
Nov 18 Javascript
在vue.js中抽出公共代码的方法示例
Jun 08 Javascript
ExtJs的Ext.Ajax.request实现waitMsg等待提示效果
Jun 14 Javascript
解决Vue2.0自带浏览器里无法打开的原因(兼容处理)
Jul 28 Javascript
利用js实现简易红绿灯
Oct 15 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
PHP 防恶意刷新实现代码
2010/05/16 PHP
一些需要禁用的PHP危险函数(disable_functions)
2012/02/23 PHP
php实现rc4加密算法代码
2012/04/25 PHP
PHP OPP机制和模式简介(抽象类、接口和契约式编程)
2014/06/09 PHP
PHP中SESSION的注销与清除
2015/04/16 PHP
thinkPHP批量删除的实现方法分析
2016/11/09 PHP
Yii2实现增删改查后留在当前页的方法详解
2017/01/13 PHP
PHP实现 APP端微信支付功能
2018/06/22 PHP
javascript制作坦克大战全纪录(2)
2014/11/27 Javascript
jQuery实现将页面上HTML标签换成另外标签的方法
2015/06/09 Javascript
JavaScript实现点击按钮切换网页背景色的方法
2015/10/17 Javascript
详解jQuery Mobile自定义标签
2016/01/06 Javascript
Vuejs第十二篇之动态组件全面解析
2016/09/09 Javascript
详解AngularJs中$sce与$sceDelegate上下文转义服务
2016/09/21 Javascript
angular bootstrap timepicker TypeError提示怎么办
2017/06/13 Javascript
详解JavaScript中的六种错误类型
2017/09/21 Javascript
使用store来优化React组件的方法
2017/10/23 Javascript
初探js和简单隐藏效果的实例
2017/11/23 Javascript
vue父组件向子组件传递多个数据的实例
2018/03/01 Javascript
15分钟上手vue3.0(小结)
2020/05/20 Javascript
在Python中使用Neo4j数据库的教程
2015/04/16 Python
python代码过长的换行方法
2018/07/19 Python
Python 项目转化为so文件实例
2019/12/23 Python
MxNet预训练模型到Pytorch模型的转换方式
2020/05/25 Python
Python eval函数原理及用法解析
2020/11/14 Python
联想瑞士官方网站:Lenovo Switzerland
2017/11/19 全球购物
DogBuddy荷兰:找到你最完美的狗保姆
2019/04/17 全球购物
Java如何格式化日期
2012/08/07 面试题
小学语文国培感言
2014/03/04 职场文书
教师个人自我剖析材料
2014/09/29 职场文书
小学教师先进事迹材料
2014/12/15 职场文书
高考诚信考试承诺书
2015/04/29 职场文书
刑事申诉状范文
2015/05/20 职场文书
中学团支部工作总结
2015/08/13 职场文书
Javascript中Microtask和Macrotask鲜为人知的知识点
2022/04/02 Javascript
Golang map映射的用法
2022/04/22 Golang