组件间通信

组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:

如上图所示:

(1)父子关系:A 和 B、B 和 C、B 和 D

(2)兄弟关系:C 和 D 

(3)隔代关系(可能隔多代):A 和 C 是

方法一:

1. 父组件向子组件传值props

通过 Prop 向子组件传递数据

2. 子组件向父组件传值(自定义事件$emit/v-on

父级组件可以像处理 native DOM 事件一样通过 v-on 监听子组件实例的任意事件:
父组件:
<blog-post
  ...
  v-on:enlarge-text="postFontSize += 0.1"
></blog-post>

子组件
<button v-on:click="$emit('enlarge-text')">
  Enlarge text
</button>
使用事件抛出一个值
可以使用 $emit 的第二个参数来提供这个值

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>


我们可以通过 $event 访问到被抛出的这个值:
<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>


或者,如果这个事件处理函数是一个方法:
<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>


那么这个值将会作为第一个参数传入这个方法:
methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

相关

有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
  Submit
</button>

methods: {
  warn: function (message, event) {
    // 现在我们可以访问原生事件对象
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}

方法二、$emit/$on(中间件)

这种方法通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。当我们的项目比较大时,可以选择更好的状态管理解决方案vuex。

    var Event=new Vue();
    Event.$emit(事件名,数据);
    Event.$on(事件名,data => {});
<div id="itany">
    <my-a></my-a>
    <my-b></my-b>
    <my-c></my-c>
</div>
<template id="a">
  <div>
    <h3>A组件:{{name}}</h3>
    <button @click="send">将数据发送给C组件</button>
  </div>
</template>
<template id="b">
  <div>
    <h3>B组件:{{age}}</h3>
    <button @click="send">将数组发送给C组件</button>
  </div>
</template>
<template id="c">
  <div>
    <h3>C组件:{{name}},{{age}}</h3>
  </div>
</template>
<script>
var Event = new Vue();//定义一个空的Vue实例
var A = {
    template: '#a',
    data() {
      return {
        name: 'tom'
      }
    },
    methods: {
      send() {
        Event.$emit('data-a', this.name);
      }
    }
}
var B = {
    template: '#b',
    data() {
      return {
        age: 20
      }
    },
    methods: {
      send() {
        Event.$emit('data-b', this.age);
      }
    }
}
var C = {
    template: '#c',
    data() {
      return {
        name: '',
        age: ""
      }
    },
    mounted() {//在模板编译完成后执行
     Event.$on('data-a',name => {
         this.name = name;//箭头函数内部不会产生新的this,这边如果不用=>,this指代Event
     })
     Event.$on('data-b',age => {
         this.age = age;
     })
    }
}
var vm = new Vue({
    el: '#itany',
    components: {
      'my-a': A,
      'my-b': B,
      'my-c': C
    }
});    
</script>

preview

$on 监听了自定义事件 data-a和data-b,因为有时不确定何时会触发事件,一般会在 mounted 或 created 钩子中来监听。

(1)引入单独文件

util.js

import Vue from 'vue'
export default new Vue()

(2)import Util from '@/untils/util.js'

@click="enterpage()"

 enterpage1 () {
      Util.$emit('navMessage', 2, '2-2', '店铺管理', {pathname: 'Popstore', title: '店铺运营管理'})
    },
 Util.$on('navMessage', function (index, ind, value, item) {
      that.goshare(index, ind, value, item)
    })

方法三:vuex

方法四、provide/inject

方法五:ref(写在父组件中

获取子组件中的数据和方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值