我正在使用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()
属性。但是为什么以某种方式共享数据?只要我不将其传递给子组件(例如在输入字段中使用v-model),vue组件中的data
就应对此组件私有。
如果我在缓存中查看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
错误或功能?
答案 0 :(得分: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 };
},
},
},
};
请注意以下几点:
user
在data
中初始化manual: true
已设置,因此Vue Apollo不会自动设置user
result
中,我们使用跨度(或Object.assign)设置this.user
,以避免复制引用。如果对象具有多个级别,请考虑使用类似cloneDeep的东西。您需要在打算对查询结果进行变异的所有位置进行类似的修改。