VUE-Data对象始终作为引用传递,还是有时被复制?

2022-03-02 00:00:00 data-visualization javascript vue.js

我有一个与VUE相关的概念。

我对如何将数据传递给子VUE文件感到有点困惑。 (VUE实例?诚实地说,不熟悉这个术语)

  1. 在某些情况下,子VUE文件中的数据更改不会更改父项的数据 当数据由"props"传递时。

  2. 另一方面,子VUE文件中的数据更改,实际上更改了父级的数据。

我刚刚遇到了案例2。 这是数据通过Eventbus传递的时间。

我可以按如下方式理解此性质吗?

"数据仅在以下情况下作为引用传递 数据通过Eventbus传递"

While,

"当数据通过道具传递时,数据将作为单独的副本传递到子级,子级中的更改不会更改父级中的原始数据"

我可以在路上看到Vue大自然吗? 如果有人能给我举一个例子,说明子项中的更改不会影响父项中的数据,我将不胜感激。

每次我问与Vue相关的问题时,总是感到非常内疚,因为代码非常长,不同于单纯的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>

解决方案

当您通过道具传递对象时,Vue不获取副本。如果通过道具传递对象,则两个组件将看到相同的对象。因为它是同一对象,所以子对象所做的任何属性更改也会影响另一个父对象。

查看有关单向数据流的文档:

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

开头的段落有点误导,可能会让您认为副本被拿走了。它具体谈到了赋予道具新的价值,但措辞含糊不清。然而,事实并非如此,关键一句在末尾:

请注意,JavaScript中的对象和数组是通过引用传递的,因此如果属性是数组或对象,则子组件内的对象或数组本身发生变异将影响父状态。

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

  1. 复制将导致性能下降。
  2. 在代码依赖于对象相等性的情况下,这可能会导致错误。
  3. 在技术上并不是所有情况下都可以复制。可以复制简单的JSON友好数据,但通常JavaScript有几个不能可靠复制的结构,例如带有闭包的函数。

关于您关于排放的问题.

发出更改事件是单向数据流和数据所有权的一部分。其想法是只有数据的所有者才能修改它。其目的是使推理和调试问题变得更容易。

在实践中,没有什么可以阻止孩子按照您所描述的那样直接修改对象。您需要自行决定哪些内容最有利于代码的可维护性。

一个问题是子级耦合到父级。仅当该对象是该数据的最终真值来源时,修改子对象中的对象才有效。例如,如果对象是使用计算属性在父级中创建的,则修改它将不起作用。通过使用$emit,我们将责任传递给数据的所有者,以决定进行所需更改的正确方式。

相关文章