vue 组件之间通信方式总结

134 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

前言

今天是 五一假的第一天,疫情回不了家,闲来无事,是时候该把之前用到的总结总结了,也为之后的面试复习 做点准备,目前只用vue2.*版本,3.0还在熟悉中,实际项目中还没用到过,等后面时间充裕后再补上,本篇文章 只针对 组件通信 这一分支 来详细总结下

v-model

说起v-model,相信使用过vue的朋友们再也熟悉不过了

v-model 本质上不过是语法糖,以下几种写法效果一样,使用语法糖不过方便一些

<input v-model="name" />
<!--等同于-->
<input v-bind:value="name" v-on:input="name="$event-target.value"" />
<!--等同于-->
<input :value="name" @input="name=$event-target.value" />

组件中应用 v-model

<!--父级 parent-->
<parent v-model="name">

<!--子组件写法-->
...
<input v-model="childName" @input="change">
...
props:{
  value:{
    type: [String,Number],
    default: ''
  }
},
created(){
  this.childName = this.value
},
data:{
  return { childName:''}
},
method:{
  change(){
    this.$emit('input',childName)
  }
}

父子 孙组件通信

最常用的 父传子props 和子传父 $emit 在上文中 组件中应用 v-model 以有介绍,不便多说 下面介绍其他 几种通信方式

this.$refs

this.$refs[**] 可以获取某个子组件的 实例

<!--父级 parent-->
...
<child ref="child">
...
mounted:{
    // 两种写法都可以
    this.refs.child.setName('哈哈哈')
    this.refs['child'].setName('哈哈哈')
}

<!--子集-->
...
{{name}}
...
data:{
  return { Name:''}
},
method:{
  setName(name){
      this.name = name
  }
}

this.$parent

获取父级实例

this.$children

当前实例的直接子组件实例集合,是个数组,但值得注意的 这个数组 不是按照组件的 顺序来的,要想确定 数组配合 v-for 来生成子组件

attrsattrs、listeners

$attrs

attrs包含了父作用域中不作为prop被识别(且获取)attribute绑定(classstyle除外),也就是说,组件中如果props属性,或者props没有父级传入传入的参数(通过:=这种),就可以在attrs 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外),也就是说 ,组件中如果props属性,或者props 没有父级 传入传入的参数(通过 :**=** 这种),就可以在 attrs 中获取

<!--父级-->
..
<child
  :a="a"
  :b="b"
  :c="c"
/>
..
data(){
    return {
        a:'1',
        b:'2',
        c:'3'
    }
}
--
<!--child-->
..
<div> child的$attrs:{{$attrs}}</div>
..

props:{
    a:'String',
    default: ''
},
mounted() {
 console.log(this.$attrs); // { "b": "2", "c": "3" }
  }

$listeners

listeners包含了父作用域中(不含.native修饰符的)von@)事件监听器,它可以通过von="listeners 包含了 父作用域中(不含.native 修饰符的) v-on (@)事件监听器,它可以通过 v-on="listeners" 出入内部组件

举例

<!--父级 parent.vue-->
<child @upData="upData" :name="name" />
...
data(){
    return {name:'parent'}
}

<!--子级 child.vue-->
<grandson v-bind="$attrs" v-on="$listeners" />
...
 // 默认情况下(inheritAttrs 默认为 true)父作用域的不被认作props的属性,
 // 将会“回退”且作为普通的HTML特性应用在子组件的根元素上,设置 inheritAttrs为false 会禁止默认行为
 inheritAttrs: false,
...

<!--孙子级 grandson.vue-->
<div>{{name}}</div>
<button @click="change">改变</button>
...
props:{
    name:{
        type:String,
        default: ''
    }
},
methods:{
    change(){
        this.$emit('upData', 'grandson')
    }
}

attrsattrs listeners 更适合 组件之间跨级传参,这样使得代码更加简洁,更利于维护。

vuex

状态 管理,适合全局性 公用组件

mapState、mapGetter、mapActions

mapState

为组件创建计算属性以返回 Vuex store 中的状态。

  computed: {
    ...mapState({
      name: (state) => state.user.name
    })
  },

mapGetters

为组件创建计算属性以返回 Vuex store 中的状态。

  computed: {
    ...mapGetters({
      name: 'userName'
    })
  },

mapActions

创建组件方法分发 action

methods: {
    ...mapActions(['getUserInfo']),
},

事件总线

按需 来创建事件和触发事件

Vue.prototype.$bus = new Vue()
...

<!--组件A-->
// 监听事件 
this.$bus.$on('sendMsg',(msg)=>{console.log(msg)})

<!--组件B-->
// 触发事件 
this.$bus.$emit('sendMsg','我是组件B')

关闭监听事件

this.$bus.$off('sendMsg')