GraphQL 入門詳解

簡介

定義

一種用於API調用的數據查詢語言css

核心思想

傳統的api調用通常獲取到的是後端組裝好的一個完整對象,而前端可能只須要用其中的某些字段,大部分數據的查詢和傳輸工做都浪費了。graphQL提供一種全新數據查詢方式,能夠只獲取須要的數據,使api調用更靈活、高效和低成本。html

特色

  1. 須要什麼就獲取什麼數據
  2. 支持關係數據的查詢
  3. API無需定義各類路由,徹底數據驅動
  4. 無需管理API版本,一個版本持續演進
  5. 支持大部分主流開發語言和平臺
  6. 強大的配套開發工具

使用方法

下面咱們經過搭建一個SpaceX的新聞網站來直觀學習graphQL的基本使用方法,全部數據由 官方API 得到。前端

服務端

服務端採用node + express。新建一個node項目,安裝以下依賴:node

$ npm i graphql express-graphql express axios

建立入口文件 server.js,裏面建立express服務。使用graphQL咱們只須要設置一個路由,全部的請求都由這個graphQL的request handler處理:react

const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./schema');

const app = express();

app.use('/graphql', graphqlHTTP({
  schema,
  graphiql: true
}));

const PORT = process.env.PORT || 5000;

app.listen(PORT,()=>console.log(`Server started on port ${PORT}`));

graphqlHTTP是grapql的http服務,用於處理graphql的查詢請求,它接收一個options參數,其中schema是一個 GraphQLSchema實例,咱們接下來定義,graphiql設置爲true能夠在瀏覽器中直接對graphQL進行調試。更多express-graphql的用法請參考 Github express-graphqlios

schema

接下來咱們定義schema,schema意爲‘模式’,其中定義了數據模型的結構、字段的類型、模型間的關係,是graphQL的核心。git

新建schema.js文件,首先定義兩個數據模型:LaunchType(發射)和 RocketType(火箭)。注意字段的數據類型須要使用GraphQL定義的,不能使用js中的基本數據類型。github

const { GraphQLObjectType, GraphQLInt, GraphQLString, GraphQLBoolean, GraphQLList, GraphQLSchema } = require('graphql');

const LaunchType = new GraphQLObjectType({
  name: 'Launch',
  fields: () => ({
    flight_number: { type: GraphQLInt },
    mission_name: { type: GraphQLString },
    launch_date_local: { type: GraphQLString },
    launch_success: { type: GraphQLBoolean },
    rocket: { type: RocketType },
  })
});

const RocketType = new GraphQLObjectType({
  name: 'Rocket',
  fields: () => ({
    rocket_id: { type: GraphQLString },
    rocket_name: { type: GraphQLString },
    rocket_type: { type: GraphQLString }
  })
});

有了數據模型以後,咱們須要從數據庫或者第三方API獲取數據,在此咱們從spacex的官方API獲取。咱們須要定義一個root query,root query作爲全部查詢的入口,處理並返回數據,更多請參考 GraphQL Root fields & resolvers數據庫

schema.js中增長代碼:express

const axios = require('axios');

...

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    launches: {
      type: new GraphQLList(LaunchType),
      resolve(parent, args) {
        return axios.get('https://api.spacexdata.com/v3/launches').then(res => res.data);
      }
    }
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery
});

查詢列表

完成這一步,服務端api基本搭建完成!咱們看一下效果,在瀏覽器中輸入 http://localhost:5000/graphql 將打開 Graphiql(生產環境建議禁用):

image

咱們能夠只查詢全部的 flight_number

image

或者更多的屬性:

image

是否是很簡單很神奇!

單個查詢

咱們也能夠經過傳入參數查詢單條信息:

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    ...
    
    launch: {
      type: LaunchType,
      args: {
        flight_number: { type: GraphQLInt }
      },
      resolve(parent, args) {
        return axios.get(`https://api.spacexdata.com/v3/launches/${args.flight_number}`)
        .then(res => res.data);
      }
    }
  }
});

結果:

image

前端

剛剛咱們都是用GraphiQL在瀏覽器調用接口,接下來咱們看一下在前端頁面中怎麼調用graphql服務。前端咱們使用react。

在項目根目錄初始化react項目:

$ npx create-react-app client

爲了便於調試,在package.json中增長scripts:

"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"dev":"concurrently \"npm run server\" \"npm run client\" "

樣式咱們使用bootswatch中的一款主題:

image

GraphQL的客戶端有多種實現,本次項目使用 Apollo,最流行的GraphQL Client。更多client請參考 GraphQL Clients

安裝依賴

安裝以下依賴:

$ cd client
$ npm i apollo-boost react-apollo graphql

其中 apollo-boost 是apollo client自己,react-apollo 是react視圖層的集成,graphql 用於解析graphql的查詢語句。

設置client

修改App.js內容以下:

import React, { Component } from 'react';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import './theme.css';
import './App.css';
import logo from './spacex-logo-light.png'

const client = new ApolloClient({
  uri: 'http://localhost:5000/graphql'
});

class App extends Component {
  render() {
    return (
      <ApolloProvider client={client}>
        <div className="container">
          <img src={logo} id="logo" />
        </div>
      </ApolloProvider>
    );
  }
}

export default App;

和redux使用<Provider>傳遞store相似,react-apollo 經過 <ApolloProvider>將apollo client向下傳遞。

實現query

接着咱們來實現顯示launches的component,新增文件 components/Launches.js

import React, { Component, Fragment } from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';
import LaunchItem from './LaunchItem';

const LAUNCHES_QUERY = gql`
  query LaunchesQuery {
    launches {
      flight_number,
      mission_name,
      launch_date_local,,
      launch_success,
    }
  }
`;

export class Launches extends Component {
  render() {
    return (
      <Fragment>
        <h1 className="display-4 my-3">Launches</h1>
        <Query query={LAUNCHES_QUERY}>
          {
            ({ loading, error, data }) => {
              if (loading) return <h4>Loading...</h4>
              if (error) console.log(error);
              return (
                <Fragment>
                  {
                    data.launches.map(launch => <LaunchItem key={launch.flight_number} launch={launch}/>)
                  }
                </Fragment>
              )
            }
          }
        </Query>
      </Fragment>
    )
  }
}

export default Launches

query語句經過 graphql-tag 定義,傳入 <Query> 執行獲取數據並傳入 LaunchItem 顯示。

components/LaunchItem.js:

import React from 'react'

export default function LaunchItem({ launch: { flight_number, mission_name, launch_date_local, launch_success } }) {
  return (
    <div className="card card-body mb-3">
      <div className="col-md-9">
        <h4>Mission: {mission_name}</h4>
        <p>Date: {launch_date_local,}</p>
      </div>
      <div className="col-md-3">
        <button className="btn btn-secondary">Launch Details</button>
      </div>
    </div>
  )
}

查詢語句經過graphql-tag定義,而後傳入<Query>執行。

運行

因爲本地調試,client和server分別運行在不一樣的端口,因此須要先進行跨域處理,使用 cors

server.js

const cors = require('cors');

...

app.use(cors());

效果

好了,大功告成,咱們來看一下效果:

image

結語

今天就主要介紹GraphQL工程的搭建和GraphQL Query的使用,更多關於GraphQL的內容好比 Mutation下次有空會跟你們逐步講解。

本文靈感來源:Youtube@Traversy Media,感謝

本文Demo Github地址:Github@MudOnTire

本文Demo線上展現:Heroku@graphql-spacex-launches

最後,推薦你們使用 Fundebug,一款很好用的BUG監控工具~
相關文章
相關標籤/搜索