VUE父组件向子组件传递值

创作灵感

最近在写一个项目时,遇到了这样的一个需求。我封装了一个组件,这个组件需要被以下两个地方使用,一个是搜索用户时用到,一个是修改用户信息时需要用到。其中,在搜索用户时,可以根据姓名或者账号进行搜索。根据账号一次只能搜索出一个用户,根据姓名可以一次性搜出许多名字包含该内容的用户,如下图:

按名称搜索示意图

然而,在更改用户信息界面使用该组件时,我们不希望用户能通过姓名来查询,因为我们是一个一个的修改用户信息的,如果通过姓名查询会查询出多个数据。因此,我们需要在更新用户信息界面使用该组件是禁止选择姓名选项,如下:

 禁止按名称搜索示意图

效果实现

要想实现上面的效果,大致思路就是父组件在使用子组件时,传递一个参数,根据这个参数选择是否禁用。这就需要用到父组件向子组件传递值的知识了。父组件向子组件传值最简单的就是props了,如果有多重传递,则需要用到别的方法,大家可以去了解一下,这里我使用的是props。

下面为子组件与父组件的代码实现:

<template>
    <div class="mt-4">
        <el-input
        v-model="content"
        style="max-width: 600px"
        placeholder="请输入用户信息"
        class="input-with-select"
        >
        <template #prepend>
            <el-select v-model="select" placeholder="账号" style="width: 115px">
                <el-option :disabled="noSelect==1" label="账号" value="1" />
                <el-option :disabled="noSelect==2" label="姓名" value="2" />
            </el-select>
        </template>
        <template #append>
            <el-button @click="search" icon="Search" />
        </template>
        </el-input>
    </div>
</template>

<style scoped lang="scss">

</style>

<script lang="ts">
import { defineComponent,reactive, ref, toRaw } from 'vue'
import API from '@/untils/axios'
import { ElMessage } from 'element-plus'

export default defineComponent({
    props:['noSelect'],
    emits:["returnResults"],
    name:"searchComponent",
    setup(){
        var select=ref("1")
        var content=ref("")
        var users=reactive({//返回的前十位用户信息
            data:[]
        })
        var total=ref(0)
        return{
            select,
            users,
            total,//总的记录数
            content
        }
    },
    methods:{
        search(){
            if(this.content==""){
                ElMessage({
                    message:"搜索值为空",
                    type:"warning"
                })
                return
            }
            API.get("admin/searchUsers",{
                params:{
                    type:this.select,
                    content:this.content                
                }
            }).then((res:any|undefined)=>{
                if(res==undefined){
                    return
                }
                if(res.data.users.length==0){
                    ElMessage({
                        message:"搜索为空",
                    })
                } else {
                    ElMessage({
                        message:"搜索成功",
                        type:"success"
                    })
                }
                this.users.data=res.data.users
                this.total=res.data.total
                var result={
                    users:toRaw(this.users.data),//搜索出来的前10位信息
                    total:this.total,
                    content:this.content
                }
                this.$emit("returnResults",result)
            })
        }
    }
})
</script>

大家主要看到的是props,里面就包含了父组件传来的'noSelect',子组件根据传来的值来禁止需要禁止的选项

父组件传递值:

<template>
    <div>
        <searchComponent :noSelect="2" class="searchComponent"/>
        <el-divider />
    </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import searchComponent from "@/components/searchComponent.vue"

export default defineComponent({
    components:{
        searchComponent
    }
})
</script>

<style scoped lang="scss">
.searchComponent{
    margin: 5vh;
}
</style>

在这里,我在使用子组件时,向其传递了'noSelect'值为2,意味着禁止了姓名选项。子组件拿到值后就可以根据拿到的值来禁止对应的选项卡了。

子向父动态的取得值并且能够改变该值

其实上面的这个标题并不完全正确,因为一般情况下,我们并不希望子组件可以直接修改父组件的值,如果真的有类似的需求,应当如何完成呢?答案是子组件复制父组件所传递的值,而后修改复制后的值就可以了。下面向大家展示一下具体的应用场景:

在上面的这个场景内,我们需要用到两个子组件,搜索的子组件与展示个人信息的子组件。其中、展示个人信息的子组件用到了两次,一次为仅供展示的,一个是可供编辑的,这样在修改个人信息时,就可以知道自己修改了哪些部分。但是需要注意的是,一开始个人展示组件里面的信息是空的,我们如何使其在拿到父组件的值后能相应的更改呢?(由于我在子组件内可能需要改变父组件传递的值,所以我们不能直接使用父组件的响应式来完成这个功能)。

这时我们就需要监听父组件传递的值,如果其发生了改变,我们就改变子组件本地备份的数据,就能做到——既可以编辑父组件传递的值(实际上为其对应的深拷贝对象)、又能在父组件重新给值时响应式的改变子组件的内容了。具体代码如下:

<script lang="ts">
import { defineComponent, reactive,watch } from 'vue'

export default defineComponent({
    props:['readOnly','user'],//readOnly(是否设置为只读)
    setup(props){
        watch(props.user,(newUser)=>{//监听父组件传递值发生改变后,将子组件的值一起改变
            localUser.data=newUser.data.data
        })
        var localUser:any=reactive({//拿到父组件传递过来的初始值对象,并使用reactive对其进行响应式监听
            data:props.user.data.data
        })
        return{
            localUser
        }
        
    },
})
</script>

子组件的js部分

上述js中,我在setup()内定义了一个本地的localUser,并且将其定义为了一个响应式的对象。其内部的值取自父组件传来的user对象,子组件可以通过编辑localUser对象,令用户感觉他们在编辑user一样。同时,此时如果还想父组件的user发生改变,子组件同时改变时,必须使用watch进行监听了。有人或许会说,我们把父组件的user对象设置为一个响应式对象不就行了?然而,由于子组件展示的是localUser,不是父组件的user,在子组件内没有触发localUser对象的值发生改变是不会令其内容发生变动的。所以必须使用一个监听器来监听父组件的值发生变动时,及时的将变动的新值赋值给子组件的本地user

其他问题

在介绍完这些后,最后向大家再介绍一个易错点,那就是浅拷贝问题。因为我这里的展示面板使用了两次,一个是仅供参考的,一个是可供编辑的。但如果在向两个子组件传值时使用的是浅拷贝,会导致在编辑面板修改时,展示面板也会被修改。解决办法就是在编辑面板传值时使用深拷贝。具体的大家可以翻看我之前的文章,下面向大家展示一下我的解决方法:

<script lang="ts">
import { defineComponent, reactive } from 'vue'
import searchComponent from "@/components/searchComponent.vue"
import userDetail from '@/components/userDetail.vue'

export default defineComponent({
    components:{
        searchComponent,
        userDetail
    },
    setup(){
        var user:{//初始对象,无需响应式
            data:{
                id:number,
                name:string,
                sex:string,
                account:string,
                type:string,
                avatar_url:string,
                email:string,
                myselfIntroduce:string,
                isIdentification:number,
            }
        }={
            data:{
                id:0,
                name:"",
                sex:"",
                account:"",
                type:"",
                avatar_url:"",
                email:"",
                myselfIntroduce:"",
                isIdentification:-1
            }
        }
        var readUser=reactive({//只读对象,需要响应式的传递至子组件
            data:user
        })
        var writeUser=reactive({//可读写对象,需要响应式的传递至子组件
            data:JSON.parse(JSON.stringify(user))//简单深度拷贝,防止修改该对象时影响到别的对象
        })
        return{
            user,
            readUser,
            writeUser,
        }
    },
    methods:{
        getResult(e:any){
            if(e.total==0){
                return
            }
            this.readUser.data.data=e.users[0]
            this.writeUser.data.data=JSON.parse(JSON.stringify(e.users[0]))//对于有修改的部分传值使用深拷贝
        }
    }
})
</script>

上面的就是我父组件的js内容,其中,在对writerUser对象赋初始值以及后面的任何一次赋值都使用了深拷贝(建议不要按照我这样来,深拷贝还有其他方法,这里我图方便就没用了

感谢大家的观看!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/572444.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

【Unity】苹果(IOS)开发证书保姆级申请教程

前言 我们在使用xcode出包的时候&#xff0c;需要用到iOS证书(.p12)和描述文件(.mobileprovision) 开发证书及对应的描述文件用于开发阶段使用&#xff0c;可以直接将 App 安装到手机上&#xff0c;一个描述文件最多绑定100台测试设备 1.证书管理 进入网站Apple Developer &…

从虚拟化走向云原生,红帽OpenShift“一手托两家”

汽车行业已经迈入“软件定义汽车”的新时代。吉利汽车很清醒地意识到&#xff0c;只有通过云原生技术和数字化转型&#xff0c;才能巩固其作为中国领先汽车制造商的地位。 和很多传统企业一样&#xff0c;吉利汽车在走向云原生的过程中也经历了稳态业务与敏态业务并存带来的前所…

视频美颜SDK原理与实践:从算法到应用

当下&#xff0c;从社交媒体到视频通话&#xff0c;人们越来越依赖于视频美颜功能来提升自己的形象。而视频美颜SDK作为支撑这一技术的重要工具&#xff0c;其原理和实践至关重要。 一、什么是视频美颜SDK&#xff1f; 视频美颜SDK是一种软件开发工具包&#xff0c;用于集成到…

FloodFill算法---DFS

目录 floodfill算法概念&#xff1a; 算法模板套路&#xff1a; 例题1&#xff1a;图像渲染 例题2&#xff1a;岛屿数量 例题3&#xff1a;岛屿的最大面积 例题4&#xff1a;被围绕的区域 floodfill算法概念&#xff1a; floodfill算法是一种常用的图像处理算法&#xf…

【IDEA】在IntelliJ IDEA中导入Eclipse项目:详细指南

IntelliJ IDEA和Eclipse是两款常用的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在软件开发中经常会遇到需要在它们之间迁移项目的情况。本文将重点介绍如何在IntelliJ IDEA中导入Eclipse项目&#xff0c;以帮助开发者顺利地迁移他们的项目&#xff0c;并在IntelliJ …

云主机修复监控插件异常的方法

首先&#xff0c;进入云监控服务--选择主机监控&#xff0c;勾选上网络配置异常的云主机&#xff0c;最上面的修复插件配置&#xff0c;然后等待大约半个小时多&#xff0c;再观察下主机的状态。 一般情况下问题都可以被解决&#xff0c;如果解决不了&#xff0c;可以尝试卸载…

剑指 Offer 03.:数组中重复的数字

剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字。 在一个长度为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。…

Linux下的进程管理:创建、终止、切换与等待

文章目录 一、引言二、进程创建1、进程创建的概念与场景2、进程创建的方式a、fork() 系统调用b、fork() 后的执行流程 3、进程创建的过程a、进程创建过程b、子进程创建过程 4、父子进程关系与属性继承 三、进程终止1、进程终止的原因2、进程的错误码和退出码a、错误码b、退出码…

Golang基础5-指针、结构体、方法、接口

指针 和c/c类似&#xff0c;但是go语言中指针不能进行偏移和运算&#xff0c;安全指针 &&#xff08;取地址) *(根据地址取值) nil(空指针&#xff09; make和new之前对比&#xff1a;make用于初始化slice&#xff0c;map&#xff0c;channel这样的引用类型 而new用于类…

热知识:更多团队采用3个及以上内部开发者平台

01 介绍 根据 Perforce Puppet 的一份新报告中&#xff0c;平台工程的采用已经在一些企业内看到了成效&#xff0c;78% 的受访者表示他们的组织拥有专门的平台团队至少三年了。 然而&#xff0c;这并不意味着这些组织只使用同一套工具。四分之三的调查参与者表示&#xff0c;他…

如何使用SOLIDWORKS添加装饰螺纹线规格

在我们的设计过程中&#xff0c;有很多的时候螺纹规格在机械设计手册上没有&#xff0c;而我们的SOLIDWORKS软件里面录制的都是符合标准的的螺纹&#xff0c;至于其他的特种或者超出的规格需要我们设计人员去手工添加&#xff0c;以下介绍我们装饰螺纹线新规格的添加方法&#…

关于PMO卓越中心职能建设的实践与思考︱PMO大会

全国PMO专业人士年度盛会 浪潮电子信息产业股份有限公司PMO时军先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾&#xff0c;演讲议题为“让组织持续卓越——关于PMO卓越中心职能建设的实践与思考”。大会将于5月25-26日在北京举办&#xff0c;敬请关注&#xff01; …

菜单访问url/接口url为什么要带时间戳

一&#xff0c; 问题 1&#xff0c;菜单url中如果不加时间戳&#xff0c;会导致什么问题。我们现在做一个东西&#xff0c;需要获取菜单的访问地址&#xff0c;我们要拼这个地址 2&#xff0c;查询接口中&#xff0c;时间戳&#xff0c;如果不加&#xff0c;具体导致什么问题 二…

Vue集成three.js,加载glb、gltf类型的3d模型

安装基本依赖 // 注意OrbitControls要加{}&#xff0c;注意路径是jsm import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls.js’; // import { dat } from ‘three/examples/jsm/controls/dat.gui.js’; // dat gui这个插件&#xff0c;是另外自己下载…

杰理使用USB声卡模式时关闭MIC

杰理在使用PC模式的时候&#xff0c;想只保留扬声器&#xff0c;但不要打开MIC功能&#xff0c;可以配置USB_DEVICE_CLASS_CONFIG中把MIC_CLASS去掉&#xff0c;然后重新编译就可以了。

Kimi 高效使用技巧,80%的人都不知道

关注我, AI 学习之旅上&#xff0c;我与您一同成长&#xff01; 一、引言 Kimi 作为国产之光&#xff0c;在过去的一个多月里成为国内大模型的香饽饽。据数据分析&#xff0c;Kimi 网页、APP、小程序等各端的日活已经突破 300 万&#xff0c;超过文心一言、通义千问、智谱清言…

单链表实现通讯录

不过多赘述了 顺序表的增删查改-CSDN博客https://blog.csdn.net/bkmoo/article/details/137566495?spm1001.2014.3001.5502 使用顺序表实现通讯录-CSDN博客https://blog.csdn.net/bkmoo/article/details/137676561?spm1001.2014.3001.5502这里没有使用文件操作只是简单的使…

6.MMD ray渲染 材质的添加及打光方法

材质 前置准备 先准备好模型和场景 将ray控制器拖入进去 添加完默认的材质以后的效果 打开插入材质页面 打开MaterialMap栏 将流萤的模型展开 自发光 现在给领带添加一个自发光效果 在自发光Emissive里&#xff0c;打开x1&#xff0c;选择albedo&#xff0c;白光 现在…
最新文章