来自 Vuex 的 Apollo 请求
Posted
技术标签:
【中文标题】来自 Vuex 的 Apollo 请求【英文标题】:Apollo request from Vuex 【发布时间】:2020-07-28 21:55:02 【问题描述】:谁能告诉我可以从哪里导入apolloClient
以便我可以向 apollo 发出请求?
我通常会收到一个错误,要么 mutate is not a function(即使我从 Vue 组件传入this.$apollo
)
我只是想进入 Vue 的方式。如果有任何关于代码和结构的提示,我将不胜感激
登录组件
<template>
<div class="signIn-component">
<form @submit.prevent="signInUser()">
<input
type="email"
placeholder="Enter your email"
v-model="formInput.email"
/>
<input
type="password"
placeholder="Enter your password"
v-model="formInput.password"
/>
<button>Sign In</button>
</form>
</div>
</template>
<script>
import createNamespacedHelpers from "vuex";
const mapActions = createNamespacedHelpers("auth");
export default
data()
return
formInput:
email: null,
password: null
;
,
methods:
// Vuex Actions
...mapActions(["signIn"]),
signInUser: function()
// eslint-disable-next-line no-unused-vars
this.signIn(this.formInput, this.$apollo).then(_ =>
this.$route.push("/")
);
;
</script>
<style></style>
Vuex.auth
import apolloClient from 'vue-cli-plugin-apollo/graphql-client';
import SignInGQL from "@/graphql/signIn.gql";
export default
namespaced: true,
state:
token: null,
user: ,
authStatus: false
,
getters:
isAuthenticated: state => !!state.token,
authStatus: state => state.authStatus,
user: state => state.user
,
actions:
async signIn( commit, dispatch , formInput)
console.log('here');
try
const data = await apollo.mutate(
mutation: SignInGQL,
variables: ...formInput
)
const token = data.signIn;
console.log(token);
commit('setToken', token);
localStorage.setItem('auth-token', token);
dispatch('setUser', token);
catch (e)
console.error(e)
,
setUser( commit , token)
const encodedPayload = token.split('.')[1];
const payload = JSON.parse(atob(encodedPayload));
console.log('payload: ', payload);
// TODO: Set User information
commit('signInUser', payload);
,
mutations:
setToken(state, token)
state.token = token
,
signInUser(state, user)
state.authStatus = true
state.user = ...user
,
// logOutUser(state)
// state.authStatus = ''
// state.token = '' && localStorage.removeItem('auth-token')
//
【问题讨论】:
【参考方案1】:This question explains adding headers to apollo client
solution repo
import setContext from "apollo-link-context";
import ApolloClient, InMemoryCache, HttpLink from "apollo-boost";
import VueApollo from "vue-apollo";
Vue.use(VueApollo);
const httpLink = new HttpLink(
uri: "http://sebapi.com/graphql"
);
const authLink = setContext((_, headers ) =>
// get the authentication token from ApplicationSettings if it exists
const token = ApplicationSettings.getString("token");
// return the headers to the context so HTTP link can read them
return
headers:
...headers,
authorization: token ? `Bearer $token` : null
;
);
// update apollo client as below
const apolloClient = new ApolloClient(
link: authLink.concat(httpLink),
cache: new InMemoryCache()
);
const apolloProvider = new VueApollo(
defaultClient: apolloClient
);
和 LOGIN.VUE
<script lang="ts">
export default
data()
return
jwt: "",
user:
identifier: "test",
password: "123123",
,
;
,
methods:
handleLogin()
request(
url: "http://sebapi.com/auth/local",
method: "POST",
headers: "Content-Type": "application/json" ,
content: JSON.stringify(
identifier: this.user.identifier,
password: this.user.password,
),
)
.then(
(response) =>
const result = response.content.toJSON();
console.log("Result from Server: ", result);
//ignore applicationsettings it's just a kind of localstore in nativescript
ApplicationSettings.setString("token", result.jwt);
,
(e) =>
console.error(e);
//ignore nativateto its routing in nativescript
this.$navigateTo(routes.login);
)
.then(() =>
this.$navigateTo(routes.app);
);
,
,
;
</script>
【讨论】:
默认情况下,Vue-Apollo 文件导出函数“createProvider”(如果您使用 Vue Apollo 的 cli 版本)。而持有 ApolloClient 的“createApolloClient”在“createRrovider”中被声明。我将 createApolloClient 移到了 CreateProvider 之外,将其导出到那里,然后将其导入到我的商店文件中。默认情况下,标题是在后台实现的。我只是简单地添加了我保存令牌的 localStorage 文件的名称。我在 Vuex 存储中使用 Apollo 时遇到了麻烦。我不想修补自己的实现,因为我使用了 Vue-Apollo 您是否使用其他路由器而不是 Vue 内置路由器?我注意到“this.$navigateTo”。或者您只是全局分配了自己的导航服务?我是这个框架的新手——很多关于实践和经验的问题 @Valaryo 这只是在 nativescript-vue 中导航的另一种方式Manual routing 我知道了。谢谢!【参考方案2】:我就是这样做的,以防有人正在寻找相同的答案:
import Vue from 'vue'
import VueApollo from 'vue-apollo'
import createApolloClient from 'vue-cli-plugin-apollo/graphql-client'
// Install the vue plugin
Vue.use(VueApollo)
// Name of the localStorage item
const AUTH_TOKEN = 'auth-token'
// Http endpoint
const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:3000/graphql';
// Config
const defaultOptions =
// You can use `https` for secure connection (recommended in production)
httpEndpoint,
// You can use `wss` for secure connection (recommended in production)
// Use `null` to disable subscriptions
wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || null,
// wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:3000/graphql',
// LocalStorage token
tokenName: AUTH_TOKEN,
// Enable Automatic Query persisting with Apollo Engine
persisting: false,
// Use websockets for everything (no HTTP)
// You need to pass a `wsEndpoint` for this to work
websocketsOnly: false,
// Is being rendered on the server?
s-s-r: false,
// Override default apollo link
// note: don't override httpLink here, specify httpLink options in the
// httpLinkOptions property of defaultOptions.
// httpLinkOptions:
// headers:
// Authorization: authHeader
//
//
// Override default cache
// cache: myCache
// Override the way the Authorization header is set
// getAuth: (tokenName) => getUserToken(),
// Additional ApolloClient options
// apollo: ...
// Client local data (see apollo-link-state)
// clientState: resolvers: ... , defaults: ...
export const apolloClient, wsClient = createApolloClient(
...defaultOptions,
// ...options,
)
// Call this in the Vue app file
export function createProvider()
// Create apollo client
apolloClient.wsClient = wsClient
// Create vue apollo provider
const apolloProvider = new VueApollo(
defaultClient: apolloClient,
defaultOptions:
$query:
fetchPolicy: 'cache-and-network',
,
,
errorHandler(error)
// eslint-disable-next-line no-console
console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
,
)
return apolloProvider
This is the source I found the solution
如果您有任何建议,请随时将它们留在此处!
【讨论】:
以上是关于来自 Vuex 的 Apollo 请求的主要内容,如果未能解决你的问题,请参考以下文章
Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求
使用 Apollo 和 GraphQL 缓存而不是 Vuex?