wagmi Vue useClient 组合式函数完全指南:获取与响应式监听 Viem Client
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
useClient 是@wagmi/vue提供的组合式函数(Composable),用于在 Vue 组件中获取 Viem 的Client实例,并在链或配置变化时自动响应式更新。本文围绕 useClient 官方文档 展开,结合@wagmi/vue与@wagmi/core的源码与测试实现,完整讲解其导入方式、用法、参数与返回值类型,帮助读者在自己的 Vue 应用中正确、高效地拿到链上客户端,用于签名、发送交易或调用合约。
背景:Viem Client 与 useClient 的角色
在 wagmi 生态中,Viem 的Client中管理,而useClient就是 Vue 组件与 ViemClient之间的桥梁:
- 它从 WagmiPlugin 提供的全局配置中读取链状态;
- 它返回一个 Vue 的
Ref<Client | undefined>,当链切换(switchChain)或配置初始化完成后,client.value会随之更新; - 组件卸载时自动清理订阅,无需手动调用
unwatch。
也就是说,useClient并不是简单的一次性取值,而是一个响应式的客户端访问入口。
导入方式
与@wagmi/vue其他组合式函数一致,直接从包入口导入即可:
import { useClient } from '@wagmi/vue'对应的类型UseClientParameters与UseClientReturnType同样从@wagmi/vue导出,供需要显式标注类型的场景使用:
import { type UseClientParameters } from '@wagmi/vue' import { type UseClientReturnType } from '@wagmi/vue'基础用法
在<script setup>中调用useClient(),即可拿到当前链对应的 Viem Client:
<script setup lang="ts"> import { useClient } from '@wagmi/vue' const client = useClient() </script>该组合式函数需要配合已安装的WagmiPlugin使用——插件通过app.provide(configKey, config)将 Config 注入到组件树中(见 packages/vue/src/plugin.ts),useClient内部再通过inject取出。示例中./config对应的配置文件如下(见 site/snippets/vue/config.ts):
import { createConfig, http } from '@wagmi/vue' import { mainnet, sepolia } from '@wagmi/vue/chains' export const config = createConfig({ chains: [mainnet, sepolia], transports: { [mainnet.id]: http(), [sepolia.id]: http(), }, })默认(不传任何参数)时,useClient返回当前激活链对应的 Client:若当前激活链为主网,则返回连接 mainnet 的 Client。
一个完整的组件示例
下面是一个可直接运行的组合示例,先安装插件,再在组件中读取 Client 并展示其链信息:
// main.ts import { createApp } from 'vue' import { WagmiPlugin } from '@wagmi/vue' import { config } from './config' const app = createApp(App) app.use(WagmiPlugin, { config }) app.mount('#app')<!-- App.vue --> <script setup lang="ts"> import { useClient } from '@wagmi/vue' const client = useClient() </script> <template> <div v-if="client"> <p>当前链 ID:{{ client.chain.id }}</p> <p>Transport 类型:{{ client.transport.type }}</p> </div> <p v-else>Client 尚未就绪或当前链未配置</p> </template>参数详解
useClient接受一个可选的UseClientParameters对象。从源码看(packages/vue/src/composables/useClient.ts),其类型为DeepMaybeRef<GetClientParameters<config, chainId> & ConfigParameter<config>>,其中DeepMaybeRef意味着参数既可以是普通值,也可以是 Vue 的 ref,从而支持响应式传参。可配置的参数共有两个。
chainId
- 类型:
config['chains'][number]['id'] | undefined - 作用:指定要获取 Client 的链 ID。不传时使用当前激活链。
典型用法是明确指定某条链:
<script setup lang="ts"> import { useClient } from '@wagmi/vue' import { mainnet } from '@wagmi/vue/chains' // [!code focus] import { config } from './config' const client = useClient({ chainId: mainnet.id, // [!code focus] }) </script>几点重要的行为细节(均有源码或测试佐证):
- 响应式参数:
chainId可以传入一个ref,改变 ref 的值会触发 Client 更新。测试 packages/vue/src/composables/useClient.test.ts 中,chainId从ref(456)变为1后,等待断言client?.chain.id === 1通过,验证了这一行为。 - 未配置的链返回 undefined:若传入的
chainId不在config的chains列表中,返回值是undefined而非抛错。测试behavior: unconfigured chain(同文件第 38-40 行)以chainId: 123456验证了这一点;底层原因在于getClient内部用try/catch包裹config.getClient(parameters),失败时返回undefined(见 packages/core/src/actions/getClient.ts)。 - 类型层面的约束:在类型测试 packages/vue/src/composables/useClient.test-d.ts 中,向已配置的
config传入chainId: 123456会触发@ts-expect-error,即 TS 会在编译期阻止你访问未配置链的 Client 类型;而省略config参数时,未配置链只会收窄为undefined,代码需先做空值判断才能访问client.value.chain。
config
- 类型:
Config | undefined - 作用:显式传入 Config,以替代从
WagmiPlugin注入的全局配置。适用于测试、多配置实例或希望在组件树之外使用useClient的场景。
<script setup lang="ts"> import { useClient } from '@wagmi/vue' import { config } from './config' // [!code focus] const client = useClient({ config, // [!code focus] }) </script>从实现看,useClient内部先调用useConfig(params)(packages/vue/src/composables/useConfig.ts):若显式传入了config则直接透传使用;否则检查是否存在注入上下文并inject全局配置,未安装WagmiPlugin时会抛出WagmiPluginNotFoundError。因此config参数既是覆盖手段,也是脱离插件依赖时的逃生通道。
返回值类型
useClient的返回类型为:
import { type UseClientReturnType } from '@wagmi/vue'- 类型:
Ref<Client | undefined> - 含义:一个 Vue 响应式引用,其值为 Viem 的
Client实例或undefined。
关于返回值的三个关键点:
- 可能是 undefined:链未配置、配置尚未就绪或当前链没有可用 transport 时,
client.value为undefined。在模板中应使用v-if="client"之类的守卫,或在使用前做空值判断。 - 只读 Ref:源码最后返回
readonly(client)(见 packages/vue/src/composables/useClient.ts),即外部无法直接改写返回值,客户端实例始终由 wagmi 内部状态驱动,避免出现状态漂移。 - 类型随参数收窄:通过
config与chainId泛型推导,TypeScript 能精确推断出client.value.chain与client.value.transport.type的具体类型(见 packages/vue/src/composables/useClient.test-d.ts),为链 ID、transport 类型等提供编译期校验。
响应式更新机制与底层 Action
useClient的响应式能力建立在两个核心 Action 之上,这也是文档末尾 Action 一节列出的内容:
getClient:同步获取 Client 实例。核心实现为config.getClient(parameters),失败时捕获异常并返回undefined(见 packages/core/src/actions/getClient.ts)。watchClient:订阅 Client 的变化。它通过config.subscribe注册监听,并用a?.uid === b?.uid作为相等性判断(见 packages/core/src/actions/watchClient.ts)——只要 Client 实例的uid未变,就认为没有变化,避免无意义的重复触发。
结合 packages/vue/src/composables/useClient.ts 的实现,useClient的完整工作流程如下:
const params = computed(() => deepUnref(parameters)):把参数中的 ref 全部解包,得到稳定的纯对象(deepUnref的实现见 packages/vue/src/utils/cloneDeep.ts);const config = useConfig(params):按上文规则解析配置;const client = ref(getClient(config, params.value)):初始同步取值;watchEffect(() => { client.value = getClient(...) }):当参数(如chainIdref)变化时重新取值;watchClient(config, { onChange }):订阅全局 Client 变化(如调用switchChain切换链),仅在uid变化时更新本地 ref;组件卸载时通过onScopeDispose(() => unsubscribe())自动清理订阅。
这一设计保证了:无论用户手动switchChain切换链,还是配置在运行时被更新,client.value都会保持与全局状态一致。
典型使用场景
- 发送交易与合约调用:将
useClient()返回的 Client 传给viem的writeContract、sendTransaction等函数,用于签名与广播交易。 - 读取链上数据:结合
readContract、getBalance等读取操作,并在链切换后自动使用新链的 Client。 - 展示当前网络状态:在 UI 中展示
client.chain.id、client.transport.type等信息,切换网络时界面自动刷新。 - 多链场景按需取客户端:通过
chainId参数固定获取某条链的 Client,而不受当前激活链影响。
常见问题与注意事项
- 没有安装 WagmiPlugin 会怎样?未传
config参数且未安装插件时,useConfig会抛出WagmiPluginNotFoundError;若连注入上下文都不存在(如在非组件环境中调用),则抛出WagmiInjectionContextError。解决方式是安装插件,或显式传入config。 - client 为 undefined 时不要直接解构:
useClient返回值可能为undefined,直接访问client.value.chain会报错;建议先用v-if或if守卫。 - chainId 未配置时不会报错,但会静默返回 undefined:这便于实现“可用则用、不可用则降级”的逻辑,但也要求开发者对未配置链做显式处理。
- 订阅自动清理:
useClient借助 Vue 的onScopeDispose在组件卸载时取消watchClient订阅,因此无需在onUnmounted中手动清理。
小结
useClient是@wagmi/vue中连接 Vue 响应式系统与 ViemClient的核心组合式函数:它从 WagmiPlugin 提供的全局配置解析链状态,支持通过chainId指定目标链、通过config覆盖全局配置,内部依托getClient与watchClient两个 Action 实现同步取值与响应式监听。理解其参数语义、返回类型及底层订阅机制,有助于在多链、动态切换网络的 Vue dApp 中写出类型安全且状态一致的客户端访问代码。
【免费下载链接】wagmiReactive primitives for Ethereum apps项目地址: https://gitcode.com/GitHub_Trending/wa/wagmi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考