在 Vue 应用程序中创建类的单个实例 [英] Creating a single instance of a class within a Vue application
问题描述
我是 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
如下:
从'vue'导入Vue从'./App.vue'导入应用程序从'./router'导入路由器从./store"导入商店导入'./registerServiceWorker'从 './services/AuthService' 导入 AuthService;Vue.config.productionTip = falseVue.prototype.$authService = new AuthService();新的 Vue({路由器,店铺,渲染:h =>h(应用程序)}).$mount('#app');
和我的 register.vue 组件如下:
<div class="关于"><h1>这是注册页面,它应该重定向到B2C</h1>
</模板><脚本>从@/router.js"导入路由器导出默认{创建(){this.$authService.isAuthenticated().then(功能(结果){如果(结果){router.push('/');}别的{authService.register();}});}}
组件说 this.$authService
是未定义的,所以它显然没有读取原型.
在这一点上,我感觉我错过了 Vue 中真正重要的东西.
您可以将其添加为 Vue 实例属性.它适用于所有 Vue 组件.
在 main.js 中像这样设置:
Vue.prototype.$authService = new AuthService();
您以后可以在任何 Vue 组件中访问它.例如:
this.$authService.Login();
参考:https://vuejs.org/v2/cookbook/adding-instance-properties.html
您必须在 isAuthenticated 回调中使用 this.$router.push 和 this.$authService.register .如果this"指的是该块中的其他内容,则存储 var self=this;在回调开始之前,或者使用粗箭头语法.
编辑 2:
也许您可以在名为 AuthServiceInst.js 的文件中创建实例(单例)本身.然后就可以在 main.js 和 router.js 中导入了.
新文件 AuthServiceInst.js:
从 './AuthService.js' 导入 AuthService出口 const authService = 新 AuthService();
main.js:
从 './AuthServiceInst.js' 导入 {authService}Vue.prototype.$authService = authService;
router.js:
从 './AuthServiceInst.js' 导入 {authService}//现在你可以使用authService
I'm new to Vue and I'm struggling to wrap my head around how to implement what seems to me like a good case for a global variable or singleton.
The background is that I'm using Azure AD B2C for authentication with the MSAL library. MSAL requires a single instance of the Msal.UserAgentApplication
to be declared and then shared through the application.
What I'm struggling with is how to declare that instance somewhere central and then access it from each component including the router.
At the moment I've got a class which is similar to this example: https://github.com/sunilbandla/vue-msal-sample/blob/master/src/services/auth.service.js and when I want to use the methods I'm doing:
var authService = new AuthService();
authService.Login();
Unfortunately this creates a new instance of MSAL each time the class is instantiated which in turn caused my users to end up stuck in an authentication loop.
Any help would be greatly appreciated.
Many thanks.
Following on from the answer below by Teddy I've amended my main.js
as follows:
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');
And my register.vue component as follows:
<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>
The component is saying that this.$authService
is undefined so it's obviously not reading the prototype.
It feels like I'm missing something really fundamental in Vue at this point.
You can just add it as a Vue instance property. It will be there for all Vue components.
Set it up in main.js like this:
Vue.prototype.$authService = new AuthService();
You can later access it in any Vue component. For example:
this.$authService.Login();
Refer: https://vuejs.org/v2/cookbook/adding-instance-properties.html
Edit: You have to use this.$router.push and this.$authService.register inside the isAuthenticated callback. If "this" refers to something else in that block, store var self=this; before the callback starts, or use fat arrow syntax.
<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>
Edit 2:
Maybe you can create the instance (singleton) itself in a file called AuthServiceInst.js. Then you can import it in both main.js and router.js.
New file 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
这篇关于在 Vue 应用程序中创建类的单个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!