为什么用vue-apollo在两个独立的组件之间共享组件数据?
Why is component data shared between two independent components with vue-apollo?
我正在使用 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>
两个组件显示在同一页面上,绝对没有涉及突变。就是这两个简单的 components.That 全部
只要我在输入字段中更改名称,用户名就会在视图中更新。
我觉得这很奇怪,我不喜欢它。
Apollo 正在执行查询并填充每个组件的 vue data()
属性。但为什么数据以某种方式共享? data
在 vue 组件中,只要我不将它传递给子组件(就像输入字段中的 v-model 一样),该组件就应该是私有的。
如果我查看缓存中的 Apollo Dev Console,我看不到名字的变化。那么它是如何工作的呢?
如果我不想要这种行为,我只有一个奇怪的选择:
我可以像这样向查询添加另一个属性:
<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>
向查询添加 "age" 会更改行为。那更陌生了!我如何编写具有这种行为的可靠组件?还是我错过了一些关键概念?
源代码可以在这里找到:
https://github.com/kicktipp/hello-apollo
错误或功能?
我看过你的代码,我很确定我知道发生了什么。
如果您通读 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 };
},
},
},
};
注意以下几点:
user
在 data
中初始化
manual: true
已设置,因此 Vue Apollo 不会自动设置 user
- 在
result
中,我们使用跨页(或 Object.assign)设置 this.user
以避免复制引用。如果对象有多于一层,请考虑使用类似 cloneDeep. 的东西
您需要在您打算改变查询结果的所有地方进行类似的修改。
我正在使用 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>
两个组件显示在同一页面上,绝对没有涉及突变。就是这两个简单的 components.That 全部
只要我在输入字段中更改名称,用户名就会在视图中更新。
我觉得这很奇怪,我不喜欢它。
Apollo 正在执行查询并填充每个组件的 vue data()
属性。但为什么数据以某种方式共享? data
在 vue 组件中,只要我不将它传递给子组件(就像输入字段中的 v-model 一样),该组件就应该是私有的。
如果我查看缓存中的 Apollo Dev Console,我看不到名字的变化。那么它是如何工作的呢?
如果我不想要这种行为,我只有一个奇怪的选择:
我可以像这样向查询添加另一个属性:
<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>
向查询添加 "age" 会更改行为。那更陌生了!我如何编写具有这种行为的可靠组件?还是我错过了一些关键概念?
源代码可以在这里找到: https://github.com/kicktipp/hello-apollo
错误或功能?
我看过你的代码,我很确定我知道发生了什么。
如果您通读 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 };
},
},
},
};
注意以下几点:
user
在data
中初始化
manual: true
已设置,因此 Vue Apollo 不会自动设置 - 在
result
中,我们使用跨页(或 Object.assign)设置this.user
以避免复制引用。如果对象有多于一层,请考虑使用类似 cloneDeep. 的东西
user
您需要在您打算改变查询结果的所有地方进行类似的修改。