Vue3 component communication method 1

Table of contents

props

Pass data from parent component to child component

The child component obtains the data passed by the parent component: method 1 

The child component obtains the data passed by the parent component: method 2 

the case

custom event

native DOM events

custom event

the case

global event bus

v-model

useAttrs


Whether it is vue2 or vue3, the communication method of components is very important, whether it is a project or an interview, it is a knowledge point that is often used.

For example: vue2 component communication method

  • **props:** can realize communication between parent-child components, child-parent components, and even sibling components
  • Custom events : communication between child and parent components can be achieved
  • Global event bus $bus : can realize arbitrary component communication
  • **pubsub:** publish and subscribe mode to realize arbitrary component communication
  • vuex : Centralized state management container, enabling arbitrary component communication
  • ref : The parent component obtains the child component instance VC, and obtains the responsive data and methods of the child component
  • **slot:**Slots (default slots, named slots, scoped slots) realize parent-child component communication........

props

Subcomponents can be used in the template after obtaining the props data, but remember that props are read-only (can only be read, cannot be modified)

Pass data from parent component to child component

<Child info="我爱祖国" :money="money"></Child>

The child component obtains the data passed by the parent component: method 1 

let props = defineProps({
  info:{
   type:String,//接受的数据类型
   default:'默认参数',//接受默认数据
  },
  money:{
   type:Number,
   default:0
}})

The child component obtains the data passed by the parent component: method 2 

let props = defineProps(["info",'money']);

the case

parent component

<template>
  <div class="box">
    <h1>props:我是父组件曹操</h1>
    <hr />
    <Child info="我是曹操" :money="money"></Child>
  </div>
</template>

<script setup lang="ts">
//props:可以实现父子组件通信,props数据还是只读的!!!
import Child from "./Child.vue";
import { ref } from "vue";
let money = ref(10000);
</script>

<style scoped>
.box {
  width: 100vw;
  height: 400px;
  background: yellowgreen;
}
</style>

props can realize parent-child component communication. In vue3, we can get the data passed by the parent component through defineProps. And there is no need to introduce the defineProps method inside the component and it can be used directly!

Subassembly

<template>
  <div class="son">
       <h1>我是子组件:曹植</h1>
       <p>{
   
   {props.info}}</p>
       <p>{
   
   {props.money}}</p>
      <!--props可以省略前面的名字--->
       <p>{
   
   {info}}</p>
       <p>{
   
   {money}}</p>
       <button @click="updateProps">修改props数据</button>
  </div>
</template>

<script setup lang="ts">
//需要使用到defineProps方法去接受父组件传递过来的数据
//defineProps是Vue3提供方法,不需要引入直接使用
let props = defineProps(['info','money']); //数组|对象写法都可以
//按钮点击的回调
const updateProps = ()=>{
  // props.money+=10;  props:只读的
  console.log(props.info)
}
</script>

<style scoped>
.son{
  width: 400px;
  height: 200px;
  background: hotpink;
}
</style>

custom event

There are two types of events in the Vue framework: one is a native DOM event, and the other is a custom event.

  • Native DOM events allow users to interact with web pages, such as click, dbclick, change, mouseenter, mouseleave...
  • Custom events can implement child components to pass data to parent components

native DOM events

code show as below:

<pre @click="handler"> 我是祖国的老花骨朵 </pre>

At the current code level, the native DOM event click event is bound to the pre tag, and the event event object is injected into the event callback by default. Of course, if you want to inject multiple parameters into the click event, you can operate as shown in the figure below. But remember that the injected event object must be called $event.

  <div @click="handler1(1,2,3,$event)">我要传递多个参数</div>

In the vue3 framework, click, dbclick, and change (such native DOM events), whether on tags or custom tags (component tags), are native DOM events.

custom event

Custom events can implement child components to pass data to parent components. It is more commonly used in projects.

For example, bind a custom event to the child component (Event2) inside the parent component

<Event2  @xxx="handler3"></Event2>

Trigger this custom event inside the Event2 subcomponent

<template>
  <div>
    <h1>我是子组件2</h1>
    <button @click="handler">点击我触发xxx自定义事件</button>
  </div>
</template>

<script setup lang="ts">
let $emit = defineEmits(["xxx"]);
const handler = () => {
  $emit("xxx", "法拉利", "茅台");
};
</script>
<style scoped>
</style>

We will find that inside the script tag, the defineEmits method is used. This method is provided by vue3 and does not need to be introduced and used directly. The defineEmits method is executed, and an array is passed. The array elements are the types of custom events that the component needs to trigger in the future. This method will return a $emit method to trigger custom events.

When the button is clicked, the event callback internally calls the $emit method to trigger the custom event. The first parameter is the trigger event type, and the second, third, and N parameters are the data passed to the parent component.

Note: the code is as follows

<Event2  @xxx="handler3" @click="handler"></Event2>

Normally, component label writing @click should be a native DOM event, but if the subcomponent is defined internally through defineEmits, it becomes a custom event

let $emit = defineEmits(["xxx",'click']);

the case

parent component

Native DOM events allow users to interact with web pages, such as click, dbclick, change, mouseenter, mouseleave...

<template>
  <div>
    <h1>事件</h1>
    <!-- 原生DOM事件 -->
    <pre @click="handler">
      大江东去浪淘尽,千古分流人物
    </pre>
    <button @click="handler1(1,2,3,$event)">点击我传递多个参数</button>
    <hr>
    <!--
        vue2框架当中:这种写法自定义事件,可以通过.native修饰符变为原生DOM事件
        vue3框架下面写法其实即为原生DOM事件

        vue3:原生的DOM事件不管是放在标签身上、组件标签身上都是原生DOM事件
      -->
    <Event1 @click="handler2"></Event1>
    <hr>
    <!-- 绑定自定义事件xxx:实现子组件给父组件传递数据 -->
    <Event2 @xxx="handler3" @click="handler4"></Event2>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Event1 from './Event1.vue';
//引入子组件
import Event2 from './Event2.vue';
//事件回调--1
const handler = (event)=>{
    //event即为事件对象
    console.log(event);
}
//事件回调--2
const handler1 = (a,b,c,$event)=>{
   console.log(a,b,c,$event)
}
//事件回调---3
const handler2 = ()=>{
    console.log(123);
}
//事件回调---4
const handler3 = (param1,param2)=>{
    console.log(param1,param2);
}
//事件回调--5
const handler4 = (param1,param2)=>{
     console.log(param1,param2);
}
</script>

<style scoped>
</style>

subcomponent one

  •         Vue3: Native DOM events are native DOM events whether they are placed on tags or component tags
  •         In the vue2 framework: this custom event can be changed into a native DOM event through the .native modifier
  •         Bind to the root node of the child component
<template>
  <div class="son">
      <p>我是子组件1</p>
      <button>点击我也执行</button>
  </div>
</template>

<script setup lang="ts">

</script>

<style scoped>
.son{
  width: 400px;
  height: 200px;
  background: skyblue;
}
</style>

Subcomponent 2

  • // Use the defineEmits method to return a function to trigger a custom event
  •  //The first parameter: event type The second | three | N parameters are the injected data
  • //defineEmits method does not need to be introduced and used directly
  • Normally, component label writing @click should be a native DOM event, but if the subcomponent is defined internally through defineEmits, it becomes a custom event
<template>
  <div class="child">
    <p>我是子组件2</p>
    <button @click="handler">点击我触发自定义事件xxx</button>
    <button @click="$emit('click','AK47','J20')">点击我触发自定义事件click</button>
  </div>
</template>

<script setup lang="ts">
//利用defineEmits方法返回函数触发自定义事件
//defineEmits方法不需要引入直接使用
let $emit = defineEmits(['xxx','click']);
//按钮点击回调
const handler = () => {
  //第一个参数:事件类型 第二个|三个|N参数即为注入数据
    $emit('xxx','东风导弹','航母');
};
</script>

<style scoped>
.child {
  width: 400px;
  height: 200px;
  background: pink;
}
</style>

global event bus

The global event bus can realize any component communication. In vue2, the global event bus can be launched according to the relationship between VM and VC.

But there is no Vue constructor in vue3, so there is no Vue.prototype. And there is no this in the combined API writing method,

Then it is a bit unrealistic to implement the bus function of global events in Vue3. If you want to use the global event bus function in Vue3

This can be achieved using the plugin mitt.

mitt: official website address: mitt - npm

 Introduce the mitt plug-in: mitt is a method, and the method execution will return the bus object

Case ------------------

export mitt

Introduce the mitt plug-in: mitt is a method, and the method execution will return the bus object

//引入mitt插件:mitt一个方法,方法执行会返回bus对象
import mitt from 'mitt';
const $bus = mitt();
export default $bus;

parent component

<template>
  <div class="box">
    <h1>全局事件总线$bus</h1>
    <hr />
    <div class="container">
      <Child1></Child1>
      <Child2></Child2>
    </div>
  </div>
</template>

<script setup lang="ts">
//引入子组件
import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";
</script>

<style scoped>
.box {
  width: 100vw;
  height: 400px;
  background: yellowgreen;
}
.container{
  display: flex;
  justify-content: space-between;
}
</style>

Subcomponent 1: Subscribe to Messages 

//When the component is mounted, the current component binds an event and accepts the data passed by the sibling components in the future

 //The first parameter: the event type The second parameter: the event callback

<template>
  <div class="child1">
    <h3>我是子组件1:曹植</h3>
  </div>
</template>

<script setup lang="ts">
import $bus from "../../bus";
//组合式API函数
import { onMounted } from "vue";
//组件挂载完毕的时候,当前组件绑定一个事件,接受将来兄弟组件传递的数据
onMounted(() => {
  //第一个参数:即为事件类型  第二个参数:即为事件回调
  $bus.on("car", (car) => {
    console.log(car);
  });
});
</script>

<style scoped>
.child1 {
  width: 300px;
  height: 300px;
  background: hotpink;
}
</style>

Subcomponent 2 publishes a message

<template>
  <div class="child2">
     <h2>我是子组件2:曹丕</h2>
     <button @click="handler">点击我给兄弟送一台法拉利</button>
  </div>
</template>

<script setup lang="ts">
//引入$bus对象
import $bus from '../../bus';
//点击按钮回调
const handler = ()=>{
  $bus.emit('car',{car:"法拉利"});
}
</script>

<style scoped>
.child2{
  width: 300px;
  height: 300px;
  background: skyblue;
}
</style>

v-model

The v-model command can collect form data (data two-way binding), and it can also realize parent-child component data synchronization.

And v-model actually refers to the realization of using props[modelValue] and custom event [update:modelValue].

The code below: is equivalent to passing a props (modelValue) to the component Child and binding a custom event update:modelValue

Realize parent-child component data synchronization

<Child v-model="msg"></Child>

In vue3, a component can use multiple v-models to synchronize multiple data between parent and child components. The code below is equivalent to passing two props to the component Child, namely pageNo and pageSize, and binding two custom events update:pageNo Synchronize parent-child data with update:pageSize

<Child v-model:pageNo="msg" v-model:pageSize="msg1"></Child>

Case ----------------

parent component

The v-model command can collect form data (data two-way binding), and it can also realize parent-child component data synchronization.

<template>
  <div>
    <h1>v-model:钱数{
   
   { money }}</h1>
    <h1>pageNo:{
   
   { pageNo }}</h1>
    <h1>pageSize:{
   
   { pageSize }}</h1>
    <input type="text" v-model="info" />
    <hr />
    <!-- props:父亲给儿子数据 -->
    <Child :modelValue="money" @update:modelValue="handler"></Child>
    <!-- 
       v-model组件身上使用
       第一:相当有给子组件传递props[modelValue] = 10000
       第二:相当于给子组件绑定自定义事件update:modelValue
     -->
    <Child v-model="money"></Child>
    <hr />
    <Child1 v-model:pageNo="pageNo" v-model:pageSize="pageSize"></Child1>
  </div>
</template>

<script setup lang="ts">
//v-model指令:收集表单数据,数据双向绑定
//v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
//父亲给子组件数据 props
//子组件给父组件数据 自定义事件
//引入子组件
import Child from "./Child.vue";
import Child1 from "./Child1.vue";
import { ref } from "vue";
let info = ref("");
//父组件的数据钱数
let money = ref(10000);
//自定义事件的回调
const handler = (num) => {
  //将来接受子组件传递过来的数据
  money.value = num;
};

//父亲的数据
let pageNo = ref(1);
let pageSize = ref(3);
</script>

<style scoped>
</style>

subcomponent one

  • Parent to child: child components pass props to parent components
  • Passing from child to parent: child components bind custom events to trigger parent-child events
<template>
  <div class="child">
    <h3>钱数:{
   
   { modelValue }}</h3>
    <button @click="handler">父子组件数据同步</button>
  </div>
</template>

<script setup lang="ts">
//接受props
let props = defineProps(["modelValue"]);
let $emit = defineEmits(['update:modelValue']);
//子组件内部按钮的点击回调
const handler = ()=>{
   //触发自定义事件
   $emit('update:modelValue',props.modelValue+1000);
}
</script>

<style scoped>
.child {
  width: 600px;
  height: 300px;
  background: skyblue;
}
</style>

Subcomponent 2

 Use on the v-model component

  •        First: It is quite necessary to pass props[modelValue] = 10000 to the child component
  •        Second: It is equivalent to binding a custom event update:modelValue to a subcomponent
  •        Can bind multiple
<template>
  <div class="child2">
    <h1>同时绑定多个v-model</h1>
    <button @click="handler">pageNo{
   
   { pageNo }}</button>
    <button @click="$emit('update:pageSize', pageSize + 4)">
      pageSize{
   
   { pageSize }}
    </button>
  </div>
</template>

<script setup lang="ts">
let props = defineProps(["pageNo", "pageSize"]);
let $emit = defineEmits(["update:pageNo", "update:pageSize"]);
//第一个按钮的事件回调
const handler = () => {
  $emit("update:pageNo", props.pageNo + 3);
};
</script>

<style scoped>
.child2 {
  width: 300px;
  height: 300px;
  background: hotpink;
}
</style>

useAttrs

In Vue3, you can use the useAttrs method to get the attributes and events of the component (including: native DOM events or custom events), and the function of this function is similar to the $attrs attribute and $listeners method in the Vue2 framework.

For example: use a child component my-button inside the parent component

<my-button type="success" size="small" title='标题' @click="handler"></my-button>

Component attributes and events can be obtained through the useAttrs method inside the child component. So you also found that it is similar to props and can accept attributes and attribute values ​​​​passed by the parent component. It should be noted that if defineProps accepts a certain attribute, the object returned by the useAttrs method will not have the corresponding attribute and attribute value.

<script setup lang="ts">
import {useAttrs} from 'vue';
let $attrs = useAttrs();
</script>

parent component

<template>
  <div>
    <h1>useAttrs</h1>
    <el-button type="primary" size="small" :icon="Edit"></el-button>
    <!-- 自定义组件 -->
    <HintButton type="primary" size="small" :icon="Edit" title="编辑按钮" @click="handler" @xxx="handler"></HintButton>
  </div>
</template>

<script setup lang="ts">
//vue3框架提供一个方法useAttrs方法,它可以获取组件身上的属性与事件!!!
//图标组件
import {
  Check,
  Delete,
  Edit,
  Message,
  Search,
  Star,
} from "@element-plus/icons-vue";
import HintButton from "./HintButton.vue";
//按钮点击的回调
const handler = ()=>{
  alert(12306);
}
</script>

<style scoped>
</style>

Subassembly

//both the props and useAttrs methods can get the attributes and attribute values ​​​​passed by the parent component

//But props can't get it after accepting the useAttrs method

<template>
  <div :title="title">
     <el-button :="$attrs"></el-button>   
  </div>
</template>

<script setup lang="ts">
//引入useAttrs方法:获取组件标签身上属性与事件
import {useAttrs} from 'vue';
//此方法执行会返回一个对象
let $attrs = useAttrs();

//万一用props接受title
let props =defineProps(['title']);
//props与useAttrs方法都可以获取父组件传递过来的属性与属性值
//但是props接受了useAttrs方法就获取不到了
console.log($attrs);
</script>

<style scoped>
</style>

Guess you like

Origin blog.csdn.net/qq_63358859/article/details/131188703