【Vue】组件间通信的7种方法(全)

目录

组件之前的通信方法

[1. props/emit](#1. props/emit)

2.parent/children

3.ref

4.v-model

5.sync

6.attrs,attrs,attrs,listeners

7.provide/inject

7.eventBus


组件之前的通信方法

1. props/$emit

父传子 props 这个只能够接收父组件传来的数据 不能进行修改 可以静态传递 也可以动态传递(一个表达式,一个对象或者布尔值等)父组件属性绑定 子组件用props接收

子改父 emit子组件的内部通过emit 子组件的内部通过emit子组件的内部通过emit去触发这个事件 同时也可以传参过去 v-on去传递事件是写在子组件的标签身边的,然后回调函数是写在父组件的methods身上的

html 复制代码
//父组件
<template>
  <div>
    <child :msg="msg"  @changeMsg="changeMsg"></child>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import child from "../components/Child";
export default {
  data() {
    return {
      msg: "hello"
    };
  },
  components: { child },
  methods:{
   changeMsg(value){
      this.msg=value
   }
  }
};
</script>

// 这是子组件
<template>
  <div>
      <div @click="change">改变父组件的{{msg}}</div>
  </div>
</template>

<script>
export default {
  props: ["msg"],
  methods:{
   change(){
     this.$emit("changeMsg",123)
   }
  }
};
</script>

2.parent/children

$parent 子组件可以获取到父组件身上的属性以及方法,但是一定要注意,如果说这个组件的父组件不止一个的话 那么容易发生报错

children父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话打印this.children 父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话 打印this.children父组件拿到自己身上的子组件的属性已经方法,如果身上的子组件不止一个的话打印this.children的时候会以数组的形式展示出来

3.ref

父组件想要拿到子组件身上的数据 还可以给子组件写上ref="名字" 然后在父组件身上 this.$ref.名字就可以拿到子组件 身上的方法已经数据都可以获取到

4.v-model

v-model:将数据传递下去的同时 子组件可以修改父组件提供过来的数据(emit方法)

html 复制代码
// 这是父组件
<template>
  <div>
    <child v-model="msg"></child>
    <p>{{msg}}</p>
  </div>
</template>

<script>
import child from "../components/Child";
export default {
  data() {
    return {
      msg: "hello"
    };
  },
  components: { child }
};
</script>
// 这是子组件
<template>
  <div>
      <input :value="value" @input="$emit('input',$event.target.value)">
  </div>
</template>

<script>
export default {
  props: ["value"]
};
</script>

5.sync

sync:将数据传递下去的同时 允许子组件可以修改数据

html 复制代码
// 父组件

<template>
  <div>
    {{num}}
   <child-a :count.sync="num" />
  </div>
</template>

<script>
import childA from "../components/ChildA";
export default {
  data() {
    return {
      num: 0
    };
  },
  components: { childA }
};
</script>

// 子组件
<template>
  <div>
     <div @click="handleAdd">ADD</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      counter: this.count
    };
  },
  props: ["count"],
  methods: {
    handleAdd() {
      this.$emit("update:count", ++this.counter);
    }
  }
};
</script>

6.attrs,attrs,attrs,listeners

attrs包含的是父组件不被prop所识别的特性(📢:inheritAttrs为true属性才会渲染false时属性不会被渲染)可以通过v−bind="attrs 包含的是父组件不被prop所识别的特性 (📢:inheritAttrs为true 属性才会渲染 false时 属性不会被渲染) 可以通过v-bind="attrs包含的是父组件不被prop所识别的特性(📢:inheritAttrs为true属性才会渲染false时属性不会被渲染)可以通过v−bind="attrs"传给内部的组件 listeners包含父组件啊种v−on事件监听器通过v−on="listeners 包含父组件啊种v-on事件监听器 通过v-on="listeners包含父组件啊种v−on事件监听器通过v−on="listeners" 传给内部的足迹爱

html 复制代码
<template>
  <div>
    <!-- 父组件 -->
    <h1>{{ count }}</h1>
    <son
      :msg="msg"
      :foo="foo"
      :boo="boo"
      :coo="coo"
      :doo="doo"
      title="前端工匠"
      @click.native="handleClick"
      v-on:focus="handleFocus"
    />
  </div>
</template>
<script>
import son from "./son.vue";
export default {
  name: "FatherVue",
  components: { son },
  data() {
    return {
      msg: "父组件的msg",
      foo: "Javascript",
      boo: "Html",
      coo: "CSS",
      doo: "Vue",
    };
  },
  computed: {
    count() {
      return this.$children[0] && this.$children[0].count;
    },
  },
  mounted() {
    console.log(this.$children); // [子组件1, 子组件2,......]
  },
  methods: {
    handleClick() {
      console.log("handleClick");
    },
    handleFocus() {
      console.log("handleFocus");
    },
  },
};
</script>


<!-- 子组件 son.vue -->
<template>
  <div>
    {{ msg }}
    <p>father 父组件的$attrs: {{ $attrs }}</p>
    <button @click="handleClick">click</button>
    <smallson v-bind="$attrs"></smallson>
  </div>
</template>

<script>
import smallson from "./smallson.vue";
export default {
  name: "FuSon",
  components: { smallson },
  inheritAttrs: true, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  computed: {
    msg() {
      return this.$parent.msg;
    },
  },
  data() {
    return {
      count: "我是子组件的count",
    };
  },
  methods: {
    handleClick() {
      console.log(this.$listeners);
    },
  },
};
</script>


<!-- smallson 组件 -->
<template>
  <div>
    <h1>smallson</h1>
    {{ $attrs }}
  </div>
</template>

<script>
export default {
  name: "SmallSon",
  inheritAttrs: false,
};
</script>

7.provide/inject

provide 提供变量 inject 注入变量

📢:

  1. 不论层级多深 只要调用了inject那么久可以注入provide的变量
  2. provide提供的数据在父组件中假设发生了变化 默认后辈的组件是不会响应式变化的 但是如果给的数据是this的数据的话 那么就是响应式的书
html 复制代码
<template>
  <div id="app">
    <myInject></myInject>
  </div>
</template>

<script>
import myInject from "./components/zujiantongxin/inject.vue";
export default {
  name: "App",
  provide: {
    for: "provide", 
  },
  // provide() {
  //   return {
  //     baba: this,
  //     msg: this.msg,
  //   };
  // }, 这个时候的数据就可以做到响应式的了 给的就是this的数据 给的就是响应式的数据 就可以做到响应式
  components: {
    myInject,
  },
};
</script>


<template>
  <div>
    <h2>inject 组件</h2>
    <h1>{{ for1 }}</h1>
  </div>
</template>

<script>
export default {
  name: "myInject",
  data() {
    return {
      for1: this.for,//这一步可以省略的
    };
  },
  inject: ["for"],
  mounted() {
    console.log(this.for);
  },
};
</script>

7.eventBus

EventBus 本质上就是一个vue实例对象,它可以实现兄弟组件之前的通信,首先在A组件中设置EventBus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.on自定义事件名称以及回调函数,然后B组件就是通过eventbus.emit去触发那个自定义事件,将数据传递给A组件

Eventbus的原理实际上就是发布订阅的模式

发布订阅模式 :其实就是一种对象间一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都将得到状态改变的通知

vue中常见的发布订阅就是emitemit emiton

redux中常见的就是subscribe

html 复制代码
// eventBus.js
import Vue from "vue";
export default new Vue();

<template>
  <!-- comA子组件 -->
  <div>
    <h1>{{ msg }}</h1>
  </div>
</template>
<script>
import eventBus from "./eventBus";
export default {
  name: "面试ComA",
  data() {
    return {
      msg: "",
    };
  },
  mounted() {
    eventBus.$on("message", (val) => {
      this.msg = val;
    });
  },
};
</script>


<template>
  <div>
    <button @click="sendMsg">click 点击 想 COMA 发消息</button>
  </div>
</template>
<script>
import eventBus from "./eventBus";
export default {
  name: "面试ComB",
  data() {
    return {};
  },
  methods: {
    sendMsg() {
      eventBus.$emit("message", "我是来自comB的数据");
    },
  },
};
</script>

<template>
  <div id="app">
    <comA></comA>
    <comB></comB>
  </div>
</template>

<script>
import comA from "@/components/zujiantongxin/comA.vue";
import comB from "@/components/zujiantongxin/comB.vue";
export default {
  name: "App",
  components: {
    comA,
    comB,
  },
};
</script>
相关推荐
yugi9878387 分钟前
基于Qt框架开发多功能视频播放器
开发语言·qt
whm27779 分钟前
Visual Basic 手工制作工具栏
开发语言·visual studio
睡前要喝豆奶粉13 分钟前
在.NET Core Web Api中使用JWT并配置UserContext获取用户信息
前端·.netcore
前端加油站18 分钟前
一份实用的Vue3技术栈代码评审指南
前端·vue.js
wangqiaowq3 小时前
StarRocks安装部署测试
java·开发语言
Jonathan Star7 小时前
沉浸式雨天海岸:用A-Frame打造WebXR互动场景
前端·javascript
缺点内向7 小时前
C#: 高效移动与删除Excel工作表
开发语言·c#·.net·excel
工业甲酰苯胺7 小时前
实现 json path 来评估函数式解析器的损耗
java·前端·json
老前端的功夫7 小时前
Web应用的永生之术:PWA落地与实践深度指南
java·开发语言·前端·javascript·css·node.js
LilySesy8 小时前
ABAP+WHERE字段长度不一致报错解决
java·前端·javascript·bug·sap·abap·alv