You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue项目的URQL中拆分字符串中的多个GraphQL操作?

实现方案

1. 安装必要依赖

首先需要借助graphql包来解析用户输入的GraphQL代码,提取操作信息:

npm install graphql
# 或使用 yarn:yarn add graphql

2. 编写GraphQL操作解析工具函数

写一个通用函数,接收用户输入的原始GraphQL代码,解析出所有操作的名称和类型:

import { parse, visit } from 'graphql'

export function extractGraphQLOperations(rawCode) {
  try {
    const document = parse(rawCode)
    const operations = []
    visit(document, {
      OperationDefinition(node) {
        if (node.name?.value) {
          operations.push({
            name: node.name.value,
            type: node.operation // 取值为 query/mutation/subscription
          })
        }
      }
    })
    return operations
  } catch (err) {
    // 处理用户输入的代码语法错误
    return []
  }
}

3. Vue组件中实现下拉选择与操作执行

以Vue 3 + Script Setup为例,结合urql的hooks完成功能:

<template>
  <div class="graphql-test-tool">
    <!-- 用户输入GraphQL代码的文本框 -->
    <textarea v-model="rawGraphQLCode" rows="12" placeholder="输入GraphQL操作代码..." class="code-input"></textarea>

    <!-- 操作选择下拉框(仅当存在多个操作时显示) -->
    <select v-if="operations.length > 1" v-model="selectedOpName" class="op-select">
      <option v-for="op in operations" :key="op.name" :value="op.name">
        {{ op.name }} ({{ op.type }})
      </option>
    </select>

    <!-- 运行按钮 -->
    <button @click="runSelectedOp" class="run-btn">运行</button>

    <!-- 结果展示区域 -->
    <div class="result-container" v-if="result">
      <pre>{{ JSON.stringify(result, null, 2) }}</pre>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { useQuery, useMutation, useSubscription } from '@urql/vue'
import { parse, print } from 'graphql'
import { extractGraphQLOperations } from './utils/graphql'

// 绑定用户输入的原始GraphQL代码
const rawGraphQLCode = ref(`query Message {
  messages {
    user
    content
  }
}

subscription RealtimeMessage {
  messages{
    content
    user
  }
}

mutation SendMessage {
  postMessage(user: "User ID", content: "Hi")
}`)

// 解析得到的操作列表
const operations = computed(() => extractGraphQLOperations(rawGraphQLCode.value))
// 默认选中第一个操作
const selectedOpName = ref(operations.value[0]?.name)

// 提取选中操作的完整代码(用graphql的print函数保证准确性)
const selectedOpCode = computed(() => {
  if (!selectedOpName.value) return ''
  try {
    const document = parse(rawGraphQLCode.value)
    const targetOp = document.definitions.find(def => 
      def.kind === 'OperationDefinition' && def.name?.value === selectedOpName.value
    )
    return targetOp ? print(targetOp) : ''
  } catch (err) {
    return ''
  }
})

const result = ref(null)

async function runSelectedOp() {
  const targetOp = operations.value.find(op => op.name === selectedOpName.value)
  if (!targetOp || !selectedOpCode.value) return

  result.value = null
  try {
    switch (targetOp.type) {
      case 'query': {
        const { data } = await useQuery({ query: selectedOpCode.value }).execute()
        result.value = data
        break
      }
      case 'mutation': {
        const { data } = await useMutation(selectedOpCode.value)()
        result.value = data
        break
      }
      case 'subscription': {
        // 订阅需要监听数据流,这里简单处理为实时更新结果
        const subscription = useSubscription({ query: selectedOpCode.value })
          .subscribe(({ data }) => {
            result.value = data
          })
        // 可保存subscription实例,用于后续取消订阅
        break
      }
    }
  } catch (err) {
    result.value = { error: err.message }
  }
}
</script>

<style scoped>
.graphql-test-tool {
  max-width: 850px;
  margin: 30px auto;
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.code-input {
  padding: 12px;
  font-family: monospace;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.op-select {
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #ddd;
}

.run-btn {
  padding: 10px;
  background-color: #2563eb;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.result-container {
  padding: 12px;
  border: 1px solid #eee;
  border-radius: 4px;
  background-color: #f8fafc;
}

pre {
  white-space: pre-wrap;
  margin: 0;
}
</style>

关键细节说明

  • 解析可靠性:用graphql官方的parse和visit函数解析代码,比手动正则匹配更稳定,能处理各种合法的GraphQL语法
  • 操作提取:使用print函数从解析后的AST节点生成选中操作的代码,确保代码格式正确
  • urql适配:根据操作类型选择对应的hook(query/mutation/subscription),严格匹配urql的使用规范
  • 错误处理:包含了代码解析错误和操作执行错误的处理,避免组件崩溃

内容的提问来源于stack exchange,提问作者Anwarul Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 01:30:56