首页IT科技grapeseed葡萄籽胶囊功效(GraphQL在react中的应用示例详解)

grapeseed葡萄籽胶囊功效(GraphQL在react中的应用示例详解)

时间2025-07-31 01:18:06分类IT科技浏览7497
导读:什么是 GraphQL GraphQL由Facebook发起,其手机客户端自2012年起,就全面采用了GraphQL查询语言, 2015年, Facebook全面开源了第一份GraphQL规范。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,是一种规范,使得客户端能够准确地获得它需要的数据...

什么是 GraphQL

GraphQL由Facebook发起                ,其手机客户端自2012年起                        ,就全面采用了GraphQL查询语言         , 2015年        , Facebook全面开源了第一份GraphQL规范                。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述                        ,是一种规范                 ,使得客户端能够准确地获得它需要的数据        ,而且没有任何冗余.

GraphQL出现的意义

传统API存在的主要问题: 接口数量众多维护成本高:接口的数量通常由业务场景的数量决定                        ,为了尽量减少接口数量                 ,服务端工程师通常会对业务做抽象,首先构建粒度较小的数据接口                        ,再根据业务场景对数据接口进行组合                         ,对外暴露业务接口,即便这样                ,服务端对前端暴露的接口数量还是非常多                         ,因为业务总是多变的                         。 接口扩展成本高:出于带宽的考虑移动端我们要求接口返回尽量少的字段         ,PC 端通常要展现更多字段;考虑首屏性能                ,我们又要求对接口做合并;传统 API 应对这些需求                        ,前后端都面临改造         ,成本较高        。 接口响应的数据格式无法预知:由于接口文档几乎总是不能及时更新        ,前端工程师无法预知接口响应的数据格式                        ,影响前端开发进度                。 GraphQL 如何解决问题

请求参数在发送到服务端之前会先经过 GraphQL Client 转换成客户端 Schema                 ,这段 Schema 其实是一段 query 开头的字符串        ,描述了客户端的对数据的述求:调用哪个方法                        ,传递什么样的参数                 ,返回哪些字段                         。服务端拿到这段 Schema 之后,通过事先定义好的服务端 Schema 接收请求参数并执行对应的 resolve 函数提供数据服务        。

GraphQL基本语法

参考 [GraphQL][1] 官网文档

标量类型

GraphQL 自带一组默认标量类型: Int:有符号 32 位整数        。 Float:有符号双精度浮点值                         。 String:UTF‐8 字符序列                。 Boolean:true 或者 false        。 ID:ID 标量类型表示一个唯一标识符                        ,通常用以重新获取对象或者作为缓存中的键                         。ID 类型使用和 String 一样的方式序列化                。

对象类型

一个 GraphQL schema 中的最基本的组件是对象类型                         ,它就表示你可以从服务上获取到什么类型的对象,以及这个对象有什么字段

type Character { name: String! list: [Episode!]! }
myField: [String!] myField: null myField: [] myField: [a, b] myField: [a, null, b] myField: [String]! myField: null myField: [] myField: [a, b] myField: [a, null, b]

GraphQL 对象类型上的每一个字段都可能有零个或者多个参数                ,

type Starship { id: ID! name: String! length(unit: LengthUnit = METER): Float }
枚举类型
enum Episode { NEWHOPE EMPIRE JEDI }

这表示无论我们在 schema 的哪处使用了 Episode                         ,都可以肯定它返回的是 NEWHOPE                、EMPIRE 和 JEDI 之一。

对象类型                         、标量以及枚举是 GraphQL 中你唯一可以定义的类型种类                         。但是当你在 schema 的其他部分使用这些类型时         ,或者在你的查询变量声明处使用时                ,你可以给它们应用额外的类型修饰符来影响这些值的验证                         。

type Character { name: String! list: [Episode]! }
GraphQL 内置指令

GraphQL 中内置了两款逻辑指令                        ,指令跟在字段名后使用。

@include 当条件成立时         ,查询此字段

query { search { actors @include(if: $queryActor) { name } } }

@skip 当条件成立时        ,不查询此字段

query { search { comments @skip(if: $noComments) { from } } }
操作类型:指定本请求体要对数据做什么操作                        ,类似与 REST 中的 GET POST                。GraphQL 中基本操作类型有 query 表示查询                 ,mutation 表示对数据进行操作        ,例如增删改操作                        ,subscription 订阅操作                         。 操作名称:操作名称是个可选的参数                 ,操作名称对整个请求并不产生影响,只是赋予请求体一个名字                        ,可以作为调试的依据        。 变量定义:在 GraphQL 中                         ,声明一个变量使用符号开头,冒号后面紧跟着变量的传入类型                。如果要使用变量                ,直接引用即可                         ,例如上面的movie就可以改写成movie(name:符号开头         ,冒号后面紧跟着变量的传入类型                         。如果要使用变量                ,直接引用即可                        ,例如上面的 movie 就可以改写成 movie(name: 符号开头         ,冒号后面紧跟着变量的传入类型        。如果要使用变量        ,直接引用即可                        ,例如上面的movie就可以改写成movie(name:name)        。
query Hero($episode: Int!, $withFriends: Boolean!) { hero(episode: $episode) { name friends @include(if: $withFriends) { name } } }

什么是 Apollo

Meteor 团队有着很丰富的数据流控制经验                 ,他们发现了 Relay 的不便之处        ,引领业界通过使用他们开发的 Apollo 享受到更简洁的接口                        ,Apollo 是基于GraphQL的全栈解决方案集合                         。包括了 apollo-client 和 apollo-server ;从后端到前端提供了对应的 lib                  ,使开发使用 GraphQL 更加的方便                。

apollo-server

apollo-server是一个在nodejs上构建grqphql服务端的web中间件        。支持express,koa 等框架                         。 参考 [apollo-server][2] 官网文档

处理流程

主要是通过官方graphql-js库进行处理

1.解析阶段

为了识别客户端 Schema                        , graphql-js 定义了一系列的特征标识符:

export const TokenKind = Object.freeze({ BANG: !, DOLLAR: $, PAREN_L: (, PAREN_R: ), SPREAD: ..., COLON: :, EQUALS: =, BRACKET_L: [, BRACKET_R: ], ... });

并定义了 AST 语法树规范                         ,规定语法树支持以下节点:

export const Kind = Object.freeze({ // Name NAME: Name, // Document DOCUMENT: Document, OPERATION_DEFINITION: OperationDefinition, VARIABLE_DEFINITION: VariableDefinition, VARIABLE: Variable, // Values INT: IntValue, FLOAT: FloatValue, STRING: StringValue, BOOLEAN: BooleanValue, ... });

有了特征字符串与 AST 语法树规范,GraphQL Server 对客户端 Schema 进行逐字符扫描,如果客户端 Schema 不符合服务端定义的 AST 规范                ,解析过程会直接抛出语法异常                。

2.校验阶段

校验阶段用于验证客户端 Schema 是否按照服务端 Schema 定义好的方式获取数据                         ,比如:获取数据的方法名是否有误         ,必填项是否有值等等                ,校验范围一共有几十种                        ,不一一举例。

{ "errors":[ { "message":"Cannot query field "getU" on type "Query". Did you mean "getUser"?", "locations":[ { "line":3, "column":9 } ] } ] }

不仅返回结构化的报错信息         ,还非常人性化的告诉你正确的调用方式是什么                         。校验阶段通过之后会进入执行阶段.

3.执行阶段

执行阶段依赖的输入为:解析阶段的产出物 document         ,服务端 Schema;其中 document 准确描述了客户端对数据的述求:请求哪个方法                        ,参数是什么                 ,需要哪些字段;服务端 Schema 描述了提供数据的方式                         。执行服务端 Schema 中的 resolve 函数        ,得到执行阶段的输出。每个类型的每个字段都由一个 resolver 函数支持                        ,该函数由 GraphQL 服务器开发人员提供                。

Schema

Schema可以说是GraphQL最具核心的部分                 ,其描述了整个接口向外暴露的形式;像Restful API,我们会定义一个查询所有人的接口url定义为:/api/v1/user/getUsers                        ,而查询人具体信息的接口url为:/api/v1/user/getUserById,前端人员调用起来很直观                         。但是graphql是完全不一样的使用方式                         ,其向前端暴露的url就一个像/api/graphql之类的,那这么多接口怎么区分呢?

一个graphql接口都有一个Schema定义                ,其定义三种操作方式:query(查询),mutation(变更)和subscription(监听)        。再往下延伸                         ,一个查询中包含多个field         ,也就是多种不同的查询                ,比如query user查询人                        ,query message查询消息         ,query weather查询天气        ,通过这些就实现了Restful API使用多个url来达到不同操作的效果                。

给server端带来的便利性

由于 GraphQL 通过客户端 Schema 而不是通过 URL 描述数据述求                        ,所以理论上服务端只需要对客户端暴露一个地址即可                 , 解决了接口数量众多维护成本高的问题; 同时        ,服务端提供的是全量字段                        ,客户端可按需获取                 ,面对接口扩展的需求,服务端没有开发成本;

import express from express; import { graphiqlExpress, graphqlExpress } from apollo-server-express; const app = express(); app.use(/graphql, graphqlExpress({ schema, })); app.use(/graphiql, graphiqlExpress({ endpointURL: /graphql }));

apollo-client

参考 [apollo-client][3] 官网文档

创建client
import ApolloClient from "apollo-boost"; const client = new ApolloClient({ uri: "https://48p1r2roz4.sse.codesandbox.io" });

在我们将Apollo Client连接到React之前                        ,让我们先尝试发送查询                         。记住首先导入gql用于将查询字符串解析为查询文档        。

import gql from "graphql-tag"; ... client.query({ query: gql` { rates(currency: "USD") { currency } } ` }) .then(result => console.log(result));
将client注入到react

react-apollo提供ApolloProvider组件                         ,ApolloProvider类似于redux的provider        。它会把apollo客户端放入到React app的上下文里,以便在组件树的任何地方都是可以获取到apollo客户端                         。

import React from "react"; import { render } from "react-dom"; import { ApolloProvider } from "react-apollo"; const App = () => ( <ApolloProvider client={client}> <div> <h3>My first Apollo app ?</h3> </div> </ApolloProvider> ); render(<App />, document.getElementById("root"));
数据请求

1.通过react-apollo提供的graphql函数获取数据                ,并connect到组建中                         ,就可以在组件的this.props中看到多了个data对象         ,

import React, { Component } from react; import { graphql } from react-apollo; import gql from graphql-tag; export const USERS_QUERY = gql` query UserQuery($pageNum: Int,$pageSize:Int){ users(pageNum:$pageNum,pageSize:$pageSize ) { pageNum pageSize total data { userName } } } `; const withQuery = graphql(USERS_QUERY, { options: () => ({ variables: { pageNum: 3, pageSize: 8, }, }), }); class List extends Component { constructor(props) { super(props); this.state = {}; } render() { const { data: { loading, error, users } } = this.props; if (loading) { return <div className="loading">Loading...</div>; } if (error) return `Error! ${error.message}`; const { total } = users; }; return ( <div> <p className="total">总共<span>{total}</span></p> </div> ); } } export default withQuery(List);

data中包含loading, error, users等字段

当React安装Query组件时                ,Apollo Client会自动触发查询                。如果想延迟触发查询                        ,直到用户执行操作(例如单击按钮)         ,该怎么办?对于这种情况        ,可以使用ApolloConsumer组件并直接调用client.query()        。

import React, { Component } from react; import { ApolloConsumer } from react-apollo; class DelayedQuery extends Component { state = { dog: null }; onDogFetched = dog => this.setState(() => ({ dog })); render() { return ( <ApolloConsumer> {client => ( <div> {this.state.dog && <img src={this.state.dog.displayImage} />} <button onClick={async () => { const { data } = await client.query({ query: GET_DOG_PHOTO, variables: { breed: "bulldog" } }); this.onDogFetched(data.dog); }} > Click me! </button> </div> )} </ApolloConsumer> ); } }

2.通过apollo提供的组件获取

import gql from "graphql-tag"; import { Query } from "react-apollo"; const GET_DOG_PHOTO = gql` query Dog($breed: String!) { dog(breed: $breed) { id displayImage } } `; const DogPhoto = ({ breed }) => ( <Query query={GET_DOG_PHOTO} variables={{ breed }} pollInterval={500}> {({ loading, error, data, startPolling, stopPolling }) => { if (loading) return null; if (error) return `Error!: ${error}`; return ( <img src={data.dog.displayImage} style={{ height: 100, width: 100 }} /> ); }} </Query> );

通过设置pollInterval为500                        ,每隔0.5秒看到一个新的小狗图像                         。 当我们从Query组件中获取数据时                 ,看看Apollo Client幕后发生的事情                。

1.当Query组件安装时        ,Apollo Client会为我们的查询创建一个observable。我们的组件通过Apollo Client缓存订阅查询结果                         。

2.首先                        ,我们尝试从Apollo缓存加载查询结果                         。如果它不在那里                 ,我们将请求发送到服务器。

3.数据恢复后,我们将其标准化并将其存储在Apollo缓存中                。由于Query组件订阅了结果                        ,因此它会自动更新数据                         。

数据缓存

创建本地缓存

import { ApolloClient } from apollo-client import { withClientState } from apollo-link-state import { HttpLink } from apollo-link-http import { InMemoryCache } from apollo-cache-inmemory import { resolvers, typeDefs, defaults } from ../client/index const cache = new InMemoryCache() const client = new ApolloClient({ cache, // 本地数据存储 link: withClientState({ resolvers, defaults, cache, typeDefs }).concat( new HttpLink({ uri: http://localhost:4001/graphql, opts: { credentials: cross-origin, }, }) ), })

要直接与缓存交互                         ,可以使用Apollo Client方法readQuery,readFragment                ,writeQuery和writeFragment        。

总结

如果使用 GraphQL                         ,那么后端将不再产出 API         ,而是将 Controller 层维护为 Resolver                ,和前端约定一套 Schema                        ,这个 Schema 将用来生成接口文档         ,前端直接通过 Schema 或生成的接口文档来进行自己期望的请求                。

GraphQL 的优缺点

优点

所见即所得:所写请求体即为最终数据结构 减少网络请求:复杂数据的获取也可以一次请求完成 Schema 即文档:定义的 Schema 也规定了请求的规则 类型检查:严格的类型检查能够消除一定的认为失误

缺点

增加了服务端实现的复杂度:一些业务可能无法迁移使用 GraphQL        ,虽然可以使用中间件的方式将原业务的请求进行代理                        ,这无疑也将增加复杂度和资源的消耗

以上就是GraphQL在react中的应用示例详解的详细内容                 ,更多关于GraphQL react应用的资料请关注本站其它相关文章!

声明:本站所有文章        ,如无特殊说明或标注                        ,均为本站原创发布                         。任何个人或组织                 ,在未征得本站同意时,禁止复制        、盗用                、采集                         、发布本站内容到任何网站        、书籍等各类媒体平台        。如若本站内容侵犯了原著者的合法权益                        ,可联系我们进行处理        。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
yolov5讲解(关于YOLOv7的分析) 2020网易游戏赚钱排行榜最新图片(有哪些网游可以赚钱-网易游戏首冲30月赚300,每天混车一小时,白嫖党终于站起来了)