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

在已配置vue-apollo的Quasar组件中使用useMutation报错,求解决方案

在Quasar组件中正确使用Vue Apollo Mutation的解决方案

问题背景

已在Quasar项目中完成vue-apollo的安装与配置,查询功能正常,但调用useMutation()时出现错误,需求是通过Mutation从后端API获取登录token。

原错误代码

<script lang="ts">
import gql from 'graphql-tag'
import { defineComponent } from 'vue'
import { useMutation } from '@vue/apollo-composable';

export default defineComponent({
    name: 'Login',
    data () {
        return {
            username: 'David_test',
            password: 'david'
        }
    },
    
methods:{
    login () {
        const { mutate: login } = useMutation(
            gql`
                mutation login(
                    $username: String!
                    $password: String!
                ) {
                    login (
                        username: $username
                        password: $password
                    ) {
                        token
                    }
                }
            `, () => (
            {
                variables: {
                    username: this.username,
                    password: this.password
                }
            })
        )
        
        login()
        
    }
}
})
</script>

项目依赖配置

{
 "dependencies": {
    "@quasar/extras": "^1.0.0",
    "pinia": "^2.0.11",
    "quasar": "^2.6.0",
    "vue": "^3.0.0",
    "vue-router": "^4.0.0"
  },
  "devDependencies": {
    "@quasar/app-vite": "^1.0.0",
    "@quasar/quasar-app-extension-apollo": "^2.0.0-beta.5",
    "@types/node": "^12.20.21",
    "autoprefixer": "^10.4.2",
    "typescript": "^4.5.4"
  },
  "engines": {
    "node": "^18 || ^16 || ^14.19",
    "npm": ">= 6.13.4",
    "yarn": ">= 1.21.1"
  }
}

核心问题分析

Vue 3的组合式API函数(如useMutation)不能在选项式API的methods内部调用,这类函数必须在组件的setup()函数或<script setup>语法糖中执行,否则会丢失Apollo客户端上下文,导致报错。同时原代码中useMutation的第二个参数写法错误,该参数应为配置对象而非回调函数。

正确实现方案

方案一:使用<script setup>语法糖(推荐)

这是Vue 3最简洁规范的写法,适配组合式API:

<script setup lang="ts">
import gql from 'graphql-tag'
import { useMutation } from '@vue/apollo-composable';
import { ref } from 'vue';

// 定义响应式表单变量
const username = ref('David_test')
const password = ref('david')

// 初始化Mutation
const { mutate: login } = useMutation(gql`
    mutation login(
        $username: String!
        $password: String!
    ) {
        login (
            username: $username
            password: $password
        ) {
            token
        }
    }
`)

// 登录处理函数
const handleLogin = async () => {
    try {
        const result = await login({
            variables: {
                username: username.value,
                password: password.value
            }
        })
        // 处理返回的token
        if (result?.data?.login?.token) {
            console.log('获取到token:', result.data.login.token)
            // 可将token存入本地存储或Pinia状态管理
        }
    } catch (error) {
        console.error('登录失败:', error)
    }
}
</script>

<template>
  <input v-model="username" type="text" placeholder="用户名">
  <input v-model="password" type="password" placeholder="密码">
  <button @click="handleLogin">登录</button>
</template>

方案二:在选项式API的setup()中使用

若需保留选项式API结构,可在setup()中初始化Mutation并暴露方法:

<script lang="ts">
import gql from 'graphql-tag'
import { defineComponent, ref } from 'vue'
import { useMutation } from '@vue/apollo-composable';

export default defineComponent({
    name: 'Login',
    setup() {
        const username = ref('David_test')
        const password = ref('david')

        const { mutate: login } = useMutation(gql`
            mutation login(
                $username: String!
                $password: String!
            ) {
                login (
                    username: $username
                    password: $password
                ) {
                    token
                }
            }
        `)

        const handleLogin = async () => {
            try {
                const result = await login({
                    variables: {
                        username: username.value,
                        password: password.value
                    }
                })
                console.log('token:', result?.data?.login?.token)
            } catch (err) {
                console.error('登录出错:', err)
            }
        }

        // 暴露变量与方法给模板
        return {
            username,
            password,
            handleLogin
        }
    }
})
</script>

<template>
  <input v-model="username" type="text" placeholder="用户名">
  <input v-model="password" type="password" placeholder="密码">
  <button @click="handleLogin">登录</button>
</template>

关键注意事项

  • 组合式API函数必须在setup()或<script setup>中调用,禁止在methods、computed等选项内部使用。
  • 调用mutate时直接传入包含variables的配置对象即可,无需使用回调函数包裹。
  • 优先使用async/await处理异步操作,提升代码可读性。

内容的提问来源于stack exchange,提问作者David Arpasi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:36:00