在globalProperties上Vue3响应组件



在vuejs 2中,可以像这样将组件分配给主应用实例中的全局变量…

const app = new Vue({});
Vue.use({
install(Vue) {
Vue.prototype.$counter = new Vue({
data: () => ({ value: 1 }),
methods: {
increment() { this.value++ },
}
});
}
})
app.$mount('#app');

但是当我将它转换为ve3时,我不能访问任何属性或方法…

const app = Vue.createApp({});
app.use({
install(app) {
app.config.globalProperties.$counter = Vue.createApp({
data: () => ({ value: 1 }),
methods: {
increment() { this.value++ }
}
});
}
})
app.mount('#app');

下面是一个示例:https://jsfiddle.net/Lg49anzh/

这是vue3版本…https://jsfiddle.net/Lathvj29/

所以我想知道如果和如何这仍然可能在vue3或我需要重构我所有的插件?

我试着让例子尽可能简单来说明问题,但如果你需要更多的信息,请告诉我。

Vue.createApp()创建一个应用实例,它与应用的根组件是分开的。

一个快速的修复方法是mount应用程序实例以获得根组件:

import { createApp } from 'vue';
app.config.globalProperties.$counter = createApp({
data: () => ({ value: 1 }),
methods: {
increment() { this.value++ }
}
}).mount(document.createElement('div')); 👈

演示1

然而,一个更习惯和更简单的解决方案是使用ref:

import { ref } from 'vue';
const counter = ref(1);
app.config.globalProperties.$counter = {
value: counter,
increment() { counter.value++ }
};

演示2

不是问题的确切答案,但相关。下面是一个在组件之间共享全局变量的简单方法。

在我的主应用程序文件中,我添加了变量$navigationProps到全局scrope:

let app=createApp(App)
app.config.globalProperties.$navigationProps = {mobileMenuClosed: false, closeIconHidden:false };
app.use(router)
app.mount('#app')

然后在任何我需要$navigationProps使用双向绑定的组件中:

<script>
import { defineComponent, getCurrentInstance } from "vue";
export default defineComponent({
data: () => ({
navigationProps:
getCurrentInstance().appContext.config.globalProperties.$navigationProps,
}),
methods: {
toggleMobileMenu(event) {
this.navigationProps.mobileMenuClosed =
!this.navigationProps.mobileMenuClosed;
},
hideMobileMenu(event) {
this.navigationProps.mobileMenuClosed = true;
},
},

对我来说很有魅力。

我用上面的技术制作全局组件(根组件中只有一个实例)。例如,像Loaders或Alerts这样的组件就是很好的例子。

Loader.vue

...
mounted() {
const currentInstance = getCurrentInstance();
if (currentInstance) {
currentInstance.appContext.config.globalProperties.$loader = this;
}
},
...

AlertMessage.vue

...
mounted() {
const currentInstance = getCurrentInstance();
if (currentInstance) {
currentInstance.appContext.config.globalProperties.$alert = this;
}
},
...

所以,在你的应用的根组件中,你必须实例化你的全局组件,如下所示:

App.vue

<template>
<v-app id="allPageView">
<router-view name="allPageView" v-slot="{Component}">
<transition :name="$router.currentRoute.name">
<component :is="Component"/>
</transition>
</router-view>
<alert-message/> //here
<loader/> //here
</v-app>
</template>
<script lang="ts">
import AlertMessage from './components/Utilities/Alerts/AlertMessage.vue';
import Loader from './components/Utilities/Loaders/Loader.vue';
export default {
name: 'App',
components: { AlertMessage, Loader }
};
</script>

最后,通过这种方式,您可以将组件置于任何其他组件中,例如:

Login.vue

... 
async login() {
if (await this.isFormValid(this.$refs.loginObserver as FormContext)) {
this.$loader.activate('Logging in. . .');
Meteor.loginWithPassword(this.user.userOrEmail, this.user.password, (err: Meteor.Error | any) => {
this.$loader.deactivate();
if (err) {
console.error('Error in login: ', err);
if (err.error === '403') {
this.$alert.showAlertFull('mdi-close-circle', 'warning', err.reason,
'', 5000, 'center', 'bottom');
} else {
this.$alert.showAlertFull('mdi-close-circle', 'error', 'Incorrect credentials');
}
this.authError(err.error);
this.error = true;
} else {
this.successLogin();
}
});
...

通过这种方式,您可以避免在每个组件中导入这些组件。

为什么不使用这种最小的方法呢?

import Manager from "@/Manager"; //Manager is a basic ES6 class with declared properties
import { reactive } from 'vue';
app.config.globalProperties.$manager=reactive(new Manager());

最新更新