vue中子组件如何间接修改父组件传递过来的值问题

 更新时间:2023年05月24日 11:52:01   作者:铁锤妹妹@  
这篇文章主要介绍了vue中子组件如何间接修改父组件传递过来的值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

一、前言

Vue官方文档Props单向数据流讲解

Vue中遵循单向数据流,所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递

这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

但是项目中总是有需求让我们来修改子组件内部传入的prop,所以才有了这篇文章,其实我们可以间接修改数据。

二、使用背景

父组件传递给子组件一个名为count数据,但是现在要在子组件中修改它的值并且实时更新页面,直接this.count是不能直接修改他的值的,控制台会报错,报错如下。

所以我采用了下面两种方式间接更改。

三、解决方法

方法1

子组件通过computed计算属性来间接修改父组件传递的值

父组件传值

<GoodsBasic :renderObj='renderBasic' :count='count'></GoodsBasic>

子组件更改传入的值

<template>
 <div class='goodsBasic'>
   <div>{{ incrementCount}}</div>
   <button @click='changeCount'>增加次数</button>
 </div>
</template>
<script>
export default {
  props: {
    renderObj: {
      type: Object,
      default () {
        return {}
      }
    },
    count:{
      type: Number,
      default:0
    }
  },
  data () {
    return {
      increment: this.count //新定义一个变量,并把prop传进来的值作为初始值
    }
  },
  computed:{
    incrementCount(){ //当新定义的变量变更时,计算属性也会自动更新
      return this.increment
    }
  },
  methods: {
    changeCount(){
      this.increment++
    }
  }
}
</script>

方法2

子组件data中重新定义个局部数据,把父组件prop传来的数据作为初始值使用。

父组件传值

<GoodsBasic :renderObj='renderBasic' :count='count'></GoodsBasic>

子组件更改传入的值

<template>
 <div class='goodsBasic'>
   <div>{{ increment }}</div>
   <button @click='changeCount'>增加次数</button>
 </div>
</template>
export default {
  props: {
    renderObj: {
      type: Object,
      default () {
        return {}
      }
    },
    count:{
      type: Number,
      default:0
    }
  },
  data () {
    return {
      increment: this.count  //作为初始值使用,这样做就使prop和后续更新无关了
    }
  },
  methods: {
    changeCount(){
      this.increment++
    }
  }
}
</script>

四、更改对象 / 数组类型的 props

经过个人测试发现,当传入的prop为Object类型的时候,修改组件内部的prop可以对应的改变父组件中的值。

如果传入的prop为简单类型(例如String,Number等)时,浏览器会报错,提示子组件不能修改prop的值。

比如上文例子更改 renderBasic.price控制台就不会报错。

个人感觉当传入的prop为引用类型时,子组件能直接修改父组件值,是因为在堆内存中公用同一个内存地址;修改的话只是改了它的值,而内存地址并没变,所以不报错; 

基本数据类型修改会报错,原因是指向的内存地址要被迫修改,所以控制台报错。

另外Vue官方文档也说了:

  • 当对象或数组作为 props 被传入时,虽然子组件无法更改 props 绑定,但仍然可以更改对象或数组内部的值。
  • 这是因为 JavaScript 的对象和数组是按引用传递,而对 Vue 来说,禁止这样的改动,虽然可能生效,但有很大的性能损耗,比较得不偿失。
  • 这种更改的主要缺陷是它允许了子组件以某种不明显的方式影响父组件的状态,可能会使数据流在将来变得更难以理解。在最佳实践中,你应该尽可能避免这样的更改,除非父子组件在设计上本来就需要紧密耦合。
  • 在大多数场景下,子组件应该抛出一个事件来通知父组件做出改变。

目前我们公司有个项目就是就是因为父子组件数据需要紧密耦合的,所以直接在子组件更改了数据;

上面文档说的子组件应该抛出一个事件来通知父组件做出改变,意思就是子组件调用$emit抛出一个事件名,去通知父组件,值要改变了,在父组件写一个事件做后续处理。

想继续深入vue传值的问题,也可以去看我之前关于vue中传值方法的文章。

vue组件之间的传值方法(父子传值,兄弟传值,跨级传值,vuex)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue.js多页面开发环境搭建过程

    vue.js多页面开发环境搭建过程

    利用 vue-cli 搭建的项目大都是单页面应用项目,对于简单的项目,单页面就能满足要求。这篇文章主要介绍了vue.js多页面开发环境搭建 ,需要的朋友可以参考下
    2019-04-04
  • Vue中component标签解决项目组件化操作

    Vue中component标签解决项目组件化操作

    这篇文章主要介绍了Vue中component标签解决项目组件化操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • vue3.0+vite2实现动态异步组件懒加载

    vue3.0+vite2实现动态异步组件懒加载

    学了vue写项目这么久,忽然发现路由懒加载的写法,节省了加载所有路由的时间。本文主要介绍了vue3.0+vite2实现动态异步组件懒加载,感兴趣的可以了解一下
    2021-06-06
  • vue使用ECharts实现折线图和饼图

    vue使用ECharts实现折线图和饼图

    这篇文章主要为大家详细介绍了vue使用ECharts实现折线图和饼图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • php+vue3实现点选验证码功能

    php+vue3实现点选验证码功能

    这篇文章主要介绍了php+vue3实现点选验证码,本文通过实例代码给大家介绍的详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • Vue3路由跳转并传递参数的应用场景分析

    Vue3路由跳转并传递参数的应用场景分析

    本文主要介绍在Vue3工程使用setup语法中如何进行路由跳转并传递参数,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-05-05
  • Vue开发中Jwt的使用详解

    Vue开发中Jwt的使用详解

    Vue中使用JWT进行身份认证也是一种常见的方式,它能够更好地保护用户的信息,本文主要介绍了Vue开发中Jwt的使用详解,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • vue开发心得和技巧分享

    vue开发心得和技巧分享

    这篇文章主要为大家分享了vue开发心得和技巧,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • 详解在Vue中通过自定义指令获取dom元素

    详解在Vue中通过自定义指令获取dom元素

    本篇文章主要介绍了详解在Vue中通过自定义指令获取dom元素 ,具有一定的参考价值,有兴趣的可以了解一下。
    2017-03-03
  • Vue使用三方工具vueUse实现虚拟列表

    Vue使用三方工具vueUse实现虚拟列表

    其实采用vueUse中的useVirtualList方法同样可以实现虚拟列表,这篇文章小编就来和大家详细介绍一下如何使用vueUse实现简单的虚拟列表效果吧
    2024-04-04

最新评论