面试题答案
一键面试利用 Apollo Client 实现数据缓存思路
- 配置 Apollo Client:在 Vue 应用中,创建 Apollo Client 实例时,默认情况下 Apollo Client 会启用一个 in-memory cache。这个缓存会自动存储从 GraphQL 服务器获取的查询结果。
- 查询操作:当执行查询时,Apollo Client 首先会检查缓存中是否有匹配的查询结果。如果有,它会直接从缓存中返回数据,而不是再次向服务器发送请求,从而提高应用性能。
关键代码示例
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
const httpLink = createHttpLink({
uri: 'YOUR_GRAPHQL_SERVER_URI'
});
const cache = new InMemoryCache();
const client = new ApolloClient({
link: httpLink,
cache
});
在 Vue 组件中使用查询:
<template>
<div>
<ul>
<li v-for="todo in todos" :key="todo.id">{{ todo.text }}</li>
</ul>
</div>
</template>
<script>
import { gql, useQuery } from '@apollo/client';
const GET_TODOS = gql`
query GetTodos {
todos {
id
text
}
}
`;
export default {
setup() {
const { data } = useQuery(GET_TODOS);
return {
todos: data?.todos || []
};
}
};
</script>
数据变化后更新缓存思路
- Mutation 操作:当执行 mutation 操作(如创建、更新或删除数据)时,需要手动更新缓存以保持 UI 数据一致性。
- 更新策略:
- Optimistic Updates:在向服务器发送 mutation 请求前,先乐观地更新缓存,这样用户能立即看到 UI 更新,提高用户体验。当服务器响应回来后,如果成功,缓存状态不变;如果失败,需要回滚缓存。
- Refetch Queries:mutation 操作后,重新执行相关查询,从服务器获取最新数据并更新缓存。
- Direct Cache Updates:直接修改缓存数据,这种方式更高效,但需要准确知道如何修改缓存。
关键代码示例(Direct Cache Updates)
假设我们有一个创建 todo 的 mutation:
import { gql, useMutation } from '@apollo/client';
const CREATE_TODO = gql`
mutation CreateTodo($text: String!) {
createTodo(text: $text) {
id
text
}
}
`;
export default {
setup() {
const { mutate } = useMutation(CREATE_TODO, {
update(cache, { data: { createTodo } }) {
const data = cache.readQuery({ query: GET_TODOS });
data.todos.push(createTodo);
cache.writeQuery({ query: GET_TODOS, data });
}
});
const createNewTodo = (text) => {
mutate({ variables: { text } });
};
return {
createNewTodo
};
}
};
在上述代码中,update
函数在 mutation 成功返回后,从缓存中读取当前的 todos
数据,将新创建的 todo 添加到数组中,然后再写回缓存,从而实现缓存更新。
关键代码示例(Optimistic Updates)
import { gql, useMutation } from '@apollo/client';
const CREATE_TODO = gql`
mutation CreateTodo($text: String!) {
createTodo(text: $text) {
id
text
}
}
`;
export default {
setup() {
const { mutate } = useMutation(CREATE_TODO, {
optimisticResponse: (variables) => {
return {
createTodo: {
id: -1, // 临时 id
text: variables.text,
__typename: 'Todo'
}
};
},
update(cache, { data: { createTodo } }) {
const data = cache.readQuery({ query: GET_TODOS });
data.todos.push(createTodo);
cache.writeQuery({ query: GET_TODOS, data });
}
});
const createNewTodo = (text) => {
mutate({ variables: { text } });
};
return {
createNewTodo
};
}
};
在这个示例中,optimisticResponse
函数在 mutation 还未得到服务器响应时,就返回一个乐观的响应数据,Apollo Client 会立即用这个数据更新缓存,让用户看到 UI 变化。update
函数在服务器响应回来后进一步处理缓存更新。