admin 管理员组

文章数量: 1086019

I have a concept-related in VUE.

I'm little bit confused about how data is passed to the child vue files. (vue instances? not familiar with the term honestly)

  1. In some cases, the data changes in the child vue files doesn't change the data of parents when the data is passed by 'props'.

  2. On the other hand, the data changes in child vue files, actually changes the data of parents.

I just encountered the case 2. which is when the data is passed through eventbus.

Can I understand this nature as below?

"Data is passed as a reference only when the data is passed via eventbus"

while,

"Data is apssed to the child as a seperate copy when the data is passed via props and the changes in the child will not change the original data in the parent"

Can I see the Vue nature in the way? It would be very grateful if someone could give me an example that the changes in child don't affect the data in the parent.

Always feel very guilty everytime I ask Vue-related quesitons cause the code is super long different from just Javascript questions. Thank you in advance.

The example I just ran into is as below.

=main.js=

import Vue from 'vue'
import App from './App.vue'

export const serverBus = new Vue()
new Vue({
  el: '#app',
  render: h => h(App)
})

=Servers.vue=

<template>
    <div class="col-xs-12 col-sm-6">
        <ul class="list-group">
            <Server v-for='server in serverinfo' :serverinfo='server' :key='server.id'></Server>
        </ul>
    </div>
</template>

<script>

import Server from './server.vue'

export default {

 ponents: {
        Server
    },

data() {
    return {
                serverinfo: [
                {id:1, servno:'#1', servstat:'normal'},
                {id:2, servno:'#2', servstat:'critical'},
                {id:3, servno:'#3', servstat:'unknown'},
                {id:4, servno:'#4', servstat:'error'},
                {id:5, servno:'#5', servstat:'excellent'}]
               }
              }

    }



</script>

<style>

</style>

=server.vue=

<template>
  <li class='list-group-item' @click='serverselected'>
      Server {{serverinfo.servno}}
  </li>
</template>

<script>
import {serverBus} from '../../main.js'
export default {
    props:['serverinfo'],

    methods:{
        serverselected(){
            serverBus.$emit('serverselected', this.serverinfo)
        }
    }

}
</script>

<style>

</style>

=ServerDetails.vue=

<template>
    <div class="col-xs-12 col-sm-6">
        <p v-if='!server'>Please Select a server</p>
        <p v-else>Server {{server.servno}} is selected. Status:{{server.servstat}}</p>
        <button class="btn btn-primary" @click='backtonormal'>Back to Normal</button>
    </div>

</template>

<script>
import {serverBus} from '../../main.js'

export default{
    methods:{
        backtonormal(){
            this.server.servstat='normal'
        }
    },

    data(){
        return{
        server:null
              }
    },

    created(){
        serverBus.$on('serverselected',(server)=>{
            this.server=server
        })
    }

}
</script>

<style>

</style>

I have a concept-related in VUE.

I'm little bit confused about how data is passed to the child vue files. (vue instances? not familiar with the term honestly)

  1. In some cases, the data changes in the child vue files doesn't change the data of parents when the data is passed by 'props'.

  2. On the other hand, the data changes in child vue files, actually changes the data of parents.

I just encountered the case 2. which is when the data is passed through eventbus.

Can I understand this nature as below?

"Data is passed as a reference only when the data is passed via eventbus"

while,

"Data is apssed to the child as a seperate copy when the data is passed via props and the changes in the child will not change the original data in the parent"

Can I see the Vue nature in the way? It would be very grateful if someone could give me an example that the changes in child don't affect the data in the parent.

Always feel very guilty everytime I ask Vue-related quesitons cause the code is super long different from just Javascript questions. Thank you in advance.

The example I just ran into is as below.

=main.js=

import Vue from 'vue'
import App from './App.vue'

export const serverBus = new Vue()
new Vue({
  el: '#app',
  render: h => h(App)
})

=Servers.vue=

<template>
    <div class="col-xs-12 col-sm-6">
        <ul class="list-group">
            <Server v-for='server in serverinfo' :serverinfo='server' :key='server.id'></Server>
        </ul>
    </div>
</template>

<script>

import Server from './server.vue'

export default {

 ponents: {
        Server
    },

data() {
    return {
                serverinfo: [
                {id:1, servno:'#1', servstat:'normal'},
                {id:2, servno:'#2', servstat:'critical'},
                {id:3, servno:'#3', servstat:'unknown'},
                {id:4, servno:'#4', servstat:'error'},
                {id:5, servno:'#5', servstat:'excellent'}]
               }
              }

    }



</script>

<style>

</style>

=server.vue=

<template>
  <li class='list-group-item' @click='serverselected'>
      Server {{serverinfo.servno}}
  </li>
</template>

<script>
import {serverBus} from '../../main.js'
export default {
    props:['serverinfo'],

    methods:{
        serverselected(){
            serverBus.$emit('serverselected', this.serverinfo)
        }
    }

}
</script>

<style>

</style>

=ServerDetails.vue=

<template>
    <div class="col-xs-12 col-sm-6">
        <p v-if='!server'>Please Select a server</p>
        <p v-else>Server {{server.servno}} is selected. Status:{{server.servstat}}</p>
        <button class="btn btn-primary" @click='backtonormal'>Back to Normal</button>
    </div>

</template>

<script>
import {serverBus} from '../../main.js'

export default{
    methods:{
        backtonormal(){
            this.server.servstat='normal'
        }
    },

    data(){
        return{
        server:null
              }
    },

    created(){
        serverBus.$on('serverselected',(server)=>{
            this.server=server
        })
    }

}
</script>

<style>

</style>
Share Improve this question asked May 8, 2020 at 22:58 BS100BS100 8739 silver badges27 bronze badges 2
  • 1 Vue does not take a copy when you pass objects via props. If you pass an object via a prop then both ponents will be seeing the same object. – skirtle Commented May 8, 2020 at 23:29
  • @skirtle if so, even if I make some changes in the child vue, it would change the data in the parents? if so, why do I need to use "emit"? or Emit is necessary only when the data is not passed from parents vis 'props'? – BS100 Commented May 9, 2020 at 0:11
Add a ment  | 

1 Answer 1

Reset to default 6

Vue does not take a copy when you pass objects via props. If you pass an object via a prop then both ponents will be seeing the same object. As it's the same object, any property changes made by the child will also impact the other parent.

Take a look at the documentation about one-way data flow:

https://v2.vuejs/v2/guide/ponents-props.html#One-Way-Data-Flow

The opening paragraph is a little misleading and might cause you to believe that copies are taken. It is specifically talking about assigning new values to props but the wording is ambiguous. However, that isn't the case and the key sentence is at the end:

Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child ponent will affect parent state.

I don't know what the official reason is for not taking copies but some possible reasons are:

  1. Taking copies would incur a performance penalty.
  2. It could potentially lead to bugs in cases where code relies on object equality.
  3. Taking copies isn't technically possible in all cases. Simple, JSON-friendly data can be copied but in general JavaScript has several constructs that can't reliably be copied, such as functions with closures.

As for your question about emitting...

Emitting change events is part of one-way data flow and data ownership. The idea is that only the owner of the data should modify it. The intention is that it makes it easier to reason about and debug problems.

In practice there is nothing stopping a child modifying an object directly as you've described. You will need to make your own decisions about what is best for the maintainability of your code.

One problem is that the child is coupled to the parent. Modifying the object in the child only works if that object is the ultimate source of truth for that data. If, for example, the object were created in the parent using a puted property then modifying it wouldn't work. By using $emit we're passing responsibility to the data's owner to decide the correct way to make the required changes.

本文标签: javascriptVUEdata object is passed as a reference always or sometimes it is copiedStack Overflow