为啥用 vue-apollo 在两个独立组件之间共享组件数据?

Posted

技术标签:

【中文标题】为啥用 vue-apollo 在两个独立组件之间共享组件数据?【英文标题】:Why is component data shared between two independent components with vue-apollo?为什么用 vue-apollo 在两个独立组件之间共享组件数据? 【发布时间】:2020-01-28 14:59:59 【问题描述】:

我正在使用 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() 属性。但是为什么数据会以某种方式共享呢? vue 组件中的data 应该是该组件私有的,只要我不将它传递给子组件(就像输入字段中的 v-model 一样)。

如果我查看我的 Apollo 开发控制台进入缓存,我看不到名字的变化。那么它是如何工作的呢?

如果我不想要这种行为,我只有一个奇怪的选择:

我可以像这样向查询中添加另一个属性:

<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

错误或功能?

【问题讨论】:

是否调用了此处未显示的突变? 没有。绝对没有突变。我编辑问题 也许不是阿波罗做出改变?据我所知,阿波罗缓存只会在突变后更新。如果没有调用,那么似乎必须有其他东西在同步这些值。 我将代码添加到github并添加了一个链接。目前 fakeql API 无法正常工作,因为它们有停机时间。我希望它很快再次工作 【参考方案1】:

我看了你的代码,我很确定我知道发生了什么。

如果您通读this thread,您会发现查询返回的数据最初由 Apollo 设计为不可变的(您不应将其用作v-model)。事实上,它曾经被冻结,因此尝试将其用作数据源会导致反应中断。

然后this happened。现在查询结果是可变的,你正在改变 Apollo 的内部数据。

这解释了为什么一个更新会立即修改具有相同查询的另一个组件的显示输出。

试试这样的:

import userQuery from './user';

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

注意以下几点:

userdata 中初始化 manual: true 已设置,因此 Vue Apollo 不会自动设置 userresult 中,我们使用展开(或Object.assign)设置this.user 以避免复制引用。如果对象有多个级别,请考虑使用 cloneDeep 之类的内容。

您需要在您打算改变查询结果的所有地方进行类似的修改。

【讨论】:

非常感谢。我查看了源代码,你是对的。只需注意一点:如果您更改数据,则不会更改您编写的查询缓存,而是更改内部数据引用的 $apolloData 对象。见github.com/Akryum/vue-apollo/blob/…

以上是关于为啥用 vue-apollo 在两个独立组件之间共享组件数据?的主要内容,如果未能解决你的问题,请参考以下文章

两个独立组件之间的通信 angular 2

Vue-apollo 从另一个组件重新获取查询

如何在 Vuepress 站点中使用 vue-apollo?

Vue-Apollo 和查询自动完成

Angular 8在两个组件之间发送数据[重复]

在 Vue-apollo 中使用 gql-tag 构造查询字符串