在已配置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
相关产品推荐
相关产品推荐

