vue3中的组件通信

在开发中,发现了一些常用的vue中组件通信的方法,接下来我将为大家介绍下,如有错误请及时批评指正。

通信方法

  • 父组件给子组件传值
  1. 父组件用v-bind传递数据给子组件,子组件用defineProps接收数据。
  2. 父组件通过provide传递数据,子组件通过inject注入。
  • 子组件给父组件传值
  1. 子组件用defineEmitd定义事件发布,父组件用v-on订阅事件。
  2. 子组件通过defineExpose暴露数据,父组件通过ref引用组件中的数据
  3. 父组件通过v-model,子组件通过defineProps接受,然后定义'update:xxx'事件,并修改父组件给送过来数据,但一定是要发布'update:xxx'
  • 兄弟组件通信
  1. 在外部的js文件中定义响应式变量,同时引入到两个组件中,因为是响应式的,所以两个组件都可以修改这给变量,从而实现通信。

组件通信的写法

父传子

我们要写一个输入框和一个点击按钮,点击按钮后,会将输入框中的内容添加到数组,放入子组件中展示。

  1. 通过在父组件中通过属性绑定v-bind将数据传递给子组件,子组件通过defineProps声明Props来接受数据。
js 复制代码
<template>

  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>

  <Child :data="data" />

</template>

<script setup>
import Child from './child.vue'
import { ref } from 'vue'
const msg = ref('')
const data = ref('')//这里定义一个data,来保证传入的数据在点击添加才会改变,不被msg的值的改变影响
const add = () => {
  data.value = msg.value
}
</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <div class="body">
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'

const props = defineProps({
  data: {
    type: String,
    default: ''
  }
})

const list = ref(['html', 'css', 'js'])

watch(() => props.data, (newVal) => { //监听如果传入的数据有改变,添加进入数组
  if (newVal) {
    list.value.push(newVal)
  }
})

</script>

<style lang="css" scoped></style>

这种写法并不是很好,将数据放在子组件中储存,会导致子组件的复用性降低,比如写一个展示数据的组件,放在主页能用,放到展示其他数据的页面就不行了。最好是将数据放在父组件中,子组件只发出更改的请求。可以根据项目需求使用,需要重复用的子组件最好别这样写。

  1. 父组件通过provide数据,子组件通过inject接收父组件传来的数据。provide有穿透的效果,在子组件的子组件中也能收到父组件传来的值。用readonly冻结数据,防止在子组件中修改。
js 复制代码
<template>

  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>

  <Child />

</template>

<script setup>
import Child from './child.vue'
import { ref, provide, readonly } from 'vue'

const msg = ref('')
const list = ref(['html', 'css', 'js'])
const add = () => {
  list.value.push(msg.value)
  console.log(list.value);
}

provide('list', readonly(list.value))  // 向下提供数据,用readonly防止子组件被修改

</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <div class="body">
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import { inject } from 'vue'

const list = inject('list')  // 注入数据

</script>

<style lang="css" scoped></style>

子传父

  1. 子组件用defineEmitd 定义事件并发布,父组件用v-on订阅事件。在子组件中发布事件,在父组件中接受数据。
js 复制代码
<template>
  <Child @add="handle" />//这里定义了函数,来接受子组件的add事件(子组件发布的事件)

  <div class="body">
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import Child from './child.vue'
import { ref } from 'vue'

const list = ref(['html', 'css', 'js'])
const handle = (val) => {
  list.value.push(val)
}
</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const msg = ref('')

const emit = defineEmits(['add'])  // 定义事件
const add = () => {
  emit('add', msg.value)
}
</script>

<style lang="css" scoped></style>
  1. 子组件通过defineExpose暴露数据,父组件通过ref引用组件中的数据.子组件将数据放到全局,让所有组件都可以拿到。
js 复制代码
<template>
  <Child ref="childRef" />

  <div class="body">
    <ul>
      <li v-for="(item, index) in childRef?.list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import Child from './child.vue'
import { ref } from 'vue'

const childRef = ref(null)

setTimeout(() => {
  console.log(childRef.value.list)
}, 1000)

</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const msg = ref('')
const list = ref(['html', 'css', 'js'])
const add = () => {
  list.value.push(msg.value)
}

// 暴露数据
defineExpose({
  list
})
</script>

<style lang="css" scoped></style>
  1. 父组件通过v-model,子组件通过defineProps接受,然后定义'update:xxx'事件,并修改父组件给送过来数据,但一定是要发布'update:xxx'。其实是一个语法糖,defineProps在子组件接受父组件的数据,修改好了后,用defineEmits传回给父组件,完成通信。
js 复制代码
<Child v-model:list="list" />//等于下面的写法
<Child v-bind:list="list" @update:title="pageTitle = $event"/>//v-bind用于接受父组件传来的数据,@updata在数据改变这个事件后,把数据从子组件传回给父组件。
js 复制代码
<template>
  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const msg = ref('')
const props = defineProps(['list'])

const emits = defineEmits(['update:list'])
const add = () => {
  const arr = props.list
  arr.push(msg.value)

  emits('update:list', arr)
}

</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <Child v-model:list="list" />

  <div class="body">
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import Child from './child.vue'
import { ref } from 'vue'

const list = ref(['html', 'css', 'js'])

</script>

<style lang="css" scoped></style>

兄弟通信

在外部的js文件中定义响应式变量,同时引入到两个组件中,因为是响应式的,所以两个组件都可以修改这个变量,从而实现通信。其实用Pinian这种工具也行。

js 复制代码
<template>
  <div class="body">
    <ul>
      <li v-for="(item, index) in list" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import { list } from './bus.js'



</script>

<style lang="css" scoped></style>
js 复制代码
<template>
  <div class="head">
    <input type="text" v-model="msg">
    <button @click="add">添加</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { list } from './bus.js'

const msg = ref('')
const add = () => {
  list.value.push(msg.value)
}

</script>

<style lang="css" scoped></style>
js 复制代码
<template>

  <Head />

  <Body />
</template>

<script setup>
import Head from './head.vue';
import Body from './body.vue';
</script>

<style lang="css" scoped></style>

js文件

js 复制代码
import { ref } from 'vue'

export const list = ref(['html', 'css', 'js'])
相关推荐
野生的程序媛1 小时前
重生之我在学Vue--第13天 Vue 3 单元测试实战指南
前端·javascript·vue.js·单元测试
褪色的笔记簿2 小时前
Vue 2 中动态新增属性丢失响应性原因探究
vue.js
褪色的笔记簿3 小时前
探索 Vue.js 中 El-Form 的 resetFields 方法重置数据
vue.js
Jazzing4 小时前
Vue 3 Diff 算法中的 newIndexToOldIndexMap 详解
vue.js
Jazzing4 小时前
Vue 3 Diff 算法中的 getSequence 源码解析
vue.js
miffycat4 小时前
Element UI ColorPicker 实时更新绑定值并转换 Hex 颜色的完整方案
vue.js
Three~stone5 小时前
Vue学习笔记集--scoped组件
vue.js·笔记·学习
zheshiyangyang5 小时前
Flask+Vue-Router+JWT实现登录验证
vue.js·python·flask