GraphQL概述:使用React前端构建待办事项列表API

该文章由Panayiotis«pvgr»Velisarakos进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!

假设您想按照食谱烤蛋糕。 您将需要一些成分,并且每种成分都需要适当的数量。 如果您可以得到一个装有您配方所需所有成分的盒子,已经过测量和称重以匹配您的配方,该怎么办? 它肯定会使烘焙容易得多。 如果您将前端UI视为蛋糕,这就是GraphQL的目的。

在本教程中,我们将编写一个小型GraphQL服务器来响应来自Todo List应用程序的请求。 您可以在那边的许多应用程序中进行选择,但是由于这些天我正在从事React项目,因此我将选择React作为前端框架。 但是,请随时选择您喜欢的任何其他JavaScript框架。

GraphQL

GraphQL允许我们定义一个查询,该查询提供了客户端和服务器之间的公共接口,用于数据获取和操作。 它处理一种查询语言,该语言允许客户端描述其所需的数据及其形状,该语言旨在通过提供直观而灵活的语法来构建客户端应用程序。

这使得从服务器检索数据对于客户端而言更加有效。 例如,假设客户端仅需要GraphQL实现中titleid ,那么它应该执行以下操作:

query Query {
  todos {
    id,
    title
  }
}

产生结果数据(JSON):

{
  "data": {
    "todos": [
      {
        "id": 1446412739542,
        "title": "Read emails"
      },
      {
        "id": 1446412740883,
        "title": "Buy orange"
      },
      {
        "id": 1446412741215,
        "title": "Fix garbage"
      }
    ]
  }
}

也许在我们的现场演示中尚未保存任何数据。 其背后的原因是,每当我们运行服务器时,存储Todo的内存中的阵列就会变空。 在以下各节中,我们将看到如何在该数组中添加数据。

可以看到,响应格式在查询中描述,由客户端而不是服务器定义。 如标题为“ GraphQL概述– GraphQL和Node.js入门”的文章所述,

GraphQL查询就像没有属性的JSON对象。 重要的是要提一下GraphQL不是特定于语言的 ,它只是客户端和服务器之间的规范。 如果客户端说通用语言,则任何客户端都应该能够与任何服务器进行通信。

GraphQL.js简介

GraphQL.js是GraphQL for JavaScript的参考实现,它提供两个重要功能:

  1. 建立类型架构。
  2. 针对该类型架构的查询。

需要构建一个映射到代码库的GraphQL类型架构。 在下面的代码中,我们定义了一个简单的架构。 它具有一种类型和一个解析为固定值的Todo(s)列表(每个元素具有三个字段)。 另外,还需要针对该类型架构提供查询结果。

var graphql = require ('graphql');

// Here is some dummy data to make this piece of code simpler.
// It will be changeable after introducing mutation.
var TODOs = [
  {
    "id": 1446412739542,
    "title": "Read emails",
    "completed": false
  },
  {
    "id": 1446412740883,
    "title": "Buy orange",
    "completed": true
  }
];

var TodoType = new graphql.GraphQLObjectType({
  name: 'todo',
  fields: function () {
    return {
      id: {
        type: graphql.GraphQLInt
      },
      title: {
        type: graphql.GraphQLString
      },
      completed: {
        type: graphql.GraphQLBoolean
      }
    }
  }
});

var queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: function () {
    return {
      todos: {
        type: new graphql.GraphQLList(TodoType),
        resolve: function () {
          return TODOs;
        }
      }
    }
  }
});

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

现在,让我们看一下JavaScript文件的代码,该代码为我们提供JSON中的结果数据:

var graphql = require ('graphql').graphql
var express = require('express')
var graphQLHTTP = require('express-graphql')
var Schema = require('./schema')
var query = 'query { todos { id, title, completed } }'

graphql(Schema, query).then( function(result) {
  console.log(JSON.stringify(result));
  // Prints
  // {
  //   "data":{
  //     "todos":[
  //       {
  //         "id":1446412739542,
  //         "title":"Read emails",
  //         "completed":false
  //       },
  //       {
  //         "id":1446412740883,
  //         "title":"Buy orange",
  //         "completed":true
  //       }
  //     ]
  //   }
  // }
});

var app = express()
  .use('/', graphQLHTTP({ schema: Schema, pretty: true }))
  .listen(8080, function (err) {
    console.log('GraphQL Server is now running on localhost:8080');
  });

通过运行下面的代码,可以获得上面的代码给出的相同结果。 为了在此示例上获得更多优势, cURL不是必需的。 这是在不点击浏览器示例的情况下检索数据的更简单方法。 请注意,如果您是Window用户,则可以使用Windows命令提示符运行cURL示例 。 此外, 在这里您可以找到一个很好的资源来学习如何在系统上安装cURL

$ curl -XPOST -H "Content-Type:application/graphql"  -d 'query { todos { title } }' http://localhost:8080
{
  "data": {
    "todos": [
      {
        "title": "Read emails"
      },
      {
        "title": "Buy orange"
      }
    ]
  }
}

该模式的重要之处在于,它不假设数据的存储方式,因为它仅描述了API使用者可以使用的内容。 数据的存储和表示方式是实现细节。

反应

React是一个JavaScript库,用于创建由Facebook和Instagram开发的用户界面。 许多人选择将React视为MVC模式中的V。 如官方网站所述

我们构建React来解决一个问题:使用随时间变化的数据构建大型应用程序。 这都是关于构建可重用组件的。 实际上,唯一的事情就是构建组件。

如果需要React指南,可以阅读和观看以下资源:

一个简单的React组件

React组件实现了render()方法,该方法获取输入数据并返回要显示的内容。 本示例使用了一种称为JSX的类似XML的语法 。 JSX是可选的,不需要使用React。 JSX是一个JavaScript语法扩展,看起来类似于XML。 您可以在React中使用简单的JSX语法转换。

可以通过render()render()通过this.props访问传递到组件的输入数据。 下面报告了一个如何创建React组件的简单示例,它也可以作为CodePen获得

var Application = React.createClass({
  render: function() {
    return 
  
  
{ this.props.text } { this.props.id }
; } });

有了前面的代码,这就是JSX编译器生成的原始JavaScript代码。

"use strict";
var Application = React.createClass({
  displayName: "Application",
  render: function render() {
    return React.createElement(
      "div",
      null,
      this.props.text,
      this.props.id
    );
  }
});

一个简单的反应组件

如果您想进一步研究React组件,请花一点时间看一下视频Component State Introduction

示例中的演练

首先,我们需要一台服务器(已启动并正在运行),以从Todo List应用程序接收GraphQL查询。 该服务器已在上面编写。

要运行我们的服务器,请在CLI上执行:

$ git clone https://github.com/sitepoint-editors/todo-graphql-server.git
$ cd todo-graphql-server
$ npm install
$ npm start

在本地运行服务器

您必须具有Node v4.0.0或更高版本,因为服务器代码使用的是旧版本不支持的ES2015功能

现在,将针对我们的GraphQL模式执行对端点/graphql所有POST请求。 要测试一切正常,请键入以下代码:

$ curl -XPOST -H "Content-Type:application/graphql"  -d 'query { todos { title } }' http://localhost:8080
{
  "data": {
    "todos": []
  }
}

尚未保存任何数据。 因此,每次我们运行服务器时,存储todo(s)内存中的阵列都会为空。 当然,我们不希望对空数组进行只读访问。 我们必须添加和更改数据。 这种有副作用的操作在GraphQL中称为突变 。 定义突变与定义查询相同,并且还会返回类型化的值。 这个想法是,如果某些东西发生了突变,那么它将返回任何被突变的东西。

var MutationAdd = {
  type: new GraphQLList(TodoType),
  description: 'Add a Todo',
  args: {
    title: {
      name: 'Todo title',
      type: new GraphQLNonNull(GraphQLString)
    }
  },
  resolve: (root, {title}) => {
    TODOs.push({
      id: (new Date()).getTime(),
      title: title,
      completed: false
    });
    return TODOs;
  }
};

var MutationType = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    add: MutationAdd
  }
});

export var Schema = new GraphQLSchema({
  query: QueryType,
  mutation: MutationType
});

上方的箭头( => )是定义函数新语法 。 ES2015最有趣的新部分之一。

正如Clay Allsopp撰写的标题为“您的第一台GraphQL服务器”的文章中所述,

突变和查询之间的有意义的区别是,突变是按顺序处理的,但是查询没有这样的保证(实际上,GraphQL鼓励服务器利用独立查询的固有并行性)。 GraphQL规范给出了一组突变查询的示例,这些突变查询必须由服务器按顺序处理:

{
  first: changeTheNumber(newNumber: 1) {
    theNumber
  },
  second: changeTheNumber(newNumber: 3) {
    theNumber
  },
  third: changeTheNumber(newNumber: 2) {
    theNumber
  }
}

因此,在请求结束时, theNumber字段的值应为2 。 在快速介绍了变异之后,我们终于可以在服务器中添加一个todo

$ curl -XPOST -H "Content-Type:application/graphql" -d 'mutation { add (title: "Clean garage") { id, title } }' http://localhost:8080
{
  "data": {
    "add": [
      {
        "id": 1446443172937,
        "title": "Clean garage"
      }
    ]
  }
}

玩服务器

很酷,不是吗? 除了这个add突变,我们还有更多的东西: toggletoggleAlldestroyclearCompleted 。 并save 。 要注意的一件事是,我们在所有突变中都传递了参数。 所有字段都可以接受参数。 创建参数非常简单,可以将它们加入函数 resolve

归根结底,我们有两种查询类型:

  • 一种用于从服务器获取( 获取 )数据的程序;
  • 一种用于处理( 创建更新删除 )数据的工具。

在运行服务器的情况下,我们准备使用在React中创建的Todo列表: React TodoMVC Example的一个分支 ,如开始所述。 要下载它,执行:

$ git clone -b react-graphql https://github.com/sitepoint-editors/todomvc.git
$ cd todomvc
$ npm install
$ node server.js

转到http://localhost:3000查看正在运行的应用程序。 与原始代码相比,此代码有两个主要更改。 首先, TodoModel已更改为到达GraphQL服务器。

反应组件模型

其次,服务器中的代理将GraphQL请求重定向到我们创建的服务器。 有关更多详细信息,请参见下面的图像。

服务器代理

此外,您可以在此处此处找到演示。

graphql概述

结论

正如您在本教程中所看到的那样,GraphQL和GraphQL.js是Facebook在2015年作为一组开源项目发布的相当新的技术。核心思想是UI最清楚呈现一组特定组件所需的数据。 。 如果您尝试从MVC Todo List中选择另一个JS框架并且遇到任何问题,请放下一行。 谢谢阅读。

From: https://www.sitepoint.com/graphql-overview/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值