GraphQL快速入门教程
摘要: 体验神奇的graphql!
- 原文:graphql 入门详解
- 作者:mudontire
fundebug经授权转载,版权归原作者所有。
graphql简介
定义
一种用于api调用的数据查询语言
核心思想
传统的api调用一般获取到的是后端组装好的一个完整对象,而前端可能只需要用其中的某些字段,大部分数据的查询和传输工作都浪费了。graphql提供一种全新数据查询方式,可以只获取需要的数据,使api调用更灵活、高效和低成本。
特点
- 需要什么就获取什么数据
- 支持关系数据的查询
- api无需定义各种路由,完全数据驱动
- 无需管理api版本,一个版本持续演进
- 支持大部分主流开发语言和平台
- 强大的配套开发工具
使用方法
下面我们通过搭建一个spacex的新闻网站来直观学习graphql的基本使用方法,所有数据由 官方api 获得。
graphql服务端
服务端采用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); } } } });
结果:
推荐大家使用fundebug,一款很好用的bug监控工具~
graphql前端
刚刚我们都是用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分别运行在不同的端口,所以需要先进行跨域处理,使用 。
// 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
最后,推荐大家使用fundebug,一款很好用的bug监控工具~
关于fundebug
fundebug专注于javascript、微信小程序、微信小游戏、支付宝小程序、react native、node.js和java线上应用实时bug监控。 自从2016年双十一正式上线,fundebug累计处理了10亿+错误事件,付费客户有阳光保险、核桃编程、荔枝fm、掌门1对1、微脉、青团社等众多品牌企业。欢迎大家免费试用!
上一篇: 老外谈户外摄影清爽背包攻略
下一篇: ai怎么画口袋妖怪中的鬼斯?