全局属性上的Vue3React组件

x33g5p2x  于 2022-11-25  发布在  Vue.js
关注(0)|答案(3)|浏览(291)

在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');

但是当我将其转换为vue3时,我无法访问任何属性或方法...

const app = Vue.createApp({});

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

app.mount('#app');

以下是vue2... https://jsfiddle.net/Lg49anzh/的示例
这里是vue3版本... https://jsfiddle.net/Lathvj29/
所以我想知道这是否以及如何在vue3中仍然可能,或者我需要重构我所有的插件吗?
我试图保持尽可能简单的例子来说明问题,但如果你需要更多的信息,只是让我知道。

f45qwnt8

f45qwnt81#

Vue.createApp()创建一个应用程序示例,该示例独立于应用程序的根组件。
一种快速解决方法是对应用程序示例执行mount操作以获取根组件:

import { createApp } from 'vue';

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

demo 1
但是,一个更符合习惯且更简单的解决方案是使用ref

import { ref } from 'vue';

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

demo 2

7uzetpgm

7uzetpgm2#

这不是问题的确切答案,但与之相关。这里有一个在组件之间共享全局变量的简单方法。
在我的主应用程序文件中,我将变量$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;
    },
  },

对我来说就像一个魔咒。

mqkwyuun

mqkwyuun3#

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

  • 加载程序.vue*
...
  mounted() {
    const currentInstance = getCurrentInstance();
    if (currentInstance) {
      currentInstance.appContext.config.globalProperties.$loader = this;
    }
  },
...
  • 警报消息.vue*
...
  mounted() {
    const currentInstance = getCurrentInstance();
    if (currentInstance) {
      currentInstance.appContext.config.globalProperties.$alert = this;
    }
  },
...

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

  • 应用程序版本 *
<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>

最后,通过这种方式你可以把你的组件放在其他任何组件中,例如:

  • 登录名.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();
          }
        });
...

这样,就可以避免在每个组件中导入这些组件。

相关问题