上一篇: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!!!