GraphQL 漸進(jìn)學(xué)習(xí) 09-graphql-apollo-client-vue-客戶端開發(fā)
軟件環(huán)境
- vue > 2.5.x
目標(biāo)
- 創(chuàng)建 graphql 客戶端
- 封裝請求處理
- 基于 token 驗(yàn)證
代碼
步驟
1 安裝依賴包
npm install
npm install --save vue-apollo graphql apollo-client apollo-link apollo-link-http apollo-cache-inmemory graphql-tag
-
webpack.json
包清單
"dependencies": {
"apollo-cache-inmemory": "^1.2.0",
"apollo-client": "^2.3.0",
"apollo-link": "^1.2.2",
"apollo-link-http": "^1.5.4",
"element-ui": "^2.3.7",
"graphql": "^0.13.2",
"graphql-tag": "^2.9.2",
"vue": "^2.5.2",
"vue-apollo": "^3.0.0-beta.5",
"vue-router": "^3.0.1"
},
如果遇到代碼編譯問題,請對照我使用的包版本
2 編寫 webpack
配置
- 文件
build/webpack.base.conf.js
module: {
rules: [
...
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
loader: 'graphql-tag/loader'
}
...
]
}
當(dāng)
import
時罗侯,對graphql
gql
擴(kuò)展名自動schema js
包裝如
import QUERY_USER from '@/graphql/user.graphql'
民宿,把QUERY_USER
打印看看
3 編寫 config.json
配置
- 文件
src/utils/config.json
{
"graphqlServer": "http://127.0.0.1:7001/graphql",
"tokenName": "UU_AUTH_TOKEN"
}
graphqlServer
服務(wù)器地址tokenName
本地寫localStorage
key
名稱 次绘,推薦大家做本地化可以用cookie
設(shè)置過期時間
4 編寫 VueApollo
適配器
- 文件
src/apolloProvider.js
import Vue from 'vue'
import {ApolloClient} from 'apollo-client'
import {HttpLink} from 'apollo-link-http'
import {InMemoryCache} from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
import { ApolloLink, concat, split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import Config from '@/utils/config.json'
Vue.use(VueApollo)
const httpLink = new HttpLink({
uri: Config.graphqlServer,
})
const authMiddleware = new ApolloLink((operation, forward) => {
const token = localStorage.getItem(Config.tokenName) || null
operation.setContext({
headers: {
Authorization: `Bearer ${token}`
}
});
return forward(operation);
})
const apolloClient = new ApolloClient({
link: concat(authMiddleware, httpLink),
cache: new InMemoryCache(),
connectToDevTools: true,
})
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
defaultOptions: {
$loadingKey: 'loading'
},
errorHandler (error) {
console.log('Global apollo error handler')
console.error(error)
}
})
export default apolloProvider
authMiddleware
中寫入Request headers token
apolloClient
中定義cache: new InMemoryCache()
- 文件
src/main.js
import apolloProvider from './apolloProvider'
...
new Vue({
el: '#app',
provide: apolloProvider.provide(),
...
})
5 編寫 schema
定義
- 項(xiàng)目中的請求定義 我都放在了 目錄
src/graphql
下,有點(diǎn)像restful
的api
定義
.
├── removeUser.graphql
├── user.graphql
└── users.graphql
- 我這里寫了 2 個查詢 1 個更新操作伟姐,名稱和服務(wù)端定義一致囤屹,這樣方便查詢修改
6 編寫 Graphql
請求
文件
src/components/HelloWorld.vue
官方
readme.md
中只寫了一種組件
方式調(diào)用,我還是喜歡api
方式
6.1 組件
方式
apollo: {
login: {
query: gql`
query queryFun($username: String!, $password: String!) {
user(username: $username, password: $password) {
id
name
token
}
}
`,
variables() {
return {
username: 'ducafecat',
password: '345457yftgyhdsfghre'
}
},
manual: true,
result({data, loading}) {
console.log(data, loading)
if (!loading) {
this.res = data
}
}
}
}
}
</script>
這種方式做查詢冤狡,適合功能單一的展示組件孙蒙,靈活性感覺還是差了點(diǎn),有興趣的可以去掉注釋大家體會下悲雳。
6.2 api
方式
-
query
查詢
import QUERY_USER from '@/graphql/user.graphql'
...
methods: {
handleLogin() {
this.clearData()
this.$apollo
.query({
// Query
query: QUERY_USER,
variables: {
username: 'ducafecat',
password: '12321321321321432'
},
})
.then(response => {
this.loading = false
this.res = response.data
localStorage.setItem(Config.tokenName, this.res.user.token)
alert('登錄成功挎峦,寫入Token完成,重新裝載 apolloProvider')
window.location.reload()
})
.catch(error => {
this.loading = false
this.err = error
})
},
-
mutate
更新
handleRemoveUser() {
this.clearData()
this.$apollo
.mutate({
// Query
mutation: MUTATION_REMOVE_USER,
variables: {
id: 123
}
})
.then(response => {
this.loading = false
this.res = response.data
})
.catch(error => {
this.loading = false
this.err = error
})
},
參考
1 文章
- vue-apollo
- Egg/GraphQL
- facebook/GraphQL
- GraphQL API v4
- github/authenticating-with-graphql
- VueConf 2017 demo