Vue3里通过props和emit进行父子组件传递数据的心得
vue3父子组件通信,vue3里props使用,vue3里emit使用
props
vue2里父组件传递数据给子组件,子组件通过props来接收,而vue3里依然如此,唯一不同的是在vue2里子组件接收数据后通过this[属性]来获取数据,而vue3则通过setup传递形参接收放在一个对象里,为了方便,形参默认就写props。如下例:父组件04-props.vue这个组件里传递给了子组件navbar两个数据,分别是myname="明哥"和myage=“27”,子组件navbar通过props接收后,在setup形参里接收使用,控制台可以看到是一个对象
代码如下:
//父组件04-props.vue
<template>
<div>父组件向子组件通信 <navbar myname="明哥" myage="27"></navbar></div>
</template>
<script>
import navbar from "./components/navbar";
export default {
components: {
navbar,
},
};
</script>
//子组件navbar.vue
<template>
<div>我是子组件navbar.vue</div>
<div>
<button>left</button>
姓名:{{ myname }} 年龄:{{ myage }}
<button>right</button>
</div>
</template>
<script>
export default {
props: ["myname", "myage"],
//vue2写法
// mounted(){
// console.log("获取父组件传过来的值",this.myname)
// },
setup(props) {
console.log("props", props, props.myname, props.myage);
},
};
</script>
emit
刚刚我们学习了父传子,现在学习一下子传父。场景如下:子组件sidebar里有很多行11111数据,默认显示,想实现当我点击left按钮时让其隐藏。可以看到setup的第二个形参aaa在控制台打印出的是一个对象,里面就有我们熟悉的emit。通过这个emit我们就能进行子传父,代码和效果如下:
我们可以在控制台看到打印的aaa如下
为了方便,我们会利用解构赋值,直接在形参上写成{emit}而不是随便写一个形参aaa,补一个常见警告吧,如下图,我的控制台报Runtime directive used on component with non-element root node.
意思是自定义指令不能放到组件上,而是要放到自有的元素上,也就是这里用到的v-show不能放在自定义组件上,而是放在原来就有的标签上,所以这里套了一层div。
回到刚刚那里,我们在vue3里通过将{emit}作为setup的第二个形参,然后通过emit(方法名,参数),就能达到和vue2里通过this.$emit(方法名,参数)相同的传数据给父组件效果。由于我们在父组件04-props.vue里通过event接收子组件传过来的方法,所以我们这里写的是emit(“event”),当然,取别的方法名也是可以的, 如下图,最后就达到了我们要的效果,点击left按钮,一行行的11111数据隐藏不见了:
完整代码如下:
//父组件04-props.vue
<template>
<div>
<navbar myname="明哥" myage="27" @event="change"></navbar>
<div v-show="obj.isShow">
<sidebar></sidebar>
</div>
</div>
</template>
<script>
import navbar from "./components/navbar";
import sidebar from "./components/sidebar";
import { reactive } from "vue";
export default {
components: {
navbar,
sidebar,
},
setup() {
const obj = reactive({
isShow: true,
});
const change = () => {
obj.isShow = !obj.isShow;
};
return {
obj,
change,
};
},
};
</script>
//子组件navbar.vue
<template>
<div>我是子组件navbar.vue</div>
<div>
<button @click="handleShow">left</button>
姓名:{{ myname }} 年龄:{{ myage }}
<button>right</button>
</div>
</template>
<script>
export default {
props: ["myname", "myage"],
//vue2写法
// mounted(){
// console.log("获取父组件传过来的值",this.myname)
// },
setup(props, { emit }) {
// console.log("props", props, props.myname, props.myage);
const handleShow = () => {
// emit就等同于this.$emit
emit("event");
};
return {
handleShow,
};
},
};
</script>
//子组件sidebar.vue
<template>
<div>我是子组件sidebar.vue</div>
<div>
<ul>
<li>11111</li>
<li>11111</li>
<li>11111</li>
<li>11111</li>
<li>11111</li>
<li>11111</li>
</ul>
</div>
</template>
<script>
export default {
props: ["myname", "myage"],
//vue2写法
// mounted(){
// console.log("获取父组件传过来的值",this.myname)
// },
setup(props) {
console.log("props", props, props.myname, props.myage);
},
};
</script>
更多推荐