当前位置: 首页 > 知识库问答 >
问题:

vue.js - 疑惑:vue3使用props传递数据的时候,该属性是一个对象,实际情况下,到底推不推荐在子组件直接修改对象内部的属性?

陶鹏
2023-10-19

假如父组件中是这样一个复杂的对象,传递给多个子组件,不同子组件要处理该修改中不同的属性,我目前的处理是直接在子组件中修改如props.params.approveStatus = 2,当然官方并不推荐这种处理,实际情况如何处理更好一些呢?

const params = ref<any>({    approveStatus: 0,    attachment: [],    bidDeadline: '',    bidFileValid: 0,    bidId: null,    bidMode: '',    bidNo: '',    bidScope: '',    bidScopeAttachment: [],    bidStage: 'initiate',    bidTitle: '',    buyMode: 1,    contact: '',    createBy: '',    createTime: '',    enterpriseId: 0,    flag: 0,    inquiryMethod: '',    inquiryMethodAttachment: [],    instanceId: 0,    labelType: 0,    promoterUserId: 0,    promoterUserName: '',    remark: '',    requestionDeadline: '',    sampleMode: 1,    status: 0,    supplierRecommenderId: null,    supplierRecommenderName: '',    technicalStandard: '',    technicalStandardAttachment: [],    updateBy: '',    updateTime: '',    valid: ''  })

共有5个答案

东方吕恭
2023-10-19

渲染框架都推荐单向数据流,目的是比较好追踪数据的改动

处理就是父组件封装接口修改数据,然后父组件进行自定义事件监听,子组件需要修改数据的时候进行emit

屠嘉勋
2023-10-19

实际使用还是不推荐,
这样破坏了单向数据流 ,随着组件变得复杂,你传入的数据在什么时候被组件内部改变了,你都不知道,可能导致一些难以发现的bug.
当你要在组件内部更改时,建议用emit到组件外部更改

const emit = defineEmits(['update:params'])emit('update:params',val)<template>    <A v-model:params="params"></A></template>
司空胤
2023-10-19

正如官网所说的那样:

更改对象 / 数组类型的 props

当对象或数组作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值。这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改动,虽然可能生效,但有很大的性能损耗,比较得不偿失。

这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响父组件的状态,可能会使数据流在将来变得更难以理解。在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变。

官方也是说了,在最佳实践中应尽可能避免,但也要根据你的业务需求来决定。

我前不久有个跟你差不多的需求,列表里一个数据,进行比如停用/启用操作,我的子组件是专门服务于这种情况的,然后在调用接口成功后直接更改props.xxx.status里参数的状态,因为需求是需要无感刷新,且这种情况应该是属于父子组件紧密耦合的状态。

邹玄裳
2023-10-19

你这种多组件处理同一对象的情况,可以使用Pinia来做啊。

// 定义storeconst useParamsStore = defineStore();// 在每个组件里面直接使用const params = useParamsStore()
宗建章
2023-10-19

在 Vue.js 中,一般不推荐在子组件中直接修改 props。这是由于 Vue 的响应式原理决定的。当你将一个对象作为 prop 传递给子组件,并在子组件中修改这个对象的属性,父组件并不能感知到这个修改。这是因为 Vue 只会关注对象属性的 getter 和 setter,当你在子组件中直接修改对象的属性,getter 和 setter 并没有触发,所以 Vue 无法感知到这个修改。

那么,面对这种情况,我们应该如何处理呢?

一个常见的解决方案是,在子组件中不直接修改 props,而是通过触发一个事件将修改传递给父组件。在父组件中,你可以监听这个事件,并做出相应的处理。这种处理方式可以使你的组件间的数据流更加清晰,也更容易维护。

下面是一个示例:

子组件:

props: ['params'],watch: {  'params.approveStatus': function(newVal, oldVal) {    this.$emit('update:params', { approveStatus: newVal });  }}

父组件:

<child-component :params="params" @update:params="updateParams"></child-component>methods: {  updateParams(newParams) {    this.params = newParams;  }}

在这个示例中,子组件监听了 params.approveStatus 的改变,并在改变后触发了一个名为 update:params 的事件,将新的参数传递给父组件。父组件接收到这个事件后,更新了 params 对象。

对于你提到的复杂对象,你可以按照上述方式对需要修改的属性一一进行处理。这样虽然看起来可能有些繁琐,但是可以保证数据在组件间的流动是可控的,也有利于维护和调试。如果你需要处理大量的属性,你也可以考虑使用 Vuex 或者其它状态管理库来帮助你管理这些数据。

 类似资料:
  • 问题内容: 我正在考虑我的应用程序的解决方案。这是一种情况:我有一个类,该类的方法将ObjectA作为输入参数并调用几个小方法,这些方法中的每个方法都需要ObjectA的某些部分(它们不重叠,即需求和,需求等等)。 …)现在的问题是:鉴于一般的良好代码实践和性能,将ObjectA传递给这些方法中的每一个方法更好,以便它们可以自己提取所需的值,还是仅传递它们的值更好?我的意思是: 要么 感谢您的任何

  • 所以,我想做的是: 创建水果的对象作为键和它们出现的次数。结束对象如下所示: 所以对于“苹果”来说: 我回顾了一堆帖子和链接,这些帖子和链接让我陷入了一个兔子洞。即便如此,他们中没有一个明确地解决了我所能说出的问题。 这段代码中Number对象保存属性并增加数字时发生了什么? 如何增加JavaScript对象中的值? 如何在JavaScript中使用for…语法获得循环计数器/索引? 遍历对象数组

  • 本文向大家介绍浅谈js内置对象Math的属性和方法(推荐),包括了浅谈js内置对象Math的属性和方法(推荐)的使用技巧和注意事项,需要的朋友参考一下 属性: constructor 所建立对象的函数参考 prototype 能够为对象加入的属性和方法 E 欧拉常量,自然对数的底(约等于2.718) LN2 2的自然对数(约等于0.693) LN10 10的自然对数(约等于2.302) LOG2E

  • 本文向大家介绍vue 数组和对象不能直接赋值情况和解决方法(推荐),包括了vue 数组和对象不能直接赋值情况和解决方法(推荐)的使用技巧和注意事项,需要的朋友参考一下 Vue 不能检测以下变动的数组: 当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue 当你修改数组的长度时,例如:vm.items.length = newLength 当第一种情况

  • 我正在使用mongoose将一个玩家推入mongoose中的玩家数组,当一个玩家加入游戏时。我收到以下错误:

  • 子组件 在expansion函数中可以直接修改父组件的值,vue也不会报警告,这是被允许的吗?为什么可以正常修改