我创建了一个简单的web(模具(组件AuthGuard
,不要与Angular的AuthGuard混淆。
该组件的目的是检查用户是否已登录。
- 如果是,则渲染插槽html
- 如果没有,则渲染"注册"按钮
组件代码如下:
import { Component, Host, h } from '@stencil/core';
import { Build, State } from '@stencil/core';
import { AuthService } from 'auth/auth.service';
import { ConfigService } from 'common/config.service';
@Component({
tag : 'auth-guard',
styleUrl : 'auth-guard.css',
shadow : true,
})
export class AuthGuard {
@State() canRender : boolean = false;
componentWillLoad() {
if (Build.isBrowser) {
const timerId = setInterval(() => {
if (AuthService.isInitialized) {
AuthService.vol$.subscribe(_u => {
this.canRender= true;
});
clearInterval(timerId);
}
}, ConfigService.loadTime);
}
}
render() {
console.log('auth guard :: render', this.canRender, AuthService.me);
return (
<Host>
{
this.canRender ? (
AuthService.me && AuthService.me.id.length > 0 ? (
<slot></slot>
) : (
<ion-button
href="/signup"
routerDirection="forward"
color="danger">
Signup
</ion-button>
)
): null
}
</Host>
);
}
}
现在在另一个文件中,我使用以下代码:
<auth-guard slot='end'>
<volunteer-mini volunteer={AuthService.me}></volunteer-mini>
</auth-guard>
有了这个,我期待的是
- 在
this.canRender
变为true之前,不进行任何渲染 - 一旦this.canRender变为true,如果AuthService.me有效,则呈现槽HTML
- 若AuthService.me为null,则呈现注册按钮
但是当this.cannder为false时,它试图将volunteer-mini
呈现为槽HTML,这是一个问题。由于volunteer-mini
内部依赖于尚未初始化的AuthService.me。
但一旦this.canRender
变为真,其他两种情况都可以正常工作。
通常,使用模板编写身份验证保护是个坏主意。核心问题是您的插槽在组件初始化之前就已经存在。
因此,使用您当前的代码,在您决定没有权限后,您必须手动删除插槽。
此外,如果您没有定义插槽位置,但仍在父对象中提供插槽内容,则该内容仍将附加到您的内部子对象。
为了解决这个问题,您可以将组件重构为一个函数,如<Host>
,但这还有其他需要考虑的问题。