如何解决Vuetify结合GraphQL/Apollo自定义主题色的TypeScript报错?
接入GraphQL动态Vuetify主题的报错问题
GraphQL 与 Apollo 的基础功能运行正常。
TypeScript 定义文件 AllColors.ts 的内容如下:
import gql from 'graphql-tag' export const ALL_COLORS = gql` query allColors { allColors { primary secondary } } `
尝试在 plugin/vuetify.ts 中实现对应主题配置逻辑时,代码无法正常运行。写出的配置代码如下:
import Vue from 'vue'; import Vuetify from 'vuetify/lib/framework'; import colors from 'vuetify/lib/util/colors'; import { ALL_COLORS } from '@/graphql/AllColors' Vue.use(Vuetify); export default new Vuetify({ data() { return { allColors: [] } }, theme: { themes: { dark: { primary: this.allColors.primary, secondary: this.allColors.secondary }, }, }, apollo: { allColors: { query: ALL_COLORS } } });
运行后编译可以通过,服务正常启动,但TypeScript类型检查抛出如下错误:
DONE Compiled successfully in 240ms 12:54:25 Type checking in progress... App running at: - Local: http://localhost:8080/ - Network: http://192.168.0.102:8080/ ERROR in /home/user1/sites/app1/src/plugins/vuetify.ts(24,19): 26:19 Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature. 24 | primary: this.allColors.primary, | ^ 25 | secondary: this.allColors.secondary 26 | }, 27 | }, 28 | }, ERROR in /home/user1/sites/app1/src/plugins/vuetify.ts(25,21): 26:19 Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature. 24 | primary: this.allColors.primary, 25 | secondary: this.allColors.secondary | ^ 26 | }, 27 | }, 28 | }, Version: typescript 3.9.7 Time: 313ms
问题原因与解决方法
报错核心来源
- 你在Vuetify构造参数的对象字面量中使用
this.allColors,但这段theme配置代码执行时,不存在Vue组件实例上下文,this直接指向全局globalThis对象,因此TypeScript报“无索引签名”的错误,根本无法取到你在data字段中定义的allColors值。 - Vuetify本身不是Vue组件,你传入的
apollo配置块不会被Apollo插件识别,完全不生效;data字段写在Vuetify构造参数里也没有实际意义。
修正方案
- 初始化Vuetify实例时设置兜底主题值,避免首次渲染时颜色为空
- 引入已经初始化完成的Apollo客户端,独立执行GraphQL查询获取颜色返回值
- 拿到返回值后通过Vuetify实例的内置属性动态更新主题配置
- 给查询返回值补充对应的TypeScript类型声明,解决类型检查报错
修正后的代码示例:
import Vue from 'vue'; import Vuetify from 'vuetify/lib/framework'; import { ALL_COLORS } from '@/graphql/AllColors' import apolloClient from '@/plugins/apollo' // 引入项目中已初始化的Apollo客户端 Vue.use(Vuetify); // 定义接口返回的颜色类型 interface AllColorsResponse { allColors: { primary: string; secondary: string; } } // 初始化Vuetify实例,配置兜底默认主题 const vuetify = new Vuetify({ theme: { themes: { dark: { primary: '#1976D2', // 兜底默认主色 secondary: '#424242' // 兜底默认次色 } } } }); // 执行GraphQL查询获取动态颜色配置 apolloClient.query<AllColorsResponse>({ query: ALL_COLORS }).then(res => { const { primary, secondary } = res.data.allColors; // 动态更新Vuetify主题配置 vuetify.theme.themes.dark.primary = primary; vuetify.theme.themes.dark.secondary = secondary; }); export default vuetify;
内容的提问来源于stack exchange,提问作者Developer
相关产品推荐
相关产品推荐

