Vue 组件间通信方式

265 阅读2分钟

如果文中有出现纰漏、错误之处,还请大神您多指教。 本文将通过实例的方式记录一下 Vue 中组件之间的通信方式。 在 Vue中,需要组件通信的情况一般有以下几种:

父组件向子组件通信 子组件向父组件通信 兄弟组件通信

Vue 支持的通信方式

prop

$emit

类似 React 的 props 回调。

provide / inject

如果你熟悉 React,这与 React 的 context 特性很相似。

1、父组件向子组件通信(props)

Vue 和React数据流动是单向的,父组件通过 props 向子组件传递需要的信息。 新建一个名为 Com1 的 vue 文件。加入以下代码。

<template>
<div>
  <div>com1</div>
  <div>{{text}}</div>
</div>
</template>

<script>
  export default {
    name: 'Com1',
    props: {
      text: {
        type: String,
        default: ''
      }
    }
  }
</script>

新建一个 vue 文件,或直接在 App.vue 上写,加入以下代码。

<template>
  <div>
    <Com1 text="我是 com1 的 props" />
  </div>
</template>

<script>
  import Com1 from './Com1'

  export default {
    name: 'app',
    components: {
      Com1,
    }
  }
</script>

完成后,运行效果如下图所示,我们在父组件传了个一句话到组件里。

2、 子组件向父组件通信 ($emit)

在上面的基础上,我们来修改代码。

// com1.vue

<template>
<div>
  <div @click="handleClick">com1</div>
  <div>{{text}}</div>
</div>
</template>

<script>
  export default {
    name: 'Com1',
    props: {
      text: {
        type: String,
        default: ''
      }
    },
    methods: {
      handleClick () {
        this.$emit('click', '我是子组件传过来的')
      }
    }
  }
</script>
// App.vue

<template>
  <div>
    <Com1 text="我是 com1 的 props" @click="handleClick" />
    <div>{{data}}</div>
  </div>
</template>

<script>
  import Com1 from './Com1'

  export default {
    name: 'app',
    components: {
      Com1
    },
    data () {
      return {
        data: ''
      }
    },
    methods: {
      handleClick (e) {
        this.data = e
      }
    }
  }
</script>

完成后,点击 " com1 " ,我们就能接收到 子组件传过来的东西了。

3. 兄弟组件通信

最土的就是层层传递,新建一个 Com2 .vue ,我们要做的是把 Com1 的文字传递到 Com2.vue。

// Com2.vue 

<template>
  <div>{{text}}</div>
</template>

<script>
  export default {
    name: 'Com2',
    props: {
      text: {
        type: String,
        default: ''
      }
    }
  }
</script>
// Com1.vue

<template>
<div>
  <div @click="handleClick">com1</div>
  <div>{{text}}</div>
</div>
</template>

<script>
  export default {
    name: 'Com1',
    props: {
      text: {
        type: String,
        default: ''
      }
    },
    methods: {
      handleClick () {
        this.$emit('click', '我是 Com1 传过来的 !!!')
      }
    }
  }
</script>
// App.vue

<template>
  <div>
    <Com1 text="我是 com1 的 props" @click="handleClick" />
    ------------
    <Com2 :text="data" />
  </div>
</template>

<script>
  import Com1 from './Com1'
  import Com2 from './Com2'

  export default {
    name: 'app',
    components: {
      Com1,
      Com2
    },
    data () {
      return {
        data: ''
      }
    },
    methods: {
      handleClick (e) {
        this.data = e
      }
    }
  }
</script>

再点击 ' com1 ' ,Com2.vue 里就接收到了我们从 Com1 传过去的东西

另一种办法就是 vue@2.2.0 新增的 provide / inject

provide 和 inject主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

我们继续修改刚才的那几个文件。

// App.vue

<template>
  <div>
    <Com1 text="我是 com1 的 props" @click="handleClick" />
  </div>
</template>

<script>
  import Com1 from './Com1'

  export default {
    name: 'app',
    provide: {
      text: '我是App.vue传过来的'
    },
    components: {
      Com1
    },
    data () {
      return {
        data: '',
        transitionName: ''
      }
    },
    methods: {
      handleClick (e) {
        this.data = e
      }
    }
  }
</script>
// Com1.vue

<template>
<div>
  <div>com1</div>
  <div>{{text}}</div>
  ------------
  <Com2 />
</div>
</template>

<script>
  import Com2 from './Com2'

  export default {
    name: 'Com1',
    components: {
      Com2
    },
    props: {
      text: {
        type: String,
        default: ''
      }
    }
  }
</script>
// Com2.vue

<template>
  <div>Com2:{{text}}</div>
</template>

<script>
  export default {
    name: 'Com2',
    inject: ['text']
  }
</script>

修改后,我们直接通过在 App.vue 中 定义了 provide , 然后 直接传递到了 Com2 组件,在 Com2 里通过 inject 接收。虽然它是 Com1 的子组件,但是我们并没有使用 props 的方式层层传递下去。

其他通信方式

就要用到那些状态管理工具了Vuex