Vue + GraphQL初試

  • 基本用法
  • GraphQL概述
    • GraphQL基本語法特性
    • GraphQL類型系統
    • GraphQL類型系統內置基礎類型
    • GraphQL類型系統內置修飾符
    • GraphQL工做原理
    • GraphQL執行過程
  • Vue工程接入GraphQL

基本用法(如何去用)

package.jsonvue

"dependencies": {
	"apollo-server-koa": "^1.3.6",
	"graphql": "^0.13.2",
	"graphql-import": "^0.6.0",
	"graphql-tools": "^3.0.2",
	"koa": "^2.5.1",
	"koa-bodyparser": "^4.2.1",
	"koa-router": "^7.4.0",
	"koa-websocket": "^5.0.1"
},
"devDependencies": {
	"babel-cli": "^6.26.0",
	"babel-preset-env": "^1.7.0"
}
複製代碼

server.jsjava

import koa from 'koa' import koaRouter from 'koa-router' import koaBody from 'koa-bodyparser' import websocketify from 'koa-websocket' import { graphqlKoa, graphiqlKoa } from 'apollo-server-koa' import { makeExecutableSchema } from 'graphql-tools' const app = websocketify(new koa()) const router = new koaRouter() const PORT = 3000 // fake data const moments = [ { user: { id: 1000, name: '銳雯', avatar: 'http://imgsrc.baidu.com/imgad/pic/item/42a98226cffc1e17d31927154090f603738de974.jpg' }, main: { content: '這是一條朋友圈', pics: [ 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529219875063&di=bc0bcc78ae800c1c21c198f52697f515&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F4a36acaf2edda3ccd53548ea0be93901203f9223.jpg', 'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529219893624&di=8d9e418df27e1fdb6afb1d993801a980&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fimgad%2Fpic%2Fitem%2F3801213fb80e7beca9004ec5252eb9389b506b38.jpg' ] }, comments: [ { user: { id: 233122, name: '亞索' }, reply: '面對疾風吧' } ] } ] const typeDefs = ` type Query { moments: [Moment] } type Mutation { addComment( entity: Add_Comment ) : Comment } type Moment { user: User main: Main comments: [Comment] } type User { id: Int name: String avatar: String } type Comment { user: User reply: String } type Main { content: String pics: [String] } input Add_User { id: Int name: String } input Add_Comment { user: Add_User reply: String } # 定義graphqlf服務哪一個是RootQuery以及RootMutation schema { query: Query mutation: Mutation } ` const resolvers = { Query: { moments () { return moments } }, Mutation: { addComment (_, { entity }, unknown, context) { console.log(entity) moments[0].comments.push(entity) return entity } } } const schema = makeExecutableSchema({ typeDefs, resolvers }) // koaBody is needed just for POST. router.post('/graphql', koaBody(), graphqlKoa({ schema: schema })) // router.get('/graphql', graphqlKoa({ schema: schema })) router.get('/graphiql', graphiqlKoa({ endpointURL: '/graphql' })) async function responseMiddleware(ctx, next) { ctx.set('Access-Control-Allow-Origin', 'http://localhost:8080') ctx.set('Access-Control-Allow-Methods', 'POST,OPTIONS') ctx.set('Access-Control-Allow-Headers', 'authorization,content-type') // ctx.set('Access-Control-Allow-Credentials', 'true') await next() } app.use(responseMiddleware) app.use(router.routes()) app.use(router.allowedMethods()) app.ws.use(responseMiddleware) app.ws.use(router.routes()) app.ws.use(router.allowedMethods()) app.listen(PORT) 複製代碼

GraphQL概述

GraphQL基本語法特性

包括有fields,alias,arguments,fragments,variables,directives,inline fragmentsweb

  • field

GraphQL類型系統

主要由RootQuery + RootMutation兩種入口類型(操做)加上RootValue(resolvers)構成GraphQL Schema。(此處用graphql-tools是爲了將全部的類型定義在一個字符串中,後續會移到一個.graphql文件中,而後用graphql-import導入)vue-cli

GraphQL類型系統內置基礎類型

  • 標量類型(Scalar Types)shell

    • Int: 有符號的32位整數
    • Float: 有符號雙精度浮點值
    • String: UTF-8字符序列
    • Boolean: true or false
    • ID:ID 標量類型表示一個惟一標識符(相似一種UUID),一般用以從新獲取對象或者做爲緩存中的鍵。ID 類型使用和 String 同樣的方式序列化。
  • 枚舉類型(Enumeration Types)npm

是一種特殊的標量類型json

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}
複製代碼
  • 數組類型(Array Types)

用方括號[]標記列表數組

  • 接口類型(Interface Types)

是一種抽象類型,與java的interface機制相似。緩存

  • 聯合類型(Union Types)
{
  search(text: "an") {
    ... on Human {
      name
      height
    }
    ... on Droid {
      name
      primaryFunction
    }
    ... on Starship {
      name
      length
    }
  }
}
複製代碼
  • 輸入類型(Input Types)

與以前提到的全部Types對立,這是一種也是惟一一種輸入類型,其主要用於mutations時傳遞整個對象的case,它沒有參數。babel

內置修飾符

  • !: 表示非空。以下
query DroidById($id: ID!) {
  droid(id: $id) {
    name
  }
}
複製代碼

GraphQL工做原理

GraphQL中每一個查詢字段是返回子類型的父類型函數。每一個類型的字段對應由一個resolver函數支持,當字段被執行時,響應的resolver被調用並return結果。

若是字段產生結果爲標量類型值,好比字符串或數字,則執行完成。不然遞歸執行對應解析器直至結果爲標量類型值。

GraphQL基本數據流

每一個GraphQL服務端應用的頂層一定會有一個入口點,一般爲Root或者Query類型,接着執行該字段預設的解析器(同步或異步),而每一個字段被解析的結果被放置在鍵值映射中,字段名(或別名)做爲鍵,解析器的值做爲值,這個過程從查詢字段的底部葉子節點開始返回,直到Query類型的起始節點,最後生成鏡像查詢結果返回給客戶端

Vue工程接入GraphQL

安裝vue-cli3.x

npm i -g @vue/cli
複製代碼

初始化工程

vue create [project-name]
複製代碼

引入apollo插件

cd [project-name]
vue add apollo
複製代碼

FriendCircle.vue

<template>
  <div>
    <div v-for="(item, index) in moments" :key="index">
      {{item}}
    </div>
    <input type="text" v-model="comment.reply" placeholder="請輸入要回復的內容">
    <button @click="addComment">回覆</button>
  </div>
</template>

<script>
import gql from 'graphql-tag'

const QUERY_LIST = gql`
  query {
    moments {
      user {
        id
        name
        avatar
      }
      main {
        content
        pics
      }
      comments {
        user {
          id
          name
        }
        reply
      }
    }
  }
`

export default {
  data () {
    return {
      moments: [],
      comment: {
        user: {
          id: (Math.random() * 10000).toFixed(0),
          name: '費德提克'
        },
        reply: ''
      }
    }
  },
  apollo: {
    moments: {
      query: QUERY_LIST
    }
  },
  methods: {
    addComment () {
      this.$apollo.mutate({
        mutation: gql`
          mutation addComment($comment: Add_Comment) {
            addComment(entity: $comment) {
              user {
                id
                name
              }
              reply
            }
          }
        `,
        variables: {
          comment: this.comment
        },
        update: (store, { data: { addComment } }) => {
          // Read the data from our cache for this query.
          const data = store.readQuery({ query: QUERY_LIST })
          // set first moment's comment
          data.moments[0].comments.push(addComment)
          // Write our data back to the cache.
          store.writeQuery({ query: QUERY_LIST, data })
        }
      })
    }
  }
}
</script>
複製代碼

涉及的知識點有Root_Query,Root_Mutation,variables以及store cache

cache

其核心機制包括如下兩點

  1. 對全部(包括嵌套的)非標量類型遞歸進行緩存,每每經過類型id或_id以及__typename惟一組合標識,而後在一個扁平的數據結構中存儲
  2. 能夠設置不一樣緩存策略:cache-and-network,no-cache,network-only

update回調

this.$apollo.mutate(options) options中有一個update回調,在成功響應數據後觸發,而且能夠直接讀取並操做由apollo-cache-inmemory生成的store。上述例子中使用此回調同步更新緩存以及UI

注:全部綁定的變量均不可直接修改,內部使用Object.freeze將對象凍結,沒法直接增刪。

做者:清風0o0 連接:https://juejin.im/post/5b2640bee51d45588d4d68d2 來源:掘金 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索