Vue3中使用props和emits详解

发布时间:2023年12月23日

前言

在Vue3中,父子组件之间的数据传递是一个常见的需求。本文将介绍如何在Vue3中传递对象,并且在子组件中访问和修改父组件对象中的属性值,以及子组件如何调用父组件中的方法。


在 Vue 3 中,父子组件之间传值有以下作用:

1. 组件通信:父组件可以通过向子组件传递数据来实现与子组件的通信。这样,父组件就能将数据传递给子组件,并且子组件可以根据接收到的数据进行渲染或执行相应的操作。

2. 数据共享:通过父子组件传值,可以在多个组件之间共享数据。当多个子组件需要访问同一个数据时,可以将数据定义在父组件中,然后通过 props 将数据传递给子组件,从而实现数据共享。

3. 动态配置:父组件可以通过向子组件传递不同的参数或配置,来动态控制子组件的行为。例如,父组件可以根据用户的操作或业务需求,向子组件传递不同的 props 值,以便子组件根据不同的配置进行展示或处理。

4. 构建组件库:通过父子组件传值,可以构建可复用的组件库。父组件可以定义一些可配置的选项或属性,并将它们作为 props 传递给子组件。这样,其他开发者在使用该组件库时,可以根据自己的需求和场景,通过修改 props 值来自定义组件的行为和外观。
?

1. 在setup()语法糖中使用 props 和 emits

setup有props和cxt两个参数,可以在setup语法糖内部使用props 和 emits

父组件代码示例:

<script setup lang="ts">
import {ref} from 'vue'

const count = ref(10)
const userlist = ref([
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"}
])

function edit(val):void{
  userlist.value[val].name = 'liudehua'
}

function del():void{
  alert("delete")
}
</script>

<template>
 

  <definePropsTest :userlist="userlist" :count="count" @edit="edit" @delete="del"></definePropsTest>
</template>

<style scoped>

</style>

子组件代码示例:?

<script lang="ts">
import {setup,emit} from 'vue';

export default{
    props:{
        count:Number,
        userlist:Array
    },
    emits:["edit","delete"],
    setup(props,cxt){
        // 语法糖内部使用
        function edit(index):void{
            cxt.emit("edit",index)
        }
        function del():void{
            cxt.emit("delete");
        }
        return {
            props,
            edit,
            del
        }
    },
    created(){
        console.log(this.count);
        console.log(this.userlist)
        this.$emit("edit",1);
    }
    
}
</script>
<template>
<!-- 在模版中访问 -->
<p>总共{{ count }}条数据</p>
    <table :border="1">
        <tr>
            <th>姓名</th>
            <th>密码</th>
            <th>操作</th>
        </tr>
        <tr v-for="(item,index) in userlist" :key="index">
            <td>{{ item.name }}</td>
            <td>{{ item.password }}</td>
            <td>
                <button @click="edit(index)">编辑</button>
                <button @click="del()">删除</button>
            </td>
        </tr>
    </table>

</template>

2. <script setup>语法中使用 props和emits

defineProps返回的props对象,是一个proxy对象,所有特性和reactive基本相同,只不过由defineProps定义出的props对象的值是只读的,还有在模板上可以单独属性直接使用

defineProps:父组件传值给子组件,实现子组件访问父组件传入的值

语法:

let props = defineProps({
    count:Number,       // 也可以直接简写 只填类型
    userlist:{
        type:Array,    // 规定数据的类型
        required:true, // 是否是必填选项
        default:[]     // 如果父组件没有传值情况下的默认值
    }
})

父组件

<script setup lang="ts">
import {ref} from 'vue'


import definePropsTest from './components/definePropsTest.vue'

const count = ref(10)
const userlist = ref([
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"}
])

</script>

<template>
  <definePropsTest :userlist="userlist" :count="count"></definePropsTest>
</template>

<style scoped>

</style>

子组件

<script setup lang="ts">
    let props = defineProps({
        count:Number,       // 也可以直接简写 只填类型
        userlist:{
            type:Array,    // 规定数据的类型
            required:true, // 是否是必填选项
            default:[]     // 如果父组件没有传值情况下的默认值
        }
    })

    // 在代码中访问
    console.log(props.count);
    console.log(props.userlist);
    
</script>
<template>
<!-- 在模版中访问 -->
    <p>总共{{ props.count }}条数据</p>
    <table :border="1">
        <tr>
            <th>姓名</th>
            <th>密码</th>
        </tr>
        <tr v-for="(item,index) in props.userlist" :key="index">
            <td>{{ item.name }}</td>
            <td>{{ item.password }}</td>
        </tr>
    </table>
</template>

子组件如何修改父组件传入的值?

vue是单项数据流,引用Vue的官网的话:父系 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父及组件的状态,从而导致你的应用的数据流向难以理解。

在父子组件通讯的时候,子组件都禁止直接修改父级传过来的prop 直接修改在控制台会报错。但VUE的两个语法糖能做到这一点,
?

这里我们来讲defineEmits的使用,子组件调用父组件中的方法

?父组件代码示例:

<script setup lang="ts">
import {ref} from 'vue'

const count = ref(10)
const userlist = ref([
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"},
  {"name":"xujingliang","password":"123456"}
])

function edit(val):void{
  userlist.value[val].name = 'liudehua'
}

function del():void{
  alert("delete")
}
</script>

<template>
 

  <definePropsTest :userlist="userlist" :count="count" @edit="edit" @delete="del"></definePropsTest>
</template>

<style scoped>

</style>

子组件代码示例:

<script setup lang="ts">
let props = defineProps({
    count:Number,       // 也可以直接简写 只填类型
    userlist:{
        type:Array,    // 规定数据的类型
        required:true, // 是否是必填选项
        default:[]     // 如果父组件没有传值情况下的默认值
    }
})

const emit = defineEmits(['edit', 'delete']);

    // 在代码中访问
    console.log(props.count);
    console.log(props.userlist);
    
</script>
<template>
<!-- 在模版中访问 -->
    <p>总共{{ props.count }}条数据</p>
    <table :border="1">
        <tr>
            <th>姓名</th>
            <th>密码</th>
            <th>操作</th>
        </tr>
        <tr v-for="(item,index) in props.userlist" :key="index">
            <td>{{ item.name }}</td>
            <td>{{ item.password }}</td>
            <td>
                <button @click="emit('edit',index)">编辑</button>
                <button @click="emit('delete',item.name)">删除</button>
            </td>
        </tr>
    </table>
</template>

在Vue3中如果想修改父组件传入的值,只能通过defineEmits让子组件调用父组件中的方法来修改父组件中的值,同时子组件中的值也会发生响应式变化;

文章来源:https://blog.csdn.net/qq_41765777/article/details/135164531
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。