小程序开发|小程序制作|小程序开发网

搜索

在小程序框架Taro中使用 vue3+graphql

2022-1-13 18:31| 发布者: xiaoxiao| 查看: 411| 评论: 1

摘要: 前言:在小程序中使用 graphql 相对来讲是一个小众的需求,并且在 Taro 中就更少一些,但对我们来讲却是一个必需要解决的问题。由于今年基础服务端的技术全面升级,已经都切换到基于 graphql api 实现上面,所以新

前言:

在小程序中使用 graphql 相对来讲是一个小众的需求,并且在 Taro 中就更少一些,但对我们来讲却是一个必需要解决的问题。由于今年基础服务端的技术全面升级,已经都切换到基于 graphql api 实现上面,所以新的小程序端就需要完全支持 grapqhl api的实现。

选型

小程序选型

首先是小程序端选型的问题,我们今年以前的所有小程序都是原生+uni来实现的,再早一点也用到过 wepy,但主要还是 uni。但今年由于 vue3 的到来和对于 typescript的应用,我们需要一个能对 typescript + vue3支持较好的小程序方案。现在市面对于这个需求支持最好的就是 taro3 了。

Graphql client 库选型

Taro 做为小程序的实现是比较满足需求的,但是 taro3 官方并没有针对 graphql 支持,而社区中主要还是基于 @apollo 的库方案比较多一些,还有一些直接是基于 post 请求来实现的,但是整体来讲方案都比较简陋,或者有一定兼容问题。graphql client实现是有一套规范标准,并且针对使用复合API编写响应式查询/变量、缓存还是要有一定支持才能体现 graphql 的强大。

经过反复选型和试验,市面能支持我们需求(Vue3+typescript+完善的 graphql 实现)的最终有两个库可选:

  1. URQL


用于React、Svelte、Vue或JavaScript的高度可定制和通用的GraphQL客户端,这个 graphql 最初实现是基于 react 端的,后期已经对各流行的库有了完善支持 https://formidable.com/open-source/urql/

  1. Villus


这是一个小而快速的GraphQL客户端,对 vue3 有完善的支持。https://villus.logaretm.com/

实现

以上两个库的网络都是基于 fetch 来实现的,所以直接导入进 taro3 工程是没有办法实现小程序端网络请求的。小程序会有自己的 wx-request,taro 也是封装了请求而已。所以我们要做一项工作就是实现一个 "fetch" 接口来适配。
URQL这个库经过适配编译会出现异常,并且包较大一些不太适配,最终选用的是 villus 直接将源码引入到 taro 工程中,结构如下:

├── villus│   ├── Mutation.ts│   ├── Provider.ts│   ├── Query.ts│   ├── Subscription.ts│   ├── cache.ts│   ├── client.ts│   ├── dedup.ts│   ├── fetch-taro.ts│   ├── fetch.ts│   ├── handleSubscriptions.ts│   ├── helpers.ts│   ├── index.ts│   ├── shared│   ├── symbols.ts│   ├── types.ts│   ├── useClient.ts│   ├── useMutation.ts│   ├── useQuery.ts│   ├── useSubscription.ts│   └── utils└── wxcomponents

我们只需要对 fetch.ts 进行改造,加入一个 fetch-taro.ts 的适配,改造如下:
** fetch.ts 原始文件**

import { GraphQLError } from 'graphql';import { ClientPlugin } from './types';import { makeFetchOptions, resolveGlobalFetch, parseResponse } from './shared';import { CombinedError } from './utils';interface FetchPluginOpts {  fetch?: typeof window['fetch'];}export function fetch(opts?: FetchPluginOpts): ClientPlugin {  const fetch = opts?.fetch || resolveGlobalFetch();  if (!fetch) {    throw new Error('Could not resolve a fetch() method, you should provide one.');  }  return async function fetchPlugin(ctx) {    const { useResult, opContext, operation } = ctx;    const fetchOpts = makeFetchOptions(operation, opContext);    let response;    try {      response = await fetch(opContext.url as string, fetchOpts).then(parseResponse);    } catch (err) {      return useResult(        {          data: null,          error: new CombinedError({ response, networkError: err }),        },        true      );    }...

fetch-taro.ts改造后文件

import {GraphQLError} from 'graphql';import {ClientPlugin, CombinedError} from "./index";import Taro from '@tarojs/taro';import {makeFetchOptions} from "./shared";export function fetch(): ClientPlugin {  return async function fetchPlugin(ctx) {    const {useResult, opContext, operation} = ctx;    const fetchOpts = makeFetchOptions(operation, opContext);    let response;    try {        const requestTask = Taro.request({        header: opContext.headers,        url: opContext.url as string,        method: 'POST',        data: fetchOpts.body,        dataType: "json",      })      response = await requestTask    } catch (err) {      return useResult(        {          data: null,          error: new CombinedError({response, networkError: err}),        },        true      );    }...

重点是把原来的 await fetch(...) 改造为 Taro.request(...) 这样一个适配就使我们引入了一个完善的 grapqhl 客户端。

应用

1. 实现 graphql client 全局定义

import {createClient} from '../villus';import global from "../utils/global";import {fetch} from '../villus/fetch-taro'import config from '../config'function authPlugin({opContext}) {  opContext.headers.Authorization = 'Bearer ' + global.getToken();}export const client = createClient({  url: config.baseUrl + 'weapp-api',  use: [ authPlugin, fetch() ],  cachePolicy: 'network-only',});

2. 定义 graphql 文件

import gql from 'graphql-tag';export const Login = gql`  mutation WxLogin($code: String!){    wxLogin(code: $code){      user{        id        identifier        token        permissions      }    }  }`### API 式请求

3. auth.ts API请求文件

  /**   * 开始登录   */  static async doLogin() {    // 取得微信 code    const {code} = await this.wxLogin()    return client.executeMutation({      query: Login,      variables: {        code      }    })  }

响应式请求

  import { useQuery } from "villus";  const FetchFood = `  query QueryFoods($operator: StringOperators!){    foods(options:{filter:{      food: $operator    }}){      items{        id        food        meta{          transform{            key            unit          }        }      }      totalItems    }  }  `;  import SearchView from '../../components/common-search/index'  export default {    components: {      SearchView    },    setup() {      const {  execute, data, isFetching } = useQuery({        query: FetchFood,        variables: {          "operator": {            "contains": "猪肉"          }        }      })      return {        data      }    },...

客户端测试

总结

此次文章中记录了 taro3 + vue3 + graphql 的整合方案,评估了 URQL和Villus两套方案,最终选用 Villus 的改造方案,完成了整套技术的结合,并最终在商业应用中完美的使用。希望对有在小程序中使用 grahql 的朋友有所帮助。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

鲜花

握手

雷人

路过

鸡蛋
发表评论

最新评论

引用 李白笑了 2022-1-13 18:41
发现个更简洁的方法,可以不考虑更改源码,直接使用fetch调整内部的请求即可,详见 https://www.rea.ink/views/frontend/uni-app-graphql.html

查看全部评论(1)

返回顶部