Vue Apollo 也支援 GraphQL 的 Fragment,讓我們將 Field 重複部分抽成 Fragment 方便維護。
Version
macOS Catalina 10.15.2
WebStorm 2019.3
Node 12.4.0
Vue CLI 4.1.1
Vue 2.6.10
Vue Apollo 3.0.0-beta.11
Vue Apollo
src/App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in books" :key="index">
{{ item.title }}:{{ item.price }} / {{ item.quantity }}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag'
let query = gql(`
query {
books {
title
price
quantity
}
}
`)
export default {
name: 'app',
apollo: {
books: {
query
}
}
}
</script>
14 行
let query = gql(`
query {
books {
title
price
quantity
}
}
`)
使用 books
query,且回傳 title
、price
與 quantity
3 個 field。
Fragment
src/App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in books" :key="index">
{{ item.title }}:{{ item.price }} / {{ item.quantity }}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag'
let query = gql(`
query {
books {
...bookFields
}
}
fragment bookFields on Book {
title
price
quantity
}
`)
export default {
name: 'app',
apollo: {
books: {
query
}
}
}
</script>
14 行
let query = gql(`
query {
books {
...bookFields
}
}
fragment bookFields on Book {
title
price
quantity
}
`)
若 title
、price
與 quantity
3 個 field 在其他 query 也使用,可使用 fragment
將這些 field 宣告成 fragment,on
後面接 type。
之後在 query 可使用類似 ES6 的 ...
spread operator 將其展開,如此多個 query 都可共用該 fragment。
src/App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in books" :key="index">
{{ item.title }}:{{ item.price }} / {{ item.quantity }}
</li>
</ul>
</div>
</template>
<script>
import gql from 'graphql-tag'
let books = function() {
let query = gql`
query {
books {
...bookFields
}
}
${ this.$options.fragments.bookFields }
`
return { query }
}
let bookFields = gql`
fragment bookFields on Book {
title
price
quantity
}
`
export default {
name: 'app',
apollo: {
books
},
fragments: {
bookFields
}
}
</script>
之前 fragment 寫法雖然能達到 query 間共用,但仍不夠靈活,需侷限在同一個 smart query 內。
34 行
export default {
name: 'app',
apollo: {
books
},
fragments: {
bookFields
}
}
比較理想的方式是在 fragments
property 下令外宣告 bookFields
fragment。
26 行
let bookFields = gql`
fragment bookFields on Book {
title
price
quantity
}
`
定義 bookFields
fragment。
14 行
let books = function() {
let query = gql`
query {
books {
...bookFields
}
}
${ this.$options.fragments.bookFields }
`
return { query }
}
在 books
query 中使用 this.$options.fragments
取得 bookFields
fragment,由於使用了 this
,因此必須使用 function expression,不能使用 arrow function。
Conclusion
- Vue Apollo 目前若使用 fragment,無法使用 Webpack Loader 寫法將 query 與 fragment 獨立出
*.graphql
,只能使用gql()
動態將 string 轉成 GraphQL AST