首页 > 其他分享 >子组件不能直接改变父组件传递的“道具”值

子组件不能直接改变父组件传递的“道具”值

时间:2024-07-25 19:56:57浏览次数:13  
标签:false 道具 prop 传递 showDialog 组件 model emit

        引言:

        不少人在刚开始使用vue时都会遇到一个报错——Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.(避免直接改变道具,因为当父组件重新渲染时,该值将被覆盖。相反,使用基于道具值的data或computed属性。)

        这个问题是因为在 Vue.js 中,数据流是单向的,父组件通过 props 将数据传递给子组件,子组件中不能直接修改父组件传递进来的值。那么我们该如何去解决呢?

一、场景举例

        大家在开发中会经常对Dialog弹窗进行二次封装,从而便于我们在多个页面使用,这个时候我们就需要在父组件中控制Dialog弹窗的展示,同时还需要在子组件Dialog中将自己关闭。这种情况下就可能会出现上面的报错。

例:

        在父组件中引入一个封装过的Dialog弹窗组件,并向子组件传递所需参数,此时我们默认showDialog为true。

<template>
	<div>
		<satisfactionDialog
			:showDialog="showDialog"
			@cancel="showDialog = false"
			@affirm="showDialog = false"
			@close="showDialog = false"
            affirm-text="确认"
			cancel-text="取消"
			title="子组件标题"
		>
			<!--			<div style="height: 200px"></div>-->
		</satisfactionDialog>
	</div>
</template>

<script>
import satisfactionDialog from "XXXXXXX";

export default {
	data() {
		return {
			showDialog: true,
		};
	},
	methods: {
	},
	components: { satisfactionDialog },
};
</script>

         子组件中接受父组件传递的参数,此时子组件为展示状态。

<template>
	<div>
		<van-dialog v-model="showDialog" width="82%" :show-confirm-button="false" :overlay="overlay" title>
			<div class="content">
				<img src="@/views/assets/close_icon.png" @click="close" alt="" />
				<header>
					{{ title }}
				</header>
				<slot></slot>
				<footer>
					<div class="cancel">
						<van-button type="info" @click="cancel">{{ cancelText }}</van-button>
					</div>
					<span></span>
					<div>
						<van-button type="info" @click="affirm">{{ affirmText }}</van-button>
					</div>
				</footer>
			</div>
		</van-dialog>
	</div>
</template>
<script>
export default {
	name: "satisfactionDialog",
	props: {
		showDialog: Boolean,
		cancelText: String, //取消按钮文案
		affirmText: String, //确认按钮文案
		title: String, //标题文案
		overlay: {
			//是否显示遮罩层
			type: Boolean,
			default: true,
		},
	},
};
</script>

        我们要在子组件中关闭Dialog弹窗,此时方法应该怎样写? 

        可能有同学会写:

methods: {
		// 取消事件
		cancel() {
			this.showDialog = false;
		},
		//确认事件
		affirm() {
			this.showDialog = false;
		},
		close() {
			this.showDialog = false;
		},
	},

        去年刚入职的我也是这样写的。。。此时我们就会发现控制台报错了,报错的原因正是:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.(避免直接改变道具,因为当父组件重新渲染时,该值将被覆盖。相反,使用基于道具值的data或computed属性。)

二、解决方法

 那么我们应该怎样去写呢?这里给大家几种方法:

       1、通过this.$emit去调用父组件的自定义方法,这样便可以控制数据流向永远都是通过父组件改变值来改变子组件的显示。
methods: {
		// 取消事件
		cancel() {
			this.$emit("cancel");
		},
		//确认事件
		affirm() {
			this.$emit("affirm");
		},
		close() {
			this.$emit("close");
		},
	},
        2、使用自定义v-model一劳永逸,就不需要再关注父子传参了。

        在父组件中使用v-model="showDialog"代替:showDialog="showDialog",注意子组件中的写法:

        首先需要设置model属性:

model: {   //在这里设置model绑定的值的对应关系
		prop: "showDialog",
		event: "change",  //定义触发的方法
	},

        props中需要正常接收 :

props: {
		showDialog: Boolean,  //注意这里需要正常接收父组件传递的值
	},

        通过调用定义好的event方法来改变值:

methods: {
		// 取消事件
		cancel() {
			this.$emit("change", false);
		},
		//确认事件
		affirm() {
			this.$emit("change", false);
		},
		close() {
			this.$emit("change", false);
		},
	},

关于自定义v-model大家也可以参考我的另一篇文章中的讲解自定义子组件的v-model

标签:false,道具,prop,传递,showDialog,组件,model,emit
From: https://blog.csdn.net/gkx19898993699/article/details/140697657

相关文章

  • HarmonyOS NEXT 学习笔记5--extend扩展组件
    1.代码:@Entry@ComponentstructPage_Button_Extend{@Statemessage:string='HelloWorld';build(){Column({space:10}){Button('微信支付').MyButton('wechat')Button('支付宝').My......
  • 深入探讨Spring Boot中的参数传递
    深入探讨SpringBoot中的参数传递在SpringBoot开发中,参数传递是一个非常常见且重要的操作。无论是处理HTTP请求,还是在方法之间传递数据,理解和掌握参数传递的各种方式都能让我们的代码更加简洁和高效。今天,我们就来深入探讨一下SpringBoot中的参数传递。1.基础知识:HTTP请求参......
  • HarmonyOS:组件Navigation使用中List显示不全的问题探究以及解决办法
    1.线性布局中在使用NavPathStack布局中中发现如果使用List组件会发现item显示不全,在使用官方提供的例子中也发现此问题。如图所示:底部被遮挡,官方示例的写法2.如果线性布局中,不显示导航栏,也会出现List被遮挡的问题如图所示:我们的页面布局中的List缺失一部分根据Previ......
  • vue3 父组件 props 异步传值,子组件接收不到或接收错误
    1.使用场景我们在子组件中通常需要调用父组件的数据,此时需要使用vue3的props进行父子组件通信传值。2.问题描述那么此时问题来了,在使用props进行父子组件通信时,因为数据传递是异步的,导致子组件无法成功获取数据,若此时父组件中数据发生变化,那子组件获取的值是改变之......
  • vue的组件事件/组件事件配合v-model使用/组件数据传递/
    1.组件事件形式为:父级页面中格式——引入子级页面importxxfrom'url'<xx@事件名="函数名"/>子级页面中格式——添加点击事件<button@click="自定义函数">自定义函数(){//自定义事件this.$emit("事件名","文本内容")}2.组件事件配合v-model使用v-modelwatch......
  • [二、状态管理]2管理组件拥有的状态(5)@Observed装饰器和@ObjectLink装饰器:嵌套类对象属
    上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器。说明从APIver......
  • vue的组件注册/组件传递数据_props/组件传递多种数据类型/组件传递Props校验
    1.组件注册全局注册:注册完后所有vue都能使用局部注册:仅当前页面能够使用全局注册虽然方便但有以下几个问题一.在打包时会将它一同打包,有时候没有用到它也打包,无任何意义二.课维护性低,在大型项目中使项目的依赖关系不明确2.组件传递数据_props父级传递子级数据(注意传递数......
  • 条件组合组件--vue3版
    参考手把手教你写一个条件组合组件此随笔是借鉴以上写的vue版,记录一下组件前期准备1.vue3的全套工具2.element-plus3.lodash数据结构主要是嵌套结构关键点在RelationGroup组件内引用本身,注意key值,不能用i,不然删除操作,会从最后删起组件结构主要是这3个文件引用......
  • vue 2 实现自定义组件一到多个v-model双向数据绑定的方法(转)
    原文链接:https://blog.csdn.net/Dobility/article/details/110147985前言有时候我们需要对一个组件绑定自定义v-model,以更方便地实现双向数据,例如自定义表单输入控件。甚至有时候,我们想要实现绑定多个“v-model”,也就是多个“双向绑定”,例如带表单输入的模块框,想同时控制模态......
  • 在K8S中,外部访问容器服务,比如说提供了一个域名,链路怎么走?数据经过哪些组件?
    在K8S(Kubernetes)中,外部访问容器服务并涉及到一个域名时,整个访问链路会经过多个组件,确保请求能够正确地被路由到目标服务。以下是详细的链路流程和涉及的组件:1.链路流程域名解析:当用户在浏览器或客户端输入域名时,首先会进行DNS解析。DNS服务器会将域名解析为对应的IP地址。......