當我需要動態生成 graphql 的 template 時,做了一個騷操作

echozh發表於2020-04-02

成立背景

在一個專案中,一個請求的結構,裡面包含三種許可權,許可權可以任意組合

一開始我的想法

這個操作有點騷,我提前準備好各種許可權組合的 template ?想了下我可能需要準備如下情況

許可權 A 許可權 B 許可權 C
X X X
X X️ ✔️
X ✔️ ✔️
✔️
X
X X
X X
X

有這 8 種,如果到時候再我加一個許可權,豈不是要原地去世。然後就考慮了下 gql 函式直接傳模板,通過對模板的過濾來生成我們想要的模板,於是就看了下用法,

// 這樣的
import gql from 'graphql-tag'

const t = gql`
   query Demo {
       
   }
`
// 支援傳 fragment 的
const t2 = gql`
   query Demo {
       ...Fragment
   }
   ${Fragment}
`
複製程式碼

看了半天沒找到我要的結果,於是我就到 graphql-tag 原始碼裡面看了下,如下圖

當我需要動態生成 graphql 的 template 時,做了一個騷操作

這裡我們看到一個 literals 變數,他就是 gql 函式的第一個引數傳進來的 template,但是如果我們直接如下使用

gql(`
    query Demo {
        ...Fragment
    }
 `, Fragment)
複製程式碼

literals 這個值就是一個純字串,到下面的拼接 args,我們可以想一下 result 肯定會被加上一些莫名其妙的字元,結局就是 parseDocument 報錯,到這裡我們要先停一下,這個時候,我們就需要去了解普通的函式呼叫和字串模板函式呼叫的區別

函式呼叫的區別

在這裡我只是簡單的列印下兩種函式呼叫的 arguments 給大家看下

當我需要動態生成 graphql 的 template 時,做了一個騷操作

我們可以看到區別就是第一個引數 arguments[0] 是不同的,普通函式是字串,模板字串函式是一個陣列,這個陣列包含一個原始模板和一個傳入的佔位符

結果

所以到此我們就有了動態模板的思路了,我們只需要構造一個和模板字串第一個引數一樣結構的引數傳入 gql 就 ok 了

export function stringRaw(template, args = 0) {
  const r = new Array(args)
  if (r.length !== 0) {
    r.fill('')
  }
  r.unshift(template)
  return r
}

const t = gql(stringRaw(`
    query Demo{
        field1
        ${permissionA ? 'field2' : ''}
        ${permissionB ? 'field3' : ''}
        ${permissionC ? 'field4' : ''}
        field5 {
            ...Fragment
        }
    }
`, 1), Fragment)
複製程式碼

至此我們就完成了傳入動態字串了

相關文章