vue组件之间的几种通讯方式

2019-06-17  本文已影响0人  广告位招租

1. props和$emit

最简单常用的方式

目录结构


目录结构
// index.vue
<template>
  <div>
    <h2>父组件中</h2> 
    输入向子组件传值<input type="text" v-model="foo">
    <child-com :foo="foo" @out="getMsg"></child-com>
    <h2>子组件信息</h2>{{childMsg}}
  </div>
</template>

<script>
  const childCom = () => import('./components/child')
  export default {
    components: {
      childCom
    },
    data() {
      return {
        foo: '',
        childMsg: ''
      }
    },
    methods: {
      getMsg(v) {
        this.childMsg = v
      }
    }
  }
</script>

// child.vue
<template>
  <div>
    <h2>子组件中</h2> {{foo}}
    <br/>
    <button @click="sendMsg">点击向父组件传值</button>
  </div>
</template>

<script>
  export default {
    props: ['foo'],
    methods: {
      sendMsg() {
        this.$emit('out', 'msg')
      }
    }
  }
</script>

效果图


props和$emit传值效果图

2. vuex

https://vuex.vuejs.org/

3. 依赖注入

使用场景

当组件嵌套过多,而且所有组件都需要使用根组件(包括但不限于)的某一些内容时(数据或方法),使用依赖注入会比普通的传值更加方便

使用

// 依赖注入一个getMap方法
provide: function () {
  return {
    getMap: this.getMap
  }
}

然后在任何子组件里,我们都可以使用 inject 选项来接收指定的我们想要添加在这个实例上的属性:

inject: ['getMap']

相比于$parent,选择依赖注入的好处

使用依赖注入可以让我们免于暴露整个根组件信息,具体有两点

4. 使用$emit/$on,模拟发布订阅模式

这里需要利用一个空的vue对象当做事件中心,可以实现组件间的通讯

目录结构


目录结构
// event.js创建一个新的vue实例
import Vue from 'vue'
const Event = new Vue()

export default Event

// index.vue
<template>
  <div> 
    父组件 {{msg}}
    <child-com01></child-com01>
    <child-com02></child-com02>
  </div>
</template>

<script>
  import Event from './components/event'

  const childCom01 = () => import('./components/child01')
  const childCom02 = () => import('./components/child02')
  
  export default {
    components: {
      childCom01,
      childCom02
    },
    data() {
      return {
        msg: ''
      }
    },
    mounted() { // 因为不知道什么时候会触发方法,所以一般会选择在created或者是mounted的时候绑定
      Event.$on('getMsg', v => this.msg = v) //箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
    }
  }
</script>

// child01.vue
<template>
  <div>
    子组件01 {{msg}}
  </div>
</template>

<script>
  import Event from './event'
  export default {
    mounted() {
      Event.$on('getMsg', v => this.msg = v)
    },
    data() {
      return {
        msg: ''
      }
    }
  }
</script>

// child02.vue
<template>
  <div>
    <h2>子组件02</h2>
    <button @click="sendMsg">to 父组件和兄弟组件</button>
  </div>
</template>

<script>
  import Event from './event'
  export default {
    methods: {
      sendMsg() {
        Event.$emit('getMsg', 'child02的数据')
      }
    }
  }
</script>
点击之后效果

注意: 在使用$on绑定事件之后,需要主动销毁事件
例如

beforeDestroy () {
  Event.$off('getMsg')
}

5. 使用$attrs/$listeners

在父组件通过v-bind绑定,但是在子组件中未被props声明的属性可以通过$attrs获取到。

$listeners包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器


目录结构
// index.vue
<template>
  <div> 
    父组件
    <child-com01 :msg1="msg1" :msg2="msg2" :msg3="msg3" :msg4="msg4" @indexfuc="indexfuc" @indexfuc2="indexfuc2" @indexfuc3="indexfuc3"></child-com01>
  </div>
</template>

<script>

  const childCom01 = () => import('./components/child01')
  
  export default {
    components: {
      childCom01
    },
    data() {
      return {
        msg1: 'm1',
        msg2: 'm2',
        msg3: 'm3',
        msg4: 'm4'
      }
    },
    methods: {
      indexfuc() {
        console.log('根组件方法1')
      },
      indexfuc2() {
        console.log('根组件方法2')
      },
      indexfuc3() {
        console.log('根组件方法3')
      }
    }
  }
</script>

// child01.vue
<template>
  <div>
    子组件01收到的数据 {{$attrs}}
    props接收的数据{{msg1 + ' ' + msg2}}
    <child-com02 v-bind="$attrs" v-on="$listeners"></child-com02>
  </div>
</template>

<script>
  const childCom02 = () => import('./child02')

  export default {
    components: {
      childCom02
    },
    props: ['msg1', 'msg2'],
    mounted() {
      console.log(this.$attrs, '---child1中')
      console.log(this.$listeners, '---child1中')
      this.$listeners.indexfuc2()
    }
  }
</script>

// child02.vue
<template>
  <div>
    子组件02收到的数据 {{$attrs}}
  </div>
</template>
<script>
export default {
  mounted() {
    console.log(this.$listeners, '---child02中')
    this.$listeners.indexfuc3()
  }
}
</script>

执行结果

这里的child02是child01的子组件,三个组件是嵌套关系,child02可以拿到全部的属性和方法

6. $refs和$parent、$children

使用ref给组件赋值一个ID

<base-input ref="usernameInput"></base-input>

之后使用this.$refs.usernameInput来访问这个组件

this.$refs.usernameInput

或者在组件中使用来获取数据

this.$parent
this.$children

但是这几种无法实现跨级或兄弟组件之间传递消息,在使用过程中,应该酌情使用以上几种方法

上一篇下一篇

猜你喜欢

热点阅读