详解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 相关文章推荐
JS Replace 全部替换字符的用法小结
Dec 24 Javascript
自写的jQuery异步加载数据添加事件
May 15 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
Mar 08 Javascript
js的form表单提交url传参数(包含+等特殊字符)的两种解决方法
May 25 Javascript
Vue.js系列之vue-router(上)(3)
Jan 03 Javascript
jquery实现多次上传同一张图片
Jan 09 Javascript
jQuery序列化后的表单值转换成Json
Jun 16 jQuery
基于ExtJs在页面上window再调用Window的事件处理方法
Jul 26 Javascript
React Native 环境搭建的教程
Aug 19 Javascript
基于Bootstrap表单验证功能
Nov 17 Javascript
vue.js select下拉框绑定和取值方法
Mar 03 Javascript
Element-ui el-tree新增和删除节点后如何刷新tree的实例
Aug 31 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实现采集程序原理和简单示例代码
2007/03/18 PHP
php注销代码(session注销)
2012/05/31 PHP
php中通过数组进行高效随机抽取指定条记录的算法
2013/09/09 PHP
PHP设置一边执行一边输出结果的代码
2013/09/30 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
2014/07/04 PHP
如何让thinkphp在模型中自动完成session赋值小教程
2014/09/05 PHP
PHP正则替换函数preg_replace和preg_replace_callback使用总结
2014/09/22 PHP
php htmlentities()函数的定义和用法
2016/05/13 PHP
php结合mysql与mysqli扩展处理事务的方法
2016/06/29 PHP
php+ajax注册实时验证功能
2016/07/20 PHP
PHP chunk_split()函数讲解
2019/02/12 PHP
jquery div拖动效果示例代码
2013/12/08 Javascript
使用javascript为网页增加夜间模式
2014/01/26 Javascript
使用jQuery动态加载js脚本文件的方法
2014/04/03 Javascript
AngularJS实现表单验证
2015/01/28 Javascript
jquery实现对联广告的方法
2015/02/05 Javascript
JavaScript 对象深入学习总结(经典)
2015/09/29 Javascript
超全面的JavaScript开发规范(推荐)
2017/01/21 Javascript
在Vue中使用echarts的实例代码(3种图)
2017/07/10 Javascript
JavaScript查看代码运行效率console.time()与console.timeEnd()用法
2019/01/18 Javascript
jQuery实现为table表格动态添加或删除tr功能示例
2019/02/19 jQuery
axios 实现post请求时把对象obj数据转为formdata
2019/10/31 Javascript
详解vue中$nextTick和$forceUpdate的用法
2019/12/11 Javascript
[01:15:16]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第一场 1月26日
2021/03/11 DOTA
Win10下Python环境搭建与配置教程
2016/11/18 Python
解决Tensorflow安装成功,但在导入时报错的问题
2018/06/13 Python
pyttsx3实现中文文字转语音的方法
2018/12/24 Python
对Python中画图时候的线类型详解
2019/07/07 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
浅析python 动态库m.so.1.0错误问题
2020/05/09 Python
pandas处理csv文件的方法步骤
2020/10/16 Python
详解python百行有效代码实现汉诺塔小游戏(简约版)
2020/10/30 Python
Bootstrap File Input文件上传组件
2020/12/01 HTML / CSS
英国IT硬件供应商,定制游戏PC:Mesh Computers
2019/03/28 全球购物
测量工程专业求职信
2014/02/24 职场文书
生死牛玉儒观后感
2015/06/11 职场文书