Vue中的组件通信

146 阅读1分钟
汇总
  1. 于$on系列的总结

image.png 2. 组件通信方式

  • v-bind 父传子
  • parent.parent.emit子传父
  • 父传递给子一个函数, 子组件调用 子传父
  • 上层传递后代 provide/inject
  • 子孙传递根 $root
  • 随意传传 eventBus
  • vuex
1. provide/inject
  • provide/inject是成对使用的,是为了解决深层次组件通信的;
  • 父组件通过provide提供数据;
  • 子组件通过inject注入值;
  • 父组件向所有子孙组件广播;
  • provide/inject传递数据的方式是非响应式的(即父组件值变化之后。子组件的值不会响应式的改变),但是对象形式的数据是响应式的;
  1. 父组件
// 2.6之后的新功能
data() {
  return {
    innerNum: 123,
    obj: { innerNum: 123 }
  }
},
provide() {
  return {
    num: this.innerNum,
    obj: this.obj
  }
}
  1. 子组件(从父组件接收的num是非响应式的,obj是响应式的)
inject:['num','obj']
2. $root + 监听和触发
2.1 相同对象使用onon和emit
  • 在父组件中使用$on绑定事件;
  • 在子组件中使用$emit接收和触发父组件绑定的事件;
  1. 父组件
<template>
    <div class="box">
        <h2>SSon1</h2>
        <button @click="bindRoot">root绑定事件</button>
    </div>
</template>

<script>
export default {
    inject:['num','obj'],
    methods:{
        bindRoot(){
            this.$root.$on('rootEvent',(data)=>{
                console.log('我是SSon1组件,事件触发了',data)
            })
        }
    }
}
</script>
  1. 子组件
<template>
  <div class="hello">
    <div class="box">
      <h2>Son1</h2>
      <button @click="toggleRoot">root触发事件</button>
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    toggleRoot() {
      this.$root.$emit('rootEvent', '【【我是数据Son1】】')
    }
  },
  name: 'Son1',
}
</script>
2.2 parent/parent/children
  • $parent:获取临近父组件;
  • children:获取临近子组件;
  1. 父组件(可以通过this.$children拿到子组件)
<template>
  <div class="box">
    <h2>App</h2>
    <button @click="showChildren">输出children</button>

    <!-- 测试ParentChildren -->
    <ParentChildren />
  </div>
</template>

<script>
import ParentChildren from './components/ParentChildren';

export default {
  name: 'App',
  methods: {
    showChildren() {
      console.log(this.$children);
    }
  },
  components: {
    ParentChildren
  }
}
</script>
  1. 子组件(可以通过this.$parent拿到父组件)
<template>
    <div class="box">
        <h2>ParentChildren</h2>
        <button @click="showParent">显示$parent</button>
    </div>
</template>

<script>
export default {
    name:'xxx',
    methods:{
        showParent(){
            console.log(this.$parent)
        }
    }
}
</script>
2.3 eventBus
  • 单独建一个new Vue()文件,用来进行组件间数据传递;
  • 专做组件通信,解决各种组件间通信的问题;
  • 具有高内聚、低耦合的优点;
  1. Connect.js文件(存放建立的new Vue()对象)
import Vue from "vue";
export default new Vue();
  1. 父组件(Connect.$on())
<template>
    <div class="box">
        <button @click="bindEventBus">EventBus绑定事件总线</button>
    </div>
</template>

<script>
import Connect from './Connect'
export default {
    methods:{
        bindEventBus(){
            Connect.$on('connectEvent',data=>{
               console.log('触发了EventBus',data) 
            })
        }
    }
}
</script>
  1. 子组件(Connect.$emit())
<template>
  <div class="hello">
    <div class="box">
      <h2>Son1</h2>
      <button @click="emitEventBus">eventBus触发事件</button>
    </div>
  </div>
</template>

<script>
import Connect from './Connect'
export default {
  methods: {
    emitEventBus() {
      Connect.$emit('connectEvent', '【【Son1的数据】】')
    }
  },
  name: 'Son1',
}
</script>
2.4 $listeners绑定事件
  1. 父组件
<template>
  <div class="box">
    <h2>App</h2>
    <button @click="showChildren">输出children</button>
    {{ data1 }} || {{ data2 }}
    <ReactiveVue v-model="data1" :show.sync="data2" />
  </div>
</template>

<script>
import ReactiveVue from './components/Reactive.vue';
export default {
  name: 'App',
  methods: {
    showChildren() {
      console.log(this.$children);
    }
  },
  components: {
    ReactiveVue
  }
}
</script>
  1. 子组件
<template>
  <div class="box">
    <h2>Reactive</h2>
    <button @click="change2">变更2</button>
  </div>
</template>

<script>
export default {
    methods:{
        output(){
            console.log(this,'组件数据')
        },
        change2(){
            this.$listeners['input'](999);
            this.$listeners['update:show'](8888);
        }
    }
}
</script>
2.5 .sync同步修饰符 v-model
  1. 父组件 <ReactiveVue v-model="data1" :show.sync="data2" />
  • 都是语法糖;
  • 真正的底层实现是:
  • :value=“xxx” :xxx.sync=“变量”;
  • @input=“xxx” @update:xxx=“函数”;
<template>
  <div class="box">
    <h2>App</h2>
    <button @click="showChildren">输出children</button>
    {{ data1 }} || {{ data2 }}
    <ReactiveVue v-model="data1" :show.sync="data2" />
  </div>
</template>

<script>
import ReactiveVue from './components/Reactive.vue';
export default {
  name: 'App',
  methods: {
    showChildren() {
      console.log(this.$children);
    }
  },
  components: {
    ReactiveVue
  }
}
</script>
  1. 子组件
<template>
  <div class="box">
    <h2>Reactive</h2>
    <button @click="output">输出</button>
    <button @click="change1">变更</button>
    <button @click="change2">变更2</button>

  </div>
</template>

<script>
export default {
    methods:{
        output(){
            console.log(this,'组件数据')
        },
        change1(){
            this.$emit('input',999);
            this.$emit('update:show',8888);
        },
        change2(){
            this.$listeners['input'](999);
            this.$listeners['update:show'](8888);
        }
    }
}
</script>