VUE - объект данных всегда передается как ссылка или иногда копируется? - PullRequest
0 голосов
/ 09 мая 2020

У меня есть связанная с концепцией VUE.

Я немного не понимаю, как данные передаются в дочерние vue файлы. (vue экземпляров? Не знакомы с этим термином честно)

  1. В некоторых случаях данные изменяются в дочерних файлах vue, но не изменяют данные родителей, когда данные передается с помощью 'props'.

  2. С другой стороны, изменения данных в дочерних vue файлах фактически изменяют данные родителей.

Я только что столкнулся со случаем 2., когда данные передаются через шину событий.

Могу ли я понять эту природу, как показано ниже?

"Данные передаются как ссылка только когда данные передаются через шину событий "

while,

". Данные передаются дочернему элементу как отдельная копия, когда данные передаются через props и изменения в дочернем элементе не изменятся исходные данные в родительском "

Могу ли я увидеть природу 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>

1 Ответ

1 голос
/ 09 мая 2020

Vue не принимает копию при передаче объектов через реквизиты. Если вы передадите объект через опору, оба компонента будут видеть один и тот же объект. Поскольку это один и тот же объект, любые изменения свойств, внесенные дочерним элементом, также повлияют на другого родителя.

Посмотрите документацию об одностороннем потоке данных:

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

Первый абзац вводит в заблуждение и может заставить вас поверить в то, что копии делаются. В нем конкретно говорится о присвоении новых значений реквизитам, но формулировка неоднозначна. Однако это не так, и ключевое предложение находится в конце:

Обратите внимание, что объекты и массивы в JavaScript передаются по ссылке, поэтому, если опора является массивом или объектом, изменение самого объекта или массива внутри дочернего компонента будет влиять на родительское состояние.

Я не знаю, какова официальная причина отказа от копирования, но есть некоторые возможные причины:

  1. Создание копий приведет к снижению производительности.
  2. Это потенциально может привести к ошибкам в тех случаях, когда код полагается на равенство объектов.
  3. С технической точки зрения, копирование невозможно возможно во всех случаях. Простые, удобные для JSON данные могут быть скопированы, но в целом JavaScript имеет несколько конструкций, которые нельзя надежно скопировать, например функции с замыканиями.

Что касается вашего вопроса об испускании. ..

Создание событий изменения является частью одностороннего потока данных и владения данными. Идея состоит в том, что изменять их должен только владелец данных. Цель состоит в том, чтобы упростить рассуждение и отладку проблем.

На практике ничто не мешает дочернему элементу напрямую изменять объект, как вы описали. Вам нужно будет принимать собственные решения о том, что лучше всего для удобства сопровождения вашего кода.

Одна проблема заключается в том, что дочерний элемент связан с родительским. Изменение объекта в дочернем элементе работает только в том случае, если этот объект является окончательным источником истины для этих данных. Если, например, объект был создан в родительском элементе с использованием вычисляемого свойства, то его изменение не сработает. Используя $emit, мы передаем ответственность владельцу данных за решение правильного способа внесения необходимых изменений.

...