vue3中子组件修改父组件传来的数据,导致父组件也发生变化

问题原因

    1. ‌引用类型数据传递‌
      父组件传递对象/数组时,子组件接收的是原数据的引用,直接修改会双向影响

    2. ‌基本类型数据安全‌
      若传递字符串、数字等基本类型,Vue 会阻止直接修改并抛出警告

注意:在子组件中修改父组件的数据是不对的,子组件不能修改父组件的属性,但是当父组件传给子组件的是一个对象类型(而非基本类型)时,修改子组件的数据时,父组件的数据也会发生变化,要想避免这种变化,就应进行深拷贝

  • 子组件 页面.vue
  • <script setup lang="ts">
    import { ref ,reactive} from "vue";
    import { cloneDeep } from 'lodash';
    
    const props = defineProps({
      msg: String,
      nameInfo: Object
    });
    const localData = ref(cloneDeep(props.nameInfo))
    
    const iphone = ref('18100000000')
    const showAddress = ref(true)
    const isEdit = ref(false)
    
    const emit = defineEmits(['zEdit','isShow'])
    
    
    const editInfo = () => {
      // props.nameInfo.age = '30';
      localData.value.age='30';
      
      iphone.value = '15100000000';
      
      isEdit.value = true;
      emit('zEdit',isEdit)
    
      const isShow = '1234'
      emit('isShow',isShow)
    }
    </script>
    
    <template>
      <el-divider content-position="right">子页面</el-divider>
      <div>
        <el-form label-width="150px" label-position="left">
          <el-form-item label="接受props信息:">{{msg}}</el-form-item>
        </el-form>
        <div class="mt-20">
          <div class="f-r">
            <el-button  type="primary" plain @click="editInfo()">修改</el-button>
            <el-button  type="primary" plain @click="showAddress=!showAddress">隐藏居住地</el-button>
          </div>
          <el-descriptions title="用户信息" size="default" :column="3" border>
            <el-descriptions-item label="用户名">{{localData.name}}</el-descriptions-item>
            <el-descriptions-item label="年龄">{{localData.age}}</el-descriptions-item>
            <el-descriptions-item label="手机号">{{iphone}}</el-descriptions-item>
            <el-descriptions-item label="备注">
              <el-tag size="small">学校</el-tag>
            </el-descriptions-item>
            <el-descriptions-item label="居住地" v-if="showAddress">苏州市</el-descriptions-item>
            <el-descriptions-item label="联系地址">江苏省苏州市吴中区吴中大道 1188 号</el-descriptions-item>
          </el-descriptions>
        </div>
      </div>
    </template>
    
    <style scoped>
    .mt-20 {
      margin-top: 20px;
    }
    .f-r{
      float: right;
    }
    .red-t{
      background: #FDE2E2;
      color: red;
    }
    
    </style>

     

 

  • 父页面
  • <script setup lang="ts">
    import { ref } from "vue";
    import DatapassZ from "./datapassZ.vue";
    
    const msg = ref("详情");
    const zedit = ref("");
    const form = ref({})
    
    interface Person {
      id: number;
      name: string;
      age: number;
    }
    const nameInfo = ref<Person>({ id: 1, name: "zz", age: 28 });
    const zEdit = (a)=>{
      console.log('子页面传回修改值',a.value);
      zedit.value = a
    }
    const isShow = (a)=>{
      console.log('子页面传回多个值',a);
    }
    
    </script>
    
    <template>
      <el-card>
        <p class="right">父页面</p>
        <div class="card">
          <div>
            <el-form ref="form" :model="form" label-width="150px" label-position="left">
              <el-form-item label="传值信息:">{{msg}}</el-form-item>
              <el-form-item label="父组件的用户年龄:">{{nameInfo.age}}</el-form-item>
              <el-form-item label="子页面是否修改:"> 
                <el-tag :type="zedit?'warning':null">{{zedit?'已修改':'未修改'}}</el-tag>
              </el-form-item>
            </el-form>
            
          </div>
          <Datapass-z :msg="msg" :nameInfo="nameInfo" @zEdit="zEdit" @isShow="isShow" /> 
        </div>
      </el-card>
    </template>
    
    <style scoped>
    .right {
      font-size: 14px;
      color: #afabab;
      text-align: right;
    }
    </style>

     

 

 

 

 

 

 

 

posted @ 2025-06-29 11:58  Evident  阅读(469)  评论(0)    收藏  举报