上一篇:GraphQL了解一下:基础篇
下一篇:GraphQL进阶篇: 挥手Redux不是梦
在基础篇主要讲了GraphQL出现的意义与一些基础语法。若是对GraphQL还不是很了解的同窗能够点击上方连接了解一下,再来跟进这一篇的实践。本篇主要讲述实现一个GraphQL Server与在React应用中引入GraphQL,代码不难,推荐跟着手敲一遍。
下面文章的代码均可以经过github下载:地址传送,里面包含两个文件夹:graphqlServer(服务端)与graphqlApp(客户端)。前端
核心依赖(npm包):
express:Node服务端框架;
apollo-server-express:express graphql中间件,提供graphiqlExpress与graphqlExpress两个方法;
graphql:graphql js实现基础库;
axios:ajax通讯,这里用于和已有的Restful API通讯;
除了安装以上的核心依赖,你还须要安装babel相关的依赖,并配置babel编译文件,具体可查看上面git下来的文件配置。react
怎么引入包这里再也不赘述,咱们先不带入graphql,启动一个express服务:webpack
const PORT = 8080; const app = express(); // 建立一个express服务; app.use('/graphql', (req, res) => { res.send('Hello GraphQL!'); }); app.listen(PORT, () => console.log(`> Listening at port ${PORT}`));
启动这个服务,并在浏览器输入http://localhost:8080/graphql,能够看到Hello GraphQL这段欢迎词,到这里咱们的后端服务已经搭建成功,接着咱们建立咱们的GraphQL服务,删除监听'/graphql'这个路由的代码,添加一下一段代码:ios
import schema from './schema'; const PORT = 8080; const app = express(); // 建立一个express服务; app.use(cors()); //这里添加cors,是由于咱们后面前端会单独跑一个服务,因此涉及到先后端跨域 app.use('/graphql', graphqlExpress({ schema })); app.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })); app.listen(PORT, () => console.log(`> Listening at port ${PORT}`));
至此,咱们就添加了GraphQL服务,graphql是用于接收url请求的,而graphiql会呈现一个graphql查询界面,这个界面能够用于查询体验,查看文档定义,这是graphql官方比较推荐的一个技术,就像下面这样:git
上面咱们略过了schema,其实这个在上一篇就花了必定篇幅来说解,其定义了整个graphql服务所支持的接口定义,照样贴上代码:github
import { GraphQLObjectType, GraphQLSchema, GraphQLInt, GraphQLID, GraphQLString, GraphQLList, GraphQLNonNull, } from 'graphql/type'; import { getUser, getUsers, getUserMixNick } from '../service/index'; // 查询某一个user的详细资料模型 const UserType = new GraphQLObjectType({ name: 'User', fields: { id: { type: GraphQLInt }, userName: { type: GraphQLString }, userMixNick: { type: GraphQLString, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: (root, args, context, info) => { const { id } = root; console.log(info) return getUserMixNick(id); } }, military: { type: GraphQLString }, age: { type: GraphQLInt }, height: { type: GraphQLInt }, education: { type: GraphQLString }, enlistTime: { type: GraphQLString }, enlistYear: { type: GraphQLInt }, } }); // 查询全部的users const PaginationType = new GraphQLObjectType({ name: 'Pagination', fields: { pageSize: { type: GraphQLInt }, pageNum: { type: GraphQLInt }, total: { type: GraphQLInt }, data: { type: new GraphQLList(UserType) } } }); // 定义schema const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: 'militaryQuery', fields: { user: { type: UserType, args: { id: { type: new GraphQLNonNull(GraphQLID) } }, resolve: (root, args, context, info) => { const { id } = args; return getUser(id); } }, users: { type: PaginationType, args: { pageNum: { type: GraphQLInt }, pageSize: { type: GraphQLInt } }, resolve: (root, { filters, pageNum, pageSize }) => { return getUsers(filters, pageNum, pageSize); } } } }) }); export default schema;
这里不想花太大的篇幅去讲解,能够git clone下来本身尝试一下,至此咱们就成功的建立了一个GraphQL服务,能够在graphiql界面查询体会一下。web
核心依赖(npm包):
react相关: 什么react,webpack,react-router-dom这些;
react-apollo与apollo-boost: 用于在app端建立一个GraphQL服务链接实例;
graphql与graphql-tag: 用于在app端发出一个GraphQL请求;ajax
页面大体是这样的一个结构,进入App的主页时,会加载兄弟连中主要的战士列表,点击查看详情,能够看到这名展现的一些详细信息,页面结构代码。express
<ApolloProvider client={client}> <Router> <div> <Route exact path="/" component={List} /> <Switch> <Route exact path="/:id/detail" component={Detail} /> </Switch> </div> </Router> </ApolloProvider>
这里须要强调一下client代码的实现:npm
const client = new ApolloClient({ uri: 'http://localhost:8080/graphql', // 服务端接口 batchInterval: 10, opts: { credentials: 'cross-origin', // App端单独跑了一个服务,因此涉及到跨域; }, });
react-apollo在实现graphql结合react编程的方式上,借鉴了相似react-redux的connect高阶组件的思想,react-apollo提供一个方法graphql用于生成一个容器,这个容器会从远端拉去数据,而后做为props传递给展现组件,直接看代码的实现:
// 建立一个查询 const USERS_QUERY = gql` query UserQuery($pageNum: Int,$pageSize:Int){ users(pageNum:$pageNum,pageSize:$pageSize ) { pageNum pageSize total data { id userName } } } `; // 生成一个graphql容器,会执行USERS_QUERY这个查询; 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, users } } = this.props; if (loading) { return <div className="loading">Loading...</div>; } const { data: lists, total } = users; return ( <div> <p className="total">总共有<span>{total}</span>名军士</p> <ul className="list"> { lists.map(({ userName, id }, key) => <li key={key}> <span>姓名:{userName}</span> <Link to={`/${id}/detail`} >详情</Link> </li> ) } </ul> </div> ); } } // 将数据注入到展现组件中 const Character = withCharacter(List); export default Character;
以上就是对列表展现组件的实现,思想仍是比较简单,和咱们基于react + redux编程比较像。
其实现思路和列表页实际上是同样的,只是涉及到动态传参的问题,上查询那一段代码说一下:
const USER_QUERY = gql` query UserQuery($id: ID!){ user(id:$id) { id, userName, age, military, height, education, enlistTime, enlistYear, } } `; const withQuery = graphql(USER_QUERY, { options: (props) => { const { match: { params } } = props; // 重点就是从props中获取路由传递的参数 return { variables: { id: params.id }, }; }, });
withQuery这个高阶组件一样能够从父组件中获取props,而后经过其option方法动态的生成查询参数,至于详细页展现组件的实现,能够具体参考git上面的代码。
到最后输入url能够看到以下的结果:
从写一个demo的角度来说,在react中嵌入graphql好像比在在react中嵌入redux还简单,但如何在咱们现有的框架中去嵌入graphql呢?好比Dva + graphql,好比react + redux + redux-thunk + graphql,在个人认知范围里,好像还须要时间去评估这一切值不值得,反正技术上确定是能够实现的。引入graphql有多大价值,这也须要结合具体项目,具体业务,具体团队来讲。愿你这两篇文章读完对GraphQL已经有了一个比较完整的认识,happy Ending!!!