Vue3组件通信的几种方式

337 阅读3分钟

学习了Vue3也有一段时间了,打算总结一下几种组件的通信方式。 既然学的是vue3,就听官方的,用了3,就不写2了。一律setup语法糖吧。

props

很简单的一种父子组件传参的方式,由父组件定义,通过v-bind绑定子组件,子组件通过defineProps接受参数,子组件只读且无法修改参数。

<!-- 父组件 -->
<template>
    <div class="header">
      <input type="text" v-model="newMsg">
      <button @click="add">确定</button>
    </div>
  
    <Child :list="list" />
  </template>
  
  <script setup>
  const newMsg = ref('')
  const list = ref(['html', 'css'])
  
  const add = () => {
    list.value.push(newMsg.value)
  }
  </script>
  
  <!-- 子组件 -->
  const props = defineProps({
  list: {
    type: Array,
    default: () => []
  }
  
})

在上面例子中,父组件将list传递给子组件,子组件定义props使用,当然也可以直接list:Array,都可以。 那么问题来了,如果我将list放在子组件中,子组件接收父组件传来的新的list元素msg,如何去实时更新list呢?

  • computed 如果你使用computed计算属性,那么你需要考虑到最开始的空字符串,还有返回的格式,是直接返回return [...list.value, props.msg]呢?还是需要push一下再返回?
  • watch : 使用watch监听当然也是个不错的选择。
  • 生命周期🪝onBeforeUpdate 它在组件即将进行更新前被调用,请注意,组件更新前,也就是说html中的元素,所以你需要用到它才行。

emit(发布)

emit函数需要从defineEmits辅助函数中获取。defineEmits用于定义组件可以触发哪些事件以及这些事件的有效负载类型。同时可以传递参数一起发布 父组件再定义函数获取该值。

//子组件定义一个名为addMsg的事件
const emits = defineEmits(['addMsg'])
const add =() =>{
    emits('addMsg',newMsg.value)  //发布订阅
}

//父组件订阅这个事件,并且通过handle方法处理,在handle中,通过list.value.push(e)更新。
<child @addMsg="handle"/>

v-model

用于在表单输入元素(如<input>, <textarea>, <select>等)和Vue实例的数据属性之间创建双向数据绑定。这意味着当用户在表单元素中输入数据时,相应的Vue实例的属性会自动更新,反之亦然。

  • 对于<input>元素v-model实际上是v-bind:valuev-on:input的语法糖。它会监听input事件,以便在数据改变时更新数据属性。
  • 对于<textarea>元素v-model同样绑定valueinput事件。
  • 对于<select>元素v-model会根据<option>value属性来更新数据属性。
  • 对于复选框和单选按钮v-model会绑定change事件,并且对于复选框组(使用<select multiple>或一组<input type="checkbox">),v-model期望一个数组来存储选中的值。

provide / inject

provide / inject 为依赖注入

provide:可以让我们指定想要提供给后代组件的数据或

inject:在任何后代组件中接收想要添加在这个组件上的数据,不管组件嵌套多深都可以直接拿来用

//父组件
<template>
    <div class="header">
        <input type="text" v-model="newMsg">
        <button @click="add">确定</button>
    </div>
    <Child />
</template>

<script setup>
const add = () => {
    list.value.push(newMsg.value)
    newMsg.value = '' // 清空输入框
}
provide('list', list)
</script>


//子组件
<script setup>
import { ref, inject } from 'vue';
const list = inject('list')
</script>

Vuex/Pinia

这两种相比于其它的方式来说就更为便捷,但是如果你只是一个小的demo,那当我没说。 这里就不细讲了,需要我们自行去了解,传送门:Pinia/Vuex

  • 选择 Vuex:如果你正在使用 Vue 2,或者你的项目已经基于 Vuex 并且需要支持 Vue 2 和 Vue 3 的多版本兼容性,那么继续使用 Vuex 可能是最合适的选择。
  • 选择 Pinia:如果你使用的是 Vue 3,尤其是如果你的项目利用了组合式 API 的优势,那么 Pinia 将提供更现代、更简洁的状态管理方案。