前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GraphQL 入门详解

GraphQL 入门详解

作者头像
Nealyang
发布2019-09-29 15:43:14
2.1K0
发布2019-09-29 15:43:14
举报

作者:MudOnTire github 地址:https://github.com/MudOnTire

简介

定义

一种用于API调用的数据查询语言

核心思想

传统的api调用一般获取到的是后端组装好的一个完整对象,而前端可能只需要用其中的某些字段,大部分数据的查询和传输工作都浪费了。graphQL提供一种全新数据查询方式,可以只获取需要的数据,使api调用更灵活、高效和低成本。

特点

  1. 需要什么就获取什么数据
  2. 支持关系数据的查询
  3. API无需定义各种路由,完全数据驱动
  4. 无需管理API版本,一个版本持续演进
  5. 支持大部分主流开发语言和平台
  6. 强大的配套开发工具

使用方法

下面我们通过搭建一个SpaceX的新闻网站来直观学习graphQL的基本使用方法,所有数据由 官方API 获得。

服务端

服务端采用node + express。新建一个node项目,安装如下依赖:

$ npm i graphql express-graphql express axios

创建入口文件 server.js,里面创建express服务。使用graphQL我们只需要设置一个路由,所有的请求都由这个graphQL的request handler处理:

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-graphql。

schema

接下来我们定义schema,schema意为‘模式’,其中定义了数据模型的结构、字段的类型、模型间的关系,是graphQL的核心。

新建schema.js文件,首先定义两个数据模型:LaunchType(发射)和 RocketType(火箭)。注意字段的数据类型需要使用GraphQL定义的,不能使用js中的基本数据类型。

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 LaunchType = 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中增加代码:

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(生产环境建议禁用):

我们可以只查询所有的 flight_number

或者更多的属性:

是不是很简单很神奇!

单个查询

我们也可以通过传入参数查询单条信息:

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);
      }
    }
  }
});

结果:

前端

刚刚我们都是用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中的一款主题:

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());

效果

好了,大功告成,我们来看一下效果:

结语

今天就主要介绍GraphQL工程的搭建和GraphQL Query的使用,更多关于GraphQL的内容比如 Mutation下次有空会跟大家逐步讲解。

本文灵感来源:Youtube@Traversy Media,感谢

本文Demo Github地址:Github@MudOnTire

本文Demo线上展示:Heroku@graphql-spacex-launches

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈前端精选 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
    • 定义
      • 核心思想
        • 特点
        • 使用方法
          • 服务端
            • schema
            • 查询列表
            • 单个查询
          • 前端
            • 安装依赖
            • 设置client
            • 实现query
            • 运行
            • 效果
        • 结语
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档