Vue2 组件通信的方式

66 阅读1分钟

组件通信

Prop和$emit

💡 主要用于父子组件通信,父组件单向传输数据给子组件,子组件不能修改`props`

父传子的过程

父组件在子组件上面绑定 (v-bind)自身的属性 msg ,子组件通过props属性接收msg。

子传父的过程

子传父 子组件通过this.$emit(事件名,参数),触发父组件事件。同时父组件通过(v-on)监听事件 然后触发父组件事件

  1. 父组件

    <template>
      <div class="father">
        father1 props传输
        <Son :msg=msg @son1="logSon"></Son>
      </div>
    </template>
    
    <script>
    import Son from './son'
    
    export default {
      components: {
        Son
      },
      data() {
        return {
          msg: 'this is father1 msg'
        }
      },
      methods: {
        logSon(emitData) {
          console.log(emitData)
        }
      }
    }
    </script>
    
    <template>
      <div class="father">
        <Son :msg=msg @son1=logSon></Son>
      </div>
    </template>
    
    <script>
    import Son from './son'
    
    export default {
      components: {
        Son
      },
      data() {
        return {
          msg: 'this is father1 msg'
        }
      },
      methods: {
        logSon(emitData) {
          console.log(emitData)
        }
      }
    }
    </script>
    
  2. 子组件

    <template>
      <div class="son">
        <button @click="$emit('son1',{a:1})"> touch</button>
      </div>
    </template>
    
    <script>z
    export default {
      props: {
        msg: {
          type: String
        }
      },
    
    }
    </script>
    

Provide& Inject

💡 祖孙元素传值,不能响应式更新值,但是如果值是可监听对象,那么还是可以响应

祖先元素定义provide

data() {
  return {
    msg: 'i can change',
    reactiveObjMsg: {
      msg: 'reactiveObjMsg'
    }
  }
},
provide() {
  return {
    provideMsg: 'this is provide', //写死的元素 无法响应式
    reactiveProvideMsg: this.reactiveObjMsg, // this.reactiveObjMsg.msg 改变子孙元素也能改变
    thisVM: this // 直接传递当前实例下去 可以直接在祖孙元素调用 thisVM.msg
  }
},
methods: {
    changed() {
      this.msg = 'changed'
      this.reactiveObjMsg.msg = 'changed'
      console.log(this.msg)
    }
  },

孙子元素接收inject

export default {
  name: "index",
  inject: ['reactiveProvideMsg', 'provideMsg', 'thisVM'],
}

$attrs & $listeners

💡 主要用于隔代传值,且不用在中间组件写更多的`props` 能传输方法和数据

只需要在中间元素绑定$attrs监听$listeners 子孙元素就可以调用祖先元素的数据和调用方法

祖先元素

<template>
  <div>
    <h2>组件A 数据项:{{ num }}</h2>
    <B @change-num="changeNum" :num="num"></B>
  </div>
</template>
<script>
import B from "./b";

export default {
  data() {
    return {
      num: 100
    };
  },
  components: {B},
  methods: {
    changeNum(val) {
      this.num =val;
    }
  }
};
</script>

中间元素

<template>
  <div>
    <h3>组件B</h3>
    <C v-bind="$attrs" v-on="$listeners"></C>
  </div>
</template>
<script>
import C from "./c";
export default {
  components: { C },
};
</script>

子孙元素

<template>
  <div>
    <h5>组件C</h5>
    <input v-model="nums" @input="$emit('change-num', nums)"/>
  </div>
</template>
<script>
export default {
  props: ['num'],
  data() {
    return {
      nums: 0
    }
  },
  created() {
    this.nums = this.num;
    console.log(this.$attrs, this.$listeners);
  },

};
</script>

$children & $parent

💡 直接调用父元素的实例和子元素的实例

调用方式

// 父组件调用子元素实例
this.$children[第几个子组件] 
//子组件调用父组件
this.$parent

ref & refs

💡 `ref`主要用于访问实例数据,如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据
<template>
  <div class="father">
    <B ref="comB" ></B>
  </div>
</template>
<script>
import B from "./b";
export default {
  components: {B},
  mounted() {
    console.log(this.$refs['comB'])
  }
};
</script>

eventBus

💡 主要用于简单的数据共享传输
// 创建 eventbus 实例 并且在需要他的地方引入
import Vue from 'vue'
export const EventBus = new Vue()

//A组件 引入Bus使用$emit派发事件
import {EventBus} from './bus.js'
EventBus.$emit(事件名, 参数)

//B组件 引入Bus使用$on监听事件
import {EventBus} from './bus.js'
EventBus.$on(事件名, fn)

//移除监听
EventBus.$off(事件名, {})

Vuex