简体   繁体   中英

Deep copy of a Javascript object is not working as expected in Vue.js

I am passing a clone of an object from a parent component to a child component using props , but when I change the value of the status property in the object of the parent component the child component gets notified and chenges the value of the status property in the "cloned" object.

I've read about Object.assign() method and that it only does shallow copying but the strange thing is that my object properties are of primitive type String meaning they should be copied by value not by reference, I even tried assigning the values manually and tried the JSON way as demonstrated below but nothing works as I expected.

Parent Component: AppServers

<template>
  <div>
    <AppServerStatus v-for="server in servers"   :serverObj="JSON.parse(JSON.stringify(server))">
    </AppServerStatus>
    <hr>
    <button @click="changeStatus()">Change server 2</button>
  </div>
</template>

<script>
  import AppServerStatus from './AppServerStatus';

  export default {
    name: "AppServers",
    components: {
      AppServerStatus
    },
    data() {
      return {
        servers: [
          {
            name: 'server1',
            status: 'Critical'
          },
          {
            name: 'server2',
            status: 'Normal'
          },
          {
            name: 'server3',
            status: 'abnormal'
          },
          {
            name: 'server4',
            status: 'idle'
          },
          {
            name: 'server5',
            status: 'Good'
          },
        ],
        serverTmp: {}
      }
    },
    methods: {
      changeStatus(){
        this.servers[1].status = 'Active';
      }
    }
  }
</script>

Child Component: AppServerStatus

<template>
  <div>
    <h3>Server Name: {{ serverObj.name }}</h3>
    <p>Server Status: {{ serverObj.status }}</p>
    <hr>
  </div>
</template>

<script>
  export default {
    name: "AppServerStatus",
    data() {
      return {
        status: 'Critical'
      }
    },
    props: [
      'serverObj'
    ]
  }
</script>

I expect the value of status property in the object of the child component to stay Normal when I execute changeStatus() in the parent component but it changes also.

Create a new object from the serverObj prop on created or mounted to prevent unwanted reactivity.

<template>
  <div>
    <h3>Server Name: {{ server.name }}</h3>
    <p>Server Status: {{ server.status }}</p>
    <hr>
  </div>
</template>

<script>
  export default {
    name: 'AppServerStatus',
    data() {
      return {
        status: 'Critical',
        server: {
          name: '',
          status: ''
        }
      }
    },

    props: [
      'serverObj'
    ],

    mounted() {
       this.server = {
         name: this.serverObj.name,
         status: this.serverObj.status
       };
    }
  }
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM