最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 详解企业级使用Graphql开发项目

    正文概述 掘金(水痕001)   2021-06-26   511

    一、基本环境搭建

    • 1、创建一个react项目

      npx create-react-app react-graphql --template typescript
      
    • 2、根据文档在react中配置Graphql的环境,链接地址

      • 安装依赖包

        npm install @apollo/client graphql
        
      • index.ts中配置连接graphql的后端地址

        import { ApolloClient, InMemoryCache } from '@apollo/client';
        
        const client = new ApolloClient({
          uri: 'http://localhost:7001/graphql',
          cache: new InMemoryCache()
        });
        
      • index.ts文件中将apolloreact相连接起来

        import { ApolloProvider } from '@apollo/client/react';
        
        import React from 'react';
        import ReactDOM from 'react-dom';
        import App from './App';
        import { ApolloClient, InMemoryCache } from '@apollo/client';
        import { ApolloProvider } from '@apollo/client/react';
        
        const client = new ApolloClient({
          uri: 'http://localhost:7001/graphql',
          // 在这里配置请求头了
          headers: {
            token: storage.getItem(authToken),
          },
          cache: new InMemoryCache()
        });
        
        ReactDOM.render(
          <React.StrictMode>
            <ApolloProvider client={client}>
              <App />
            </ApolloProvider>
          </React.StrictMode>,
          document.getElementById('root')
        );
        
      • 运行项目看是否正常

    • 3、测试是否可以查询数据出来

      import React from 'react';
      import { useQuery, gql } from '@apollo/client';
      
      const AccountListGql = gql`
        query AccountList { # 定义查询方法(浏览器上显示的)
          accountList { # 定义与后端对接的方法名
            id
            username
            password
          }
        }
      `;
      
      export const Page1: React.FC = () => {
        const { loading, error, data } = useQuery(AccountListGql);
        console.log(loading);
        console.log(error);
        console.log(data);
        return <div>测试查询数据</div>
      }
      

    二、查询数据

    • 1、简单的查询,上面使用useQuery就可以实现

    • 2、需要传递参数的查询

      import React from 'react';
      import { gql, useQuery } from '@apollo/client';
      
      const AccountGql = gql`
        query Account($id: ID!) {
          account(id: $id) {
            id
            username
            password
          }
        }
      `;
      export const Page2: React.FC = () => {
        const {  data } = useQuery(AccountGql, {
          variables: {
            id: 1
          }
        });
        console.log(data, '查询结果');
        return <div>根据条件来查询</div>
      }
      
    • 3、点击按钮才触发请求

      import React from 'react'
      import { gql, useLazyQuery } from '@apollo/client';
      
      const AccountListGql = gql`
        query AccountList { # 定义查询方法(浏览器上显示的)
          accountList { # 定义与后端对接的方法名
            id
            username
            password
          }
        }
      `;
      
      export const Page3: React.FC = () => {
        const [getAccount, { loading, data }] = useLazyQuery(AccountListGql);
        if (loading) return null;
        console.log(data, '请求回来的数据');
        return (
          <div>
            点击按钮请求数据
            <button onClick={() => getAccount()}>点击按钮</button>
          </div>
        )
      }
      
    • 4、点击按钮触发,需要传递参数进去

      const AccountGql = gql`
        query Account($id: ID!) {
          account(id: $id) {
            id
            username
            password
          }
        }
      `;
      
      export const Page3: React.FC = () => {
        const [getAccount, { loading: loading2, data: account }] = useLazyQuery(AccountGql);
        console.log(account, '根据条件返回的数据');
        return (
          <div>
            点击按钮请求数据
            <button onClick={() => getAccount({variables: {id:2}})}>传递参数按钮</button>
          </div>
        )
      }
      
    • 5、关于更多的使用请参考文档文档地址

    三、对数据的增删改操作

    • 1、文档地址

    • 2、添加数据的操作

      import React from 'react';
      import {gql, useMutation} from '@apollo/client';
      
      const AddAccountGql = gql`
        mutation AddAccount($username: String!, $password: String!) {
          createAccount(username: $username, password: $password) {
            code
            message
          }
        }
      `;
      
      export const Page4: React.FC = () => {
        const [addTodo, { data }] = useMutation(AddAccountGql);
        console.log(data, '创建结果');
        const addAccountHandle = () => {
          addTodo({
            variables: {
              username: '王五',
              password: '123456',
            }
          })
        };
        return (
          <div>
            <h3>添加数据</h3>
            <button onClick={addAccountHandle}>添加数据</button>
          </div>
        )
      }
      

    四、文件上传

    上面的配置仅仅的对于简单的业务可以满足,如果你要对文件的上传操作上面的配置是不行的,下面介绍在graphql中上传文件的方式

    • 1、安装依赖包

      npm install apollo-upload-client@14.1
      npm install @types/apollo-upload-client -D
      
    • 2、修改graphql的配置项,必须要这样配置

      import { createUploadLink } from 'apollo-upload-client';
      ...
      const client = new ApolloClient({
        // uri: 'http://localhost:7001/graphql',
        link: {
          uri: 'http://localhost:7000/graphql',
          // 在这里配置请求头了
          headers: {
            token: storage.getItem(authToken),
          },
        },
        cache: new InMemoryCache()
      });
      
    • 3、在react中使用文件上传,这里使用自定义按钮来上传,因为html中自带的上传文件样式太丑了

      import { useMutation, gql, useQuery } from '@apollo/client';
      
      // 上传文件的gql
      const fileUploadGql = gql`
        mutation FileUpload($file: Upload!) {
          fileUpload(file: $file)
        }
      `;
      // 省去100行代码
      ...
      const [uploadFileApi, { data: uploadResult, error: uploadError }] = useMutation(fileUploadGql);
      ...
      // 省去100行代码
      
      const uploadHandler = () => {
        const fileNode: HTMLElement = document.getElementById('file') as HTMLElement;
        fileNode.click();
        fileNode.addEventListener<'change'>(
          'change',
          function ({
            target: {
              validity,
              files: [file],
            },
          }: // eslint-disable-next-line
                     any) {
            setIsShowFile(false);
            validity.valid && uploadFileApi({ variables: { file } });
            setTimeout(() => {
              setIsShowFile(true);
            });
          }
        );
      };
      
      // 省去100行代码
      {isShowFile && <input type="file" id="file" style={{ display: 'none' }} />}
      {imgUrl && (
        <img src={imgUrl}  style={{ width: 100, height: 100, marginBottom: 10 }} />
      )}
      <div>
        <Button type="primary" onClick={uploadHandler}>上传封面图</Button>
      </div>
      

    五、关于apollo错误处理

    一般我们使用restfull api的时候会对axios二次封装,在里面统一处理错误,比如token失效的时候你要重定向到登录页面,上面介绍的方法中我们仅仅是使用apollo打通了前后接口,数据能增删改查,也能上传文件了,如果你的业务中没有登录的限制这里也可以不用关心了。但是作为有追求的码农,总要彻底的掌握一门技术,下面介绍如何对apollo二次简单封装,来处理错误

    • 1、在utils/initApollo.ts中对apollo简单的封装

      import {
        ApolloClient,
        ApolloLink,
        from as fromLinks,
        InMemoryCache,
        NormalizedCacheObject,
        QueryOptions,
        WatchQueryOptions,
      } from '@apollo/client';
      import { onError } from '@apollo/client/link/error';
      import { createUploadLink } from 'apollo-upload-client';
      import { authToken } from 'src/config';
      import { storage } from './storage';
      
      let apolloClient: ApolloClient<NormalizedCacheObject> | null = null;
      
      const defaultOptions = {
        watchQuery: {
          fetchPolicy: 'no-cache',
          errorPolicy: 'ignore',
        } as WatchQueryOptions,
        query: {
          fetchPolicy: 'no-cache',
          errorPolicy: 'all',
        } as QueryOptions,
      };
      
      function create(): ApolloClient<NormalizedCacheObject> {
        const httpLink = createUploadLink({
          uri: 'http://localhost:7000/graphql',
          headers: {
            token: storage.getItem(authToken),
          },
        });
        const authMiddleware = new ApolloLink((operation, forward) => {
          const token = storage.getItem(authToken);
          if (token) {
            operation.setContext({
              headers: {
                token,
              },
            });
          }
          return forward(operation);
        });
        // 处理错误的时候
        const errorLink = onError(({ graphQLErrors, networkError }) => {
          console.log(graphQLErrors, '错误');
          if (graphQLErrors) {
            graphQLErrors.map(({ message, locations, path }) => {
              // 根据错误处理业务,省去100行代码
              console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`);
              return false;
            });
          }
          if (networkError) {
            console.log(`[Network error]: ${networkError}`);
          }
        });
        return new ApolloClient({
          // errorLink 应在 httpLink 前
          link: fromLinks([errorLink, authMiddleware, httpLink]),
          cache: new InMemoryCache(),
          defaultOptions,
          connectToDevTools: true,
        });
      }
      
      export const initApollo = (): ApolloClient<NormalizedCacheObject> => {
        if (!apolloClient) {
          apolloClient = create();
        }
        return apolloClient;
      };
      
    • 2、在react的入口文件中使用

      import { initApollo } from './utils';
      
      const client = new ApolloClient(initApollo());
      
      ReactDOM.render(
        <ApolloProvider client={client}>
        	<Router />
        </ApolloProvider>,
        document.getElementById('root')
      );
      

    六、使用后端的schema自动生成hooks

    • 1、参考文档

    • 2、安装依赖包

      npm install --save graphql
      npm install --save-dev @graphql-codegen/cli
      
    • 3、初始化,直接选择默认和Y就可以

      npx graphql-codegen init
      

      详解企业级使用Graphql开发项目

    • 4、默认生成的codegen.yml文件修改如下

      overwrite: true
      schema: "http://localhost:7000/graphql" # 根据自己后端服务器地址来写,
      # schema: "./schema.graphql" # 将后端的schema拷贝到前端项目中
      documents: "src/**/*.graphql" # 表示会去查找graphql结尾的文件
      generates:
        src/generated/graphql.ts:
          plugins:
            - "typescript"
            - "typescript-operations"
            - "typescript-react-apollo"
      
    • 5、我们在src文件夹下创建一个graphql的文件夹,创建两个login.graphqlregister.graphql文件

      # login.graphql文件内容
      query Login($username: String!, $password: String!) {
        # 定义查询方法(浏览器上显示的)
        login(data: { username: $username, password: $password }) {
          id
          username
          token
        }
      }
      
      # register.graphql文件内容
      mutation registerUser($username: String!, $password: String!, $confirmPassword: String!) {
        register(data: { username: $username, password: $password, confirmPassword: $confirmPassword })
      }
      
    • 6、运行安装依赖包

      使用命令npx graphql-codegen init初始化的时候,并不会帮我们安装依赖包的,只是会添加依赖包到package.json

    • 7、运行命令生成对应的hooks,注意这个要看自己根据第三小点生成的命令来运行,或者自己配置的命令

      npm run codegen
      
    • 8、在生成的src/generated/graphql.ts文件中最底部可以查看到生成了登录和注册的hooks,因为我们只写了这两个接口的graphql文件

    • 9、在App.tsx组件中调用

      import React, { useEffect } from 'react';
      import { useLoginLazyQuery, useRegisterUserMutation } from './generated/graphql';
      
      function App(): React.ReactElement {
        const [loginApi, { data: loginResult }] = useLoginLazyQuery();
        const [registerApi] = useRegisterUserMutation();
        const loginHandler = () => {
          loginApi({ variables: { username: 'admin', password: '123456' } });
        };
        const registerHandler = async () => {
          const result = await registerApi({ variables: { username: 'test1', password: '123456', confirmPassword: '123456' } });
          console.log(result, '注册结果');
        };
        useEffect(() => {
          if (loginResult) {
            console.log('登录信息', loginResult);
          }
        }, [loginResult]);
        return (
          <div className='App'>
            <button onClick={loginHandler}>登录</button>
            <button onClick={registerHandler}>注册</button>
          </div>
        );
      }
      
      export default App;
      

    七、如果你想练习graphql,又不会写后端的graphql,可以下载我的项目,项目地址,根据文档简单来配置下,有问题可以加我,我帮你解答。


    起源地下载网 » 详解企业级使用Graphql开发项目

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元