VUE - 数据对象总是作为引用传递,还是有时被复制?

问题描述 投票:0回答:1

我在VUE中有一个概念。

我对如何将数据传递给子 vue 文件有点困惑。(vue 实例?

  1. 在某些情况下,当数据由'props'传递时,孩子的vue文件中的数据变化并没有改变父母的数据。

  2. 另一方面,在子虚文件中的数据变化,实际上改变了父母的数据。

我只是遇到了2.就是数据通过事件总线传递的情况。

我可以把这种性质理解为以下几点吗?

"只有当数据通过eventbus传递时,数据才会作为引用传递"

而。

"当数据被传递给孩子时,数据会作为一个单独的副本被传递给孩子。道具 而子代的变化不会改变父代的原始数据"

我可以看到Vue本质的方式吗?如果有人能给我一个例子,在孩子的变化不影响在父的数据,这将是非常感激。

每次我问Vue相关的quesitons总是感到非常内疚,因为代码超级长,不同于单纯的Javascript问题。先谢谢你了。

我刚才碰到的例子如下。

=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 {

 components: {
        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>
javascript vue.js data-visualization
1个回答
1
投票

当你通过道具传递对象时,Vue不会采取复制。如果你通过道具传递一个对象,那么两个组件将看到同一个对象。由于是同一个对象,子对象所做的任何属性变化也会影响到另一个父对象。

请看一下关于单向数据流的文档。

https:/vuejs.orgv2guidecomponents-props.html#单向数据流。

开头一段有点误导,可能会让你认为副本是被拿走的。它具体说的是给道具赋予新的价值,但措辞含糊不清。然而,事实并非如此,关键句子在最后。

请注意,JavaScript中的对象和数组都是通过引用来传递的,所以如果道具是一个数组或对象,那么在子组件中突变对象或数组本身的内容 影响母国。

我不知道官方不收复印件的原因是什么,但一些可能的原因是。

  1. 拷贝会导致性能下降
  2. 在代码依赖于对象平等的情况下,它可能会导致错误。
  3. 从技术上讲,并不是所有情况下都可以采取副本。简单的、对JSON友好的数据可以被复制,但一般来说,JavaScript有几个结构不能可靠地被复制,比如带有闭包的函数。

至于你提出的发射问题......

发出变化事件是单向数据流和数据所有权的一部分。这个想法是,只有数据的所有者才应该修改数据。这样做的目的是为了更容易推理和调试问题。

在实践中,没有什么可以阻止子代直接修改对象,就像你所描述的那样。你需要自己决定什么是对你的代码的可维护性最好的。

其中一个问题是,子程序是与父程序耦合的。只有当该对象是该数据的最终真相来源时,修改子对象才会有效。比如说,如果对象是在父对象中使用计算属性创建的,那么修改它就不行了。通过在父对象中使用 $emit 我们将责任转嫁给数据的所有者,让他们决定以正确的方式进行所需的更改。

© www.soinside.com 2019 - 2024. All rights reserved.