在Vue应用程序中创建一个类的单个实例

17

我刚接触Vue,目前在努力理解如何实现全局变量或单例的好处。

背景是我正在使用Azure AD B2C进行身份验证,并使用MSAL库。 MSAL要求声明 Msal.UserAgentApplication 的一个单一实例,然后通过应用程序共享它。

我遇到的问题是如何在某个中心位置声明该实例,然后从每个组件(包括路由器)访问它。

目前,我有一个类似于此示例的类:https://github.com/sunilbandla/vue-msal-sample/blob/master/src/services/auth.service.js,当我想使用这些方法时,我正在执行以下操作:

var authService = new AuthService();
authService.Login();

不幸的是,每次实例化该类都会创建一个新的MSAL实例,这反过来导致我的用户陷入了身份验证循环中。

任何帮助将不胜感激。

非常感谢。


继Teddy下面的答案之后,我已经修改了我的main.js如下:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './registerServiceWorker'
import AuthService from './services/AuthService';

Vue.config.productionTip = false

Vue.prototype.$authService = new AuthService();

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app');

我的 register.vue 组件如下:

<template>
  <div class="about">
    <h1>This is the register page, it should redirect off to B2C</h1>
  </div>
</template>

<script>
  import router from '@/router.js'

  export default {

    created(){

      this.$authService.isAuthenticated().then(
      function(result){
        if(result){
          router.push('/');  
        }
        else{
          authService.register();  
        }
      });
    }  
  } 
</script>
组件表示,this.$authService 未定义,所以显然没有读取原型。

感觉我在 Vue 中缺少一些非常基本的东西。
2个回答

16

你可以将它作为Vue实例属性添加,这样它就会存在于所有的Vue组件中。

像这样在main.js中进行设置:

Vue.prototype.$authService = new AuthService();

你可以在任何Vue组件中后续访问它。例如:

this.$authService.Login();

参考: https://v2.vuejs.org/v2/cookbook/adding-instance-properties.html

编辑: 您必须在isAuthenticated回调函数内使用this.$router.push和this.$authService.register。如果“this”在该块中引用其他内容,请在回调开始之前存储var self=this;,或使用fat arrow语法。


<script>
  //No import as router is available in 'this'
  export default {

    created(){
      var self=this; //For use inside the callback
      this.$authService.isAuthenticated().then(
      function(result){
        if(result){
          self.$router.push('/');  
        }
        else{
          self.$authService.register();  
        }
      });
    }  
  } 
</script>

编辑2:

也许你可以在名为AuthServiceInst.js的文件中创建实例(单例)。然后,你可以在main.js和router.js中导入它。

新文件AuthServiceInst.js:

import AuthService from './AuthService.js'

export const authService = new AuthService();

main.js:

import {authService} from './AuthServiceInst.js'

Vue.prototype.$authService = authService;

router.js:

import {authService} from './AuthServiceInst.js'

//Now you can use authService

嗨 Teddy,感谢你的回答,但不幸的是它没有起作用。我在我的问题上面添加了一段代码片段,如果有帮助的话?感觉我在Vue的设置方面做错了什么。 - AndyM
你必须在 isAuthenticated 回调函数内使用 this.$router.push 和 this.$authService.register。如果“this”在该块中指代其他内容,请在回调开始前先将var self=this;存储。 - Teddy
谢谢 Teddy,在组件中它很好用,但我无法在路由器内访问它。我会尽快提供代码示例更新。 - AndyM
嗨 Teddy,事实证明,你最初的建议问题都与 MSAL 有关,而不是 Vue 方面的问题,所以一切都好了,感谢你的帮助。 - AndyM
@AndyM 很高兴我能帮到你。 - Teddy

5
在Vue 3中,要声明全局实例,需要使用app.config.globalProperties。这是Vue 2的Vue.prototype的替代品,Vue 3中已不再存在。像任何全局变量一样,应该谨慎使用。
// main.js
const app = createApp(App)
  .use(router)
  .use(store)
  .use(vuetify)

app.config.globalProperties.msg = 'hello world'

app.mount('#app')

这使得msg可以在应用程序中的任何组件模板中使用,也可以在任何组件实例的上下文中使用:
export default {
  mounted() {
    console.log(this.msg) // 'hello world'
  }
}

Source: Docs


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接