Почему данные компонента совместно используются двумя независимыми компонентами с помощью vue-apollo? - PullRequest
1 голос
/ 28 сентября 2019

Я работаю над новым проектом с vue и vue-apollo.

У меня есть один компонент с именем пользователя (UserShow.vue):

<template>
    <div v-if="!this.$apollo.queries.user.loading">
        Your name is: {{user.firstname}}
    </div>
</template>
<script>
    import gql from "graphql-tag";
    export default {
        apollo: {
            user: {
                query: gql`{
                   user (id: 1) {
                     id
                     firstname
                   }
                }`
            }
        }
    }
</script>

и один компонент для редактирования (UserEdit.vue):

<template>
    <div v-if="!this.$apollo.queries.user.loading">
        Edit your name: <input v-model="user.firstname" />
    </div>
</template>

<script>
    import gql from "graphql-tag";
    export default {
        apollo: {
            user: {
                query: gql`{
                   user (id: 1) {
                     id
                     firstname
                   }
                }`
            }
        }
    }
</script>

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

Как только я изменю имя в поле ввода, имя пользователя обновляется в представлении.

Мне странно, и мне это не нравится.

Apollo выполняет запрос и заполняет свойство vue data() каждого компонента.Но почему данные каким-то образом передаются?data в компоненте vue должен быть закрытым для этого компонента, если я не передаю его субкомпоненту (как с v-моделью в поле ввода).

Если я загляну в свой Apollo DevКонсоль в кеш я не вижу изменения в имени.Так как же это работает?

Если я не хочу такого поведения, у меня есть только одна странная опция:

Я могу добавить еще один атрибут в запрос следующим образом:

<template>
    <div v-if="!this.$apollo.queries.user.loading">
        Edit your name:
        <input v-model="user.firstname" />
    </div>
</template>

<script>
    import userQuery from "./user";
    import gql from "graphql-tag";
    export default {
        apollo: {
            user: {
                query: gql`{
                   user (id: 1) {
                     id
                     firstname
                     age         // added to create a different query
                   }
                }`
            }
        }
    }
</script>

Добавление «возраста» к запросу меняет поведение.Это даже незнакомец!Как я могу написать надежные компоненты с таким поведением?Или я пропустил какую-то важную концепцию?

Исходный код можно найти здесь: https://github.com/kicktipp/hello-apollo

Ошибка или функция?

1 Ответ

1 голос
/ 30 сентября 2019

Я посмотрел ваш код, и я почти уверен, что знаю, что происходит.

Если вы прочитаете эту ветку , вы увидите, что данные возвращаются из запросов.Первоначально Аполлон предполагал быть неизменным (вы не должны использовать его как v-model).Фактически, он был заморожен, поэтому попытки использовать его в качестве источника данных привели к нарушению реактивности.

Затем это произошло .Теперь результаты запроса являются изменяемыми, и вы изменяете внутренние данные Apollo.

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

Вместо этого попробуйте что-то подобное:

import userQuery from './user';

export default {
  data() {
    return { user: {} };
  },
  apollo: {
    user: {
      query: userQuery,
      manual: true,
      result({ data }) {
        this.user = { ...data.user };
      },
    },
  },
};

Обратите внимание на следующее:

  • user инициализируется в data
  • manual: true установлено, поэтому user неавтоматически устанавливается Vue Apollo
  • В result мы устанавливаем this.user с использованием разворота (или Object.assign), чтобы избежать копирования ссылки.Если объект имеет более одного уровня, подумайте о том, чтобы использовать что-то вроде cloneDeep .

Вам необходимо будет вносить аналогичные изменения во всех местах, где вы собираетесь изменять результаты запроса.

...