首页  >  文章  >  web前端  >  vue3组件间怎么通信?通信方式浅析

vue3组件间怎么通信?通信方式浅析

青灯夜游
青灯夜游转载
2023-04-21 19:53:461616浏览

在我们写 vue3 的项目中,我们都会进行组件通信,我们除了使用 pinia 公共数据源的方式除外,我们还可采用那些更简单的API方法呢?那下面我就来给大家介绍介绍几种父子组件和子父组件通信的方式。

vue3组件间怎么通信?通信方式浅析

1、父子组件通信

1.1 defineProps

父子组件通信我们第一个想到的就是props,我们在子组件显示声明所接受的props,然后我们在从父组件传入对应的 key与value, 这样我们就可以在子组件上接收到父组件传过来的属性与值。【相关推荐:vuejs视频教程web前端开发

具体实现如下:

// children.vue
<template>
  <ul class="list-group">
      <li class="list-group-item" v-for="item in list" :key="index">
        {{item}}
      </li>

  </ul>
</template>

<script setup>
import { defineProps } from &#39;vue&#39;;
const props = defineProps({
    list :{
        type: Array,
        default: () => {}
    }
})
</script>
// parent.vue
<template>
  <div class="parent-wrap">
      <input type="text" v-model="value" class="form-control" placeholder="请输入">
      <div class="input-group-append">
          <button class="btn btn-primary" @click="handleAdd">添加</button>
      </div>
  </div>
  <!-- child -->
  <childrenVue :list="list"></childrenVue>
</template>
<script setup>
import { ref } from &#39;vue&#39;;
import childrenVue from &#39;./children.vue&#39;;
const value = ref(&#39;&#39;)
const list = ref([&#39;javaScript&#39;, &#39;Html&#39;, &#39;CSS&#39;])
const handleAdd = () =>{
    list.value.push(value.value)
    value = &#39;&#39;
}
</script>

图片.png

如上图所示,我们既实现了在子组件上显示了父组件传过来的 list 数组,还使可以向list添加数据使子组件数据更新。

1.2 provide/inject

当我们聊完了props,我们第二个要介绍的就是 vue3 的一个组合式选项 provide 和inject。

projct用于提供可以被后代组件注入的值,而inject用于声明要通过从上层提供方匹配并注入进当前组件的属性。 其代码实现如下:

// children.vue
<template>
    <ul class="list-group">
        <li class="list-group-item" v-for="item in list" :key="item">{{item}}</li>
    </ul>
</template>
<script setup>
import { inject } from &#39;vue&#39;;
const list = inject(&#39;list&#39;)
</script>
// parent.vue
<template>
    <div class="parent-wrap">
        <input type="text" v-model="value" class="form-control" placeholder="请输入">
        <div class="input-group-append">
            <button class="btn btn-primary" @click="handleAdd">添加</button>
        </div>
    </div>
    <!-- child -->
    <childVue />
</template>
<script setup>
import childVue from "./child.vue";
const { ref, provide, readonly } = require("vue");
const value = ref(&#39;&#39;)
const list = ref([&#39;javaScript&#39;, &#39;HTML&#39;, &#39;CSS&#39;])
provide(&#39;list&#39;, readonly(list.value))
const handleAdd = () => {
list.value.push(value.value)
}
</script>

图片.png

如上图所示,我们使用 provide API向外提供了一个 key 为 list,值为list.value,同时将 list,value 设置成了只读属性,防止子组件修改父组件的数据源。然后我们 injectAPI接收了 list,实现了父子组件的通信。

2.子父组件通信

2.1 defineEmits

上面我介绍了两种父向子传值的方法,但在我们开发中,我们还会遇到子向父组件传值的情况,那我们该怎么解决呢? 第一个方法就是vue3中的 defineEmits API,代码实现如下:

// children.vue
<template>
    <div class="parent-wrap">
        <input type="text" v-model="value" class="form-control" placeholder="请输入" />
        <div class="input-group-append">
            <button class="btn btn-primary" @click="handleAdd">添加</button>
        </div>
    </div>
</template>
<script setup>
const { ref, defineEmits } = require("vue");
const value = ref(&#39;&#39;)
const emits = defineEmits([&#39;add&#39;]) //父传子

  // 给父组件传一个函数
const handleAdd = () => {
    emits(&#39;add&#39;, value.value)
    value.value= &#39;&#39;
}
</script>
// parent.vue
<template>  
    <childVue @add=&#39;handleAdd&#39;/>
    <ul class="list-group">
        <li class="list-group-item" v-for="item in list" :key="item">{{item}}</li>
    </ul>
</template>
<script setup>
import { ref } from &#39;@vue/reactivity&#39;;
import childVue from &#39;./child.vue&#39;;
const list = ref([&#39;javaScript&#39;, &#39;HTML&#39;, &#39;CSS&#39;])
const handleAdd = (val) => {
    list.value.push(val)
}
</script>

图片.png

如上图所示,我们在子组件上emit一个出了一个 add事件给父组件接收,同时在父组件上调用来执行添加的逻辑,再将 inputvalue变为空,实现了父组件向子组件传参。

2.2 v-model:xxx + emit

在介绍完 defineEmits后, 我们再来介绍一种与其有异曲同工之处的v-model:xxx + emit的方法,实现如下:

// children.vue
<template>
    <div class="parent-wrap">
        <input type="text" v-model="value" class="form-control" placeholder="请输入" />
        <div class="input-group-append">
            <button class="btn btn-primary" @click="handleAdd">添加</button>
        </div>
    </div>
</template>
<script setup>
const { ref, defineProps, defineEmits } = require("vue");
const value = ref(&#39;&#39;)
const props = defineProps({
    list: {
        type: Array,
        default: () => []
    }
})
const emits = defineEmits([&#39;list&#39;])
  // 给父组件一点东西
const handleAdd = () => {
    // props.list.push(value.value)  //不建议直接修改props的值 把握不住数据源的流转
    const arr = props.list
    arr.push(value.value)
    emits(&#39;list&#39;, arr)
    value.value= &#39;&#39;
}

</script>
<template>  
    <childVue v-model:list="list" @list =&#39;add&#39;/>
    <ul class="list-group">
        <li class="list-group-item" v-for="item in list" :key="item">{{item}}</li>
    </ul>
</template>
<script setup>
import { ref } from &#39;@vue/reactivity&#39;;
import childVue from &#39;./child.vue&#39;;
const list = ref([&#39;javaScript&#39;, &#39;HTML&#39;, &#39;CSS&#39;])
const add =(val) => {
    console.log(val);
    console.log(list);
}
</script>

图片.png

再和上面的defineEmits方法比较完以后,相信大家也看出了这两者的异曲同工在哪了。我们这里是先将父组件的list传给了子组件,再在子组件修改了父组件的数据源,同时再emit还给父组件,实现了子组件向父组件传值。

(学习视频分享:vuejs入门教程编程基础视频

以上是vue3组件间怎么通信?通信方式浅析的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:juejin.cn。如有侵权,请联系admin@php.cn删除