提示:vue组件传值学习用vue3语法
提示:以下是本篇文章正文内容,下面案例可供参考
1.在父组件中引入子组件并通过components
注册
父组件内容示例:
html 内容
<template>
<div class="home">
父组件
<child :msg="msg">child>
div>
template>
js 内容
import child from "../components/Child/Child";
<script>
import { defineComponent, ref, computed } from "vue";
import child from "../components/Child/Child";
import { useRouter } from "vue-router";
export default defineComponent({
name: "About",
components: {
child,
},
setup(props, ctx) {
let msg = ref("这是父组件的值");
let send = (value) => {
console.log(value);
};
return {
msg,
send,
};
},
});
</script>
子组件内容示例
html 内容
<template>
<div class="">
这是子组件 父组件传地的值 {{ msg }}
div>
template>
js 内容
props: { msg: { type: String, default: "", }, },;
<script>
import { defineComponent, ref, computed, onMounted } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
name: "child",
props: {
msg: {
type: String,
default: "",
},
},
});
</script>
子组件内容示例
html 内容
<template>
<div class="">
<button @click="send">子组件传给父组件button>
div>
template>
js 内容
setup(props, ctx)
ctx.emit("send", [childMsg.value, childNum.value]);
<script>
import { defineComponent, ref, computed, onMounted } from "vue";
import { useRouter } from "vue-router";
export default defineComponent({
name: "child",
props: {
msg: {
type: String,
default: "",
},
},
setup(props, ctx) {
console.log(props.msg);
let childMsg = ref("这是子组件传递给父组件");
let childNum = ref(10);
// 子组件 传父组件
let send = () => {
// 通过 ctx.emit 分发事件
// emit 第一个参数是事件名称 第二个参数是传递数据
// 传参方式
// 数组形式 对象像是
ctx.emit("send", [childMsg.value, childNum.value]);
// ctx.emit("send",{
// msg:childMsg.value,
// num:childNum.value
// })
};
onMounted(() => {
// ctx.emit("send",[childMsg.value,childNum.value])
ctx.emit("send", {
msg: childMsg.value,
num: childNum.value,
});
});
return {
childMsg,
childNum,
send,
};
},
});
</script>
父组件内容示例:
html 内容
@send="send"
<template>
<div class="home">
父组件
<child @send="send">child>
div>
template>
js 内容
import child from "../components/Child/Child";
<script>
import { defineComponent, ref, computed } from "vue";
import child from "../components/Child/Child";
import { useRouter } from "vue-router";
export default defineComponent({
name: "About",
components: {
child,
},
setup(props, ctx) {
let send = (value) => {
console.log(value); //子组件传的值
};
return {
send,
};
},
});
</script>
子组件可以通过 expose 暴露自身的方法和数据。
父组件通过 ref 获取到子组件并调用其方法或访问数据。
<template>
<div>父组件:拿到子组件的message数据:{{ msg }}div>
<button @click="childFun">调用子组件的方法button>
<hr />
<Child ref="childRef" />
template>
<!-- Parent.vue -->
<script setup>
import { ref, onMounted } from "vue";
import Child from "@/components/Child.vue";
const childRef = ref(null); // 通过 模板ref 绑定子组件
const msg = ref("");
onMounted(() => {
// 在加载完成后,将子组件的 message 赋值给 msg
msg.value = childRef.value.message;
});
function childFun() {
// 调用子组件的 changeMessage 方法
childRef.value.changeMessage("前端诡刺");
// 重新将 子组件的message 赋值给 msg
msg.value = childRef.value.message;
}
</script>
<template>
<div>子组件:{{ message }}div>
template>
<!-- Parent.vue -->
<script setup>
import { ref } from "vue";
const message = ref("前端菜鸟");
function changeMessage(data) {
message.value = data;
}
//使用 defineExpose 向外暴露指定的数据和方法
defineExpose({
message,
changeMessage,
});
</script>
可以支持多个数据双向绑定
父组件
<template>
<Child v-model:msg1="message1" v-model:msg2="message2" />
template>
<!-- Parent.vue -->
<script setup>
import { ref } from "vue";
import Child from "@/components/Child.vue";
const message1 = ref("前端菜鸟1");
const message2 = ref("前端菜鸟2");
</script>
子组件
<template>
<div><button @click="changeMsg1">修改msg1button> {{ msg1 }}div>
<div><button @click="changeMsg2">修改msg2button> {{ msg2 }}div>
template>
<!-- Child.vue -->
<script setup>
import { ref } from "vue";
// 接收
const props = defineProps({
msg1: String,
msg2: String,
});
const emit = defineEmits(["update:msg1", "update:msg2"]);
function changeMsg1() {
emit("update:msg1", "前端诡刺1");
}
function changeMsg2() {
emit("update:msg2", "前端诡刺2");
}
</script>
遇到多层传值时,使用 props 和 emit 的方式会显得比较笨拙。
这时就可以用 provide 和 inject 了。
provide 是在父组件里使用的,可以往下传值。
inject 是在子(后代)组件里使用的,可以往上取值。
无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。
父组件
<template>
<Child>Child>
template>
<!-- Parent.vue -->
<script setup>
import { ref, provide, readonly } from "vue";
import Child from "@/components/Child.vue";
const msg1 = ref("");
const msg2 = ref("前端菜鸟2");
// 使用readonly后子组件直接修改会发出警告,需要调用provide往下传的方法来修改
provide("msg1", readonly(msg1));
provide("msg2", msg2);
provide("changeName", (value) => {
msg1.value = value;
});
</script>
子组件
<template>
<div>
<div>msg1: {{ msg1 }}div>
<div>msg2: {{ msg2 }}div>
<button @click="handleClick">修改button>
div>
template>
<!-- Child.vue -->
<script setup>
import { inject } from "vue";
const msg1 = inject("msg1", "默认值"); // 看看有没有值,没值的话就适用默认值。
const msg2 = inject("msg2");
const changeName = inject("changeName");
function handleClick() {
// 这样写不合适,因为vue里推荐使用单向数据流,当父级使用readonly后,子元素直接修改会发出警告。
// msg1.value = '前端诡刺1'
// 正确的方式
changeName("前端诡刺1");
// 因为 msg2 没被 readonly 过,所以可以直接修改值
msg2.value = "前端诡刺2";
}
</script>
Vue3 中没有了 EventBus 跨组件通信,但是现在有了一个替代的方案 mitt.js,原理还是 EventBus。
先安装 npm i mitt -S
然后像以前封装 bus 一样,封装一下。
//mitt.js
import mitt from 'mitt'
const mitt = mitt()
export default mitt
// 组件 A
<script setup>
import mitt from './mitt'
const handleClick = () => {
mitt.emit('handleChange')
}
</script>
// 组件 B
<script setup>
import mitt from './mitt'
import { onUnmounted } from 'vue'
const someMethed = () => { ... }
mitt.on('handleChange',someMethed)
onUnmounted(()=>{
mitt.off('handleChange',someMethed)
})
</script>
pinia使用方法简易版