Vue3 CLI项目如何正确添加可全局调用的公共服务方法?
报错根因说明
你使用的模态框代码是针对Vue2编写的,Vue3已经移除了全局的Vue构造函数,同时废弃了实例的$on/$emit事件API,所以直接在Vue3项目中调用必然触发TypeError: default is not a constructor报错。
以下是适配Vue3 CLI项目的正确实现方式:
第一步:重构modal.service.js
不需要依赖Vue构造函数,自行实现轻量的事件监听/触发逻辑即可保持原功能:
// modal.service.js const eventBus = { listeners: [], $on(callback) { this.listeners.push(callback) }, $emit(payload) { this.listeners.forEach(cb => cb(payload)) } } export default { // 对外暴露的调用方法,返回Promise和原逻辑完全一致 open(component, props = {}) { return new Promise((resolve, reject) => { eventBus.$emit({ component, props, resolve, reject }) }) }, // 给ModalRoot组件使用的内部监听方法 _registerListener(callback) { eventBus.$on(callback) } }
第二步:修改ModalRoot.vue适配逻辑
只需要调整事件监听的入口,原有渲染逻辑不需要改动:
<script> import ModalService from '../services/modal.service'; import Modal from '../components/Modal.vue'; export default { components: { Modal }, data() { return { modal: {}, } }, created() { // 替换原有的ModalService.$on监听 ModalService._registerListener(({ component, props, resolve, reject }) => { this.modal = { component, props, close: value => { this.modal = {}; resolve(value); }, dismiss: reason => { this.modal = {}; reject(reason); }, }; }); } } </script>
第三步:注册全局调用方法(可选)
如果需要在项目任意组件内无需import直接调用,可以在main.js中挂载为全局属性:
import { createApp } from 'vue' import App from './App.vue' import router from './router' import './assets/styles.css' // 引入改造后的模态框服务和根组件 import ModalService from './services/modal.service' import ModalRoot from './components/ModalRoot.vue' const app = createApp(App) // 挂载全局方法,组件内通过this.$modal调用 app.config.globalProperties.$modal = ModalService // 注册全局ModalRoot组件 app.component('ModalRoot', ModalRoot) app.use(router) app.mount('#app')
最后在App.vue的最外层 template 中添加<ModalRoot />,确保模态框可以渲染到页面顶层。
调用示例
选项式API组件内调用
// 按钮点击事件中直接调用 this.$modal.open(自定义弹窗组件, { 标题: '测试', 内容: '弹窗内容' }) .then(res => { // 处理用户点击确认的返回结果 }) .catch(err => { // 处理用户关闭/取消的返回结果 })
组合式API组件内调用
直接import ModalService调用即可,也可以自行封装为useModal组合式函数使用。
内容的提问来源于stack exchange,提问作者Harvey Mushman
相关产品推荐
相关产品推荐

