前言
我们知道vue框架构造的是一个单页面,它不同于传统方法有很多html文件,只有一个html文件,vue文件被挂载到唯一的html中。vue通讯可以在不同vue组件中传递数据,今天就让我们聊一聊vue的组件通讯。
父子通讯
1.父子组件通讯 --- 父组件将值v-bind绑定传给子组件,子组件使用defineProps接受
父组件:
<template>
<div class="input-group">
<input type="text" v-model="value">
<button @click="add">添加</button>
</div>
<Child :msg="toChild"></Child>
</template>
<script setup>
import Child from '@/components/child.vue'
import { ref } from 'vue'
const value = ref('')
const toChild = ref('')
const add = () => {
toChild.value = value.value
}
</script>
<style lang="css" scoped>
</style>
输入框中v-model="value"将value值双向绑定(根据表单输入元素或组件输出的值而变化)
添加按钮上添加了add点击事件.
第7行将子组件引入,并将msg通过v-bind传给子组件,toChild是一个变量
子组件
<template>
<div class="child">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
const list = ref(['html', 'css', 'js'])
const props = defineProps({
msg: ''
})
watch(
() => props.msg,
(newVal, oldVal) => {
list.value.push(newVal)
}
)
</script>
<style lang="css" scoped></style>
子组件从vue引入ref和watch,分别用于响应和监听。 定义响应式list数组.
defineProps函数定义了一个叫msg的属性接收父组件的传值,可为任何类型
watch()函数里有两个回调函数,第一个是要监听的目标,第二个表示当目标的值发生变化,将newval放到list数组中
v-for可以遍历数组长度,只要数组中还有值就会生成一个list并将item放入li
效果:
当输入框输入值并点击添加时
子父通讯
方法一:借助发布订阅机制,子组件负责发布事件并携带参数,父组件订阅该事件通过事件参数获取子组价提供的值
父组件:
<template>
<!-- 订阅add1事件 -->
<Child @add1="handle"></Child>
<div class="child">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import Child from '@/components/child2.vue'
import { ref } from 'vue'
const list = ref(['html', 'css', 'js'])
const handle = (event) => {
list.value.push(event)
}
</script>
<style lang="css" scoped>
</style>
父组件引入子组件并绑定一个事件add1,add1发生就会执行handle函数
定义一个响应式数组list
handle函数将从子组件传来的值放入数组
子组件:
<template>
<div class="input-group">
<input type="text" v-model="value">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const value = ref('')
const emits = defineEmits(['add1']) // 创建一个add1事件
const add = () => {
// 将value给到父组件
emits('add1', value.value) // 发布事件
}
</script>
<style lang="css" scoped>
</style>
输入框中v-model="value"将value值双向绑定(根据表单输入元素或组件输出的值而变化)
添加按钮上添加了add点击事件,add可以发布事件
第12行我们创建了一个add1事件,当添加按钮被点击时触发add函数,将add1事件发布,并将value值给到父组件
方法二:父组件借助v-model将数据绑定给子组件,子组件创建'update:xxx'事件,并接收到的数据修改后emits出来
父组件:
<template>
<Child v-model:list="list"></Child>
<div class="child">
<ul>
<li v-for="item in list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import Child from '@/components/child3.vue'
import { ref } from 'vue'
const list = ref(['html', 'css', 'js'])
</script>
<style lang="css" scoped>
</style>
父组件引入子组件,定义了一个数组list,v-model:list将数据绑定给子组件
子组件:
<template>
<div class="input-group">
<input type="text" v-model="value">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref, defineProps } from 'vue';
const value = ref('')
const props = defineProps({
list: {
type: Array,
default: () => []
}
})
const emits = defineEmits(['update:list'])
const add = () => {
// props.list.push(value.value) // 不建议直接操作父组件给过来的数据,会污染数据
const arr = props.list
arr.push(value.value)
emits('update:list', arr)
}
</script>
<style lang="css" scoped></style>
defineProps定义了接收数据的类型及默认是空数组
defineEmits定义了一个事件update:list,当点击按钮触发add,会将update:list事件发布出去
23到25行不直接修改父组件的数据而是新new了一个数组arr,将数组arr给父组件。
方法三:父组件通过ref获取子组件中defineExpose() 暴露出来的数据
父组件:
<template>
<Child ref="childRef"></Child>
<div class="child">
<ul>
<li v-for="item in childRef?.list">{{ item }}</li>
</ul>
</div>
</template>
<script setup>
import Child from '@/components/child4.vue'
import { ref, onMounted } from 'vue'
const childRef = ref(null)
</script>
<style lang="css" scoped>
</style>
父组件引入子组件,ref="childRef"可以让父组件访问到子组件。
v-for="item in childRef?.list"当childRef有不为空时访问list数组,以防还没拿到数据就编译这行代码导致错误。
子组件:
<template>
<div class="input-group">
<input type="text" v-model="value">
<button @click="add">添加</button>
</div>
</template>
<script setup>
import { ref, defineProps } from 'vue';
const value = ref('')
const list = ref(['html', 'css', 'js'])
const add = () => {
list.value.push(value.value)
}
defineExpose({ list:list }) // 心甘情愿暴露出来list
</script>
<style lang="css" scoped></style>
这种方法只需将子组件input框的值放入数组中,任何将list数组暴露出来就行了
defineExpose({ list:list })可以将list暴露给父组件
总结
今天我们聊了不同组件之间的通讯,希望对你们有帮助,可以的画帮忙点个赞。好好学习,天天向上!