如何在Vue导出函数GISWSCaller中正确使用provide?
问题描述
我想导出函数GISWSCaller,参考某教程实现其第3段代码示例的效果,但在GISWSCaller.ts中调用provide('GISWSContext', ctx)时浏览器出现警告,尽管已经导入了{ provide } from 'vue'。请告知如何在GISWSCaller中正确使用provide;如果无法在导出函数中使用provide,请解释教程作者的实现方式。
附带代码如下:
GISWSCaller.ts
import { provide } from 'vue'; let res = undefined export default function GISWSCaller(){ async function fetchURL(params){ console.log("params:",params); const splitted = params.split(',') if (splitted.length == 4) { const response = await fetch('https://xx/xx/getDistanceFromOriginToDestination/' + params) res = await response.json() return res } return false } const ctx = { fetchURL } provide('GISWSContext',ctx) return fetchURL }
App.vue 调用代码
<template> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> <g-i-s-w-s-caller @evtRunWSRouteTest="evtReceiverForRunWSRouteTest"/> </template> <script> import HelloWorld from './components/HelloWorld.vue' import GISWSCaller from './composables/GISWSCaller.ts' import { reactive } from 'vue' export default { name: 'App', components: { HelloWorld, GISWSCaller } } </script> <script setup> const g = GISWSCaller() console.log("g:",g['fetchURL']('30.976639,30.056021,30.97775,30.033333')); // functions function evtReceiverForRunWSRouteTest(e) { console.log("evt:",e); } </script>
解决方案
一、正确在GISWSCaller中使用provide的方式
警告的核心原因是**provide必须在Vue组件的生命周期或<script setup>/组件setup选项的同步执行阶段调用**,你直接在普通导出函数里调用provide时,Vue没有当前组件实例的上下文,因此会抛出警告。
修复步骤
- 调整
GISWSCaller.ts,避免全局变量污染
import { provide } from 'vue'; export default function GISWSCaller(){ // 将res移到函数内部,防止全局变量冲突 let res = undefined; async function fetchURL(params){ console.log("params:",params); const splitted = params.split(',') if (splitted.length == 4) { const response = await fetch('https://xx/xx/getDistanceFromOriginToDestination/' + params) res = await response.json() return res } return false } const ctx = { fetchURL } // 仅当函数在组件setup上下文被调用时,provide才能正常工作 provide('GISWSContext', ctx) return fetchURL }
- 修正
App.vue的调用逻辑
- 移除组件注册中的
GISWSCaller(它是组合式函数,不是Vue组件) - 异步函数调用需用
await或.then处理结果
<template> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> </template> <script> import HelloWorld from './components/HelloWorld.vue' import { reactive } from 'vue' export default { name: 'App', components: { HelloWorld // 移除GISWSCaller的组件注册 } } </script> <script setup> import GISWSCaller from './composables/GISWSCaller.ts' // 在组件setup上下文调用GISWSCaller,此时provide能获取到组件实例 const g = GISWSCaller() // 正确处理异步函数返回值 g('30.976639,30.056021,30.97775,30.033333').then(result => { console.log("请求结果:", result); }) function evtReceiverForRunWSRouteTest(e) { console.log("evt:",e); } </script>
二、教程作者的实现逻辑
教程中的组合式函数能直接使用provide,是因为作者默认该函数会在组件的setup上下文(<script setup>或组件setup选项)中被调用。只有在这个前提下,provide才能获取到当前组件的注入上下文,从而正常执行。
组合式函数的设计初衷就是为了在组件setup阶段复用逻辑,因此provide/inject这类依赖组件实例的API,只能在组合式函数被组件setup调用时才能正常工作。
内容的提问来源于stack exchange,提问作者Amrmsmb
相关产品推荐
相关产品推荐

