# Vue.js 之组件通信的方式

# 父传子

# Prop

# 数组形式接收 prop

<parent>
  <child title= "我是标题" content="我是内容"></child>
</parent>
1
2
3

那么在子组件中就可以使用 props 来接收这个 content

Vue.component('child',{
  // 以数组的形式接收父组件传递的多个数据
  props: ['title','content']
});
1
2
3
4

# 对象形式接收 prop

使用对象的形式定义每一个 prop 相关的属性。

Vue.component('child',{
  props: {
    title: {
      // 类型
      type: String,
      // 默认值
      default: '',
      // 必需
      required: false,
      // 自定义校验
      validator: function(value) {

      }
    },
    content: {}
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# $attrs

<parent>
  <child title="我是标题" content="我是内容"></child>
</parent>
1
2
3

有时候子组件并没有定义自身的 Prop ,那么就可以使用 $attrs 来获取父组件传递的所有属性值。

Vue.component('child',{
  mounted: function() {
    console.log(this.$attrs.title);   // 我是标题
    console.log(this.$attrs.content); // 我是内容
  }
});
1
2
3
4
5
6

# $listeners

<parent>
  <child @click="click()"></child>
</parent>
1
2
3

当父组件传递的是一个原生事件的时候,我们可以加上 .native 修饰符,, 这样子组件就可以正确接收。

<parent>
  <child @click.native="click()"></child>
</parent>
1
2
3

也可以使用 $listeners 获取父组件传递的所有事件

Vue.component('child',{
  mounted: function() {
    console.log(this.$listeners.click());   // 调用 click 事件
  }
});
1
2
3
4
5

或者在子组件上监听父组件传递的所有事件

Vue.component('child',{
  template: '<button v-on=$listeners></button>'
});
1
2
3

# $children

父组件可以通过 $children 获取到自己下面的所有子组件实例

<parent>
  <child></child>
  <child></child>
  <child></child>
</parent>

<script>
  Vue.component('parent',{
    mounted: function() {
      console.log(this.$children);
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

# provide/inject

父组件中使用 provide 提供数据

Vue.componet('parent',{
  provide:{
    title: '我是标题',
    content: '我是内容'
  }
});
1
2
3
4
5
6

子组件中使用 inject 注入数据

Vue.componet('child',{
  inject: ['child']
});
1
2
3

# ref

在父组件中可以使用 ref 特性直接访问一个子组件实例

<parent>
  <child ref="child"></child>
</parent>

<script>
  Vue.component('parent',{
    mounted: function() {
      console.log(this.$refs.child);
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11

# 子传父

# Prop

有时候父组件传递给子组件的 prop 是一个对象,那么在子组件中修改了该对象的属性后,父组件同样会受到影响。

<parent>
  <child :data="obj"></child>
</parent>

<script>
Vue.component('parent',{
  data: {
    obj: {
      content: '我是内容'
    }
  }
});
Vue.component('child',{
  props: ['data'],
  mounted: function() {
    // 修改后,父组件中的 content 会变化
    this.data.content = '被子组件修改'
  }
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# $emit

我们可以在子组件中触发自定义的事件,在父组件的作用域监听。

<parent>
  <child @update="change"></child>
</parent>

<script>
Vue.component('parent',{
  methods: {
    change: function(value) {
      console.log(value);  // 打印:子组件传递的数据
    }
  }
});
Vue.component('child',{
  mounted: function() {
    this.$emit('update', '子组件传递的数据');
  }
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# .sync

<parent>
  <child v-bind:title.sync="title"></child>
</parent>

<script>
Vue.component('parent',{
  data: {
    title: '我是一个标题'
  }
});
Vue.component('child',{
  mounted: function() {
    this.$emit('update:title', '子组件修改数据');
  }
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

v-bind:title.sync = "title" 等价于 v-bind:title="title" v-on:update:title="title = $event"

# $parent

子组件通过 $parent 获取父组件实例

<parent>
  <child></child>
</parent>

<script>
  Vue.component('child',{
    mounted: function() {
      console.log(this.$parent);
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11

# 同级组件

# EventBus

使用一个全局的 Vue 实例作为事件的传递媒介。

<A></A>
<B></B>
<C></C>

<script>
  var EventBus = new Vue();

  Vue.component('A',{
    mounted: function() {
      EventBus.$emit('change', 'A 传递的数据');
    }
  });
  Vue.component('B',{
    mounted: function() {
      EventBus.$on('change',function(data) {
        console.log(data);
      });
    }
  });
  Vue.component('C',{
    mounted: function() {
      EventBus.$on('change',function(data) {
        console.log(data);
      });
    }
  });
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27