Aurelia - Navmenu 不根据@computed 值更新
Aurelia - Navmenu not updating based on @computed value
我收到并回答了 THIS 我认为正确的问题,但是我没有得到传播回视图的值。我添加了一些 console.logs 并且它们没有被击中。
这是我的 navMenu - 如果它在本地存储中有值,我希望 "loggedIn" 为真...
<template bindable="router">
<require from="./navmenu.css"></require>
<div class="main-nav">
<div class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/home">Jobsledger.API</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li repeat.for="row of router.navigation" class="${ row.isActive ? 'link-active' : '' }">
<a href.bind="row.href" if.bind="loggedIn">${ row.title }</a>
<a href.bind="row.href" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"
if.bind="loggedIn">
${row.title}
<span class="caret"></span>
</a>
<ul if.bind="loggedIn" class="dropdown-menu">
<li repeat.for="menu of row.settings.nav">
<a href.bind="menu.href">${menu.title}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
test ${loggedIn}
</template>
这是显示@computedFrom 和getter:
的navmenu.ts 视图模型
import { autoinject, inject, NewInstance } from "aurelia-framework";
import { computedFrom } from "aurelia-binding";
import { bindable } from "aurelia-templating";
import { LoggedInService } from "../components/auth/LoggedInService";
@autoinject
export class Navmenu {
constructor(private testAuthentication: LoggedInService) {
console.log("loggedin value: ", this.testAuthentication.isAuthenticated())
}
@computedFrom('testAuthentication.authenticated')
get loggedIn() {
console.log("loggedin value: ", this.testAuthentication.isAuthenticated())
return this.testAuthentication.isAuthenticated()
}
}
这是我的登录 class - 非常简单 - 关闭并在本地存储中获取一个值 - 如果它不存在它 returns false。
export class LoggedInService {
private LOGGED_IN = "loggedIn";
constructor() {}
isAuthenticated(): boolean {
var authenticated = localStorage.getItem(this.LOGGED_IN);
console.log("LOGGEDIN - typeof: ", authenticated);
if (authenticated != null) {
return true;
} else return false;
}
}
我的 console.logs 的 None 显示在控制台中,这意味着 none 的这些功能正在被击中。我不知道为什么..应该很简单..
有人可以查看一下并告诉我为什么它仍然无法正常工作吗?
更新
感谢 Jeremy 看一看,我已经着手实施了。这是我更新的 classes.
我已经更改了 classes 上的名称,但它们代表了 Jeremy 的建议。在这里,它们的顺序与他展示它们的顺序相同...
这是他的 "user.ts" 我的版本:
export class LoggedInService {
private LOGGED_IN = "loggedIn";
isLoggedIn: boolean = false;
userName: string = 'anonymous';
constructor() { }
isAuthenticated(): boolean {
var authenticated = localStorage.getItem(this.LOGGED_IN);
console.log("LOGGEDIN value HERE!: ", authenticated);
if (authenticated != null) {
return true;
} else {
return false;
}
}
}
我将 "isLoggedIn" 设置为 'false' 并将 "username" 设置为 'anonymous'。
这是我的 "navmenu.ts" 版本:
import { autoinject } from "aurelia-framework";
import { bindable } from "aurelia-templating";
import { LoggedInService } from "../components/auth/LoggedInService";
@autoinject
export class Navmenu {
constructor(public loggedInService: LoggedInService) { }
}
我假设这应该给我的 navmenu.html - 视图 - 访问这些值,在这里我不确定在 if.bind 中应该如何访问它们。我只是想使用以下方法对其进行测试:
<div if.bind="loggedInService.isLoggedIn">
working
</div>
这没用。
最后是我的 auth_service.ts 版本。这是进行提取以登录的地方 - 我在提取中设置了 loggedIn 和用户名的值:
constructor(
private login: userLogin,
private loggedinService: LoggedInService,
private tokenService: TokenService,
private userService: UserService,
private router: Router,
private http: HttpClient,
private controllerFactory: ValidationControllerFactory
) {
this.router = router;
this.controller = controllerFactory.createForCurrentScope();
this.controller.addRenderer(new BootstrapFormRenderer());
// Check if user is logged in
if (this.loggedinService.isAuthenticated()) {
loggedinService.isLoggedIn = true;
loggedinService.userName = this.userService.getUserName();
}
}
submitLogin() {
if (this.controller.validate()) {
// Lets do a fetch!
this.login.Username = this.username;
this.login.Password = this.password;
const task = fetch("/api/jwt", {
method: "POST",
body: JSON.stringify(this.login),
headers: new Headers({ 'content-type': 'application/json' })
})
.then(response => response.json())
.then(data => {
// First save the JWT and as well save it to loggedInService.
this.loggedinService.isLoggedIn = this.tokenService.saveJWT(data);
// Next go back to the api and get the username and save that to loggedInService also.
this.loggedinService.userName = this.userService.saveUserName();
// Finally redirect to home page.
this.router.navigate("home");
})
.catch(error => {
this.tokenService.clearJWT();
});
}
}
我仍然没有在导航菜单视图中看到任何类型的 activity.. 不确定我是否设置了这个 ok 想知道是否有人可以再看看这个.. 也许我没有在导航栏视图。我注意到 loggedInService 在导航菜单和 login.ts 视图模型中都是依赖项。这不应该工作还是搞砸了....
您可以对此进行稍微不同的建模,并避免所有脏检查和 computedFrom 内容。
为您当前的用户创建模型:
user.ts
export class User {
isLoggedIn = false;
name = 'anonymous';
}
然后在需要访问 isLoggedIn
状态或用户详细信息的视图模型中依赖于用户:
navmenu.ts
@autoinject
export class Navmenu {
constructor(public user: User) { }
}
执行登录工作或本地存储工作的服务也依赖于当前用户,在登录状态更改时更新其属性。
auth-service.ts
@autoinject
export class AuthService {
constructor(private user: User) {
if (... check local storage, etc ... ) {
user.isLoggedIn = true;
user.name = ....
}
}
login(username, password) {
return fetch('/api/login', { method: 'POST', body: { ... } })
.then(result => {
...
...
this.user.isLoggedIn = true;
this.user.name = username;
...
});
}
}
这可能是因为您根本没有使用视图模型。尝试检查您是否引用了模块 navmenu 视图模型或其视图 navmenu.html
我收到并回答了 THIS 我认为正确的问题,但是我没有得到传播回视图的值。我添加了一些 console.logs 并且它们没有被击中。
这是我的 navMenu - 如果它在本地存储中有值,我希望 "loggedIn" 为真...
<template bindable="router">
<require from="./navmenu.css"></require>
<div class="main-nav">
<div class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#/home">Jobsledger.API</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li repeat.for="row of router.navigation" class="${ row.isActive ? 'link-active' : '' }">
<a href.bind="row.href" if.bind="loggedIn">${ row.title }</a>
<a href.bind="row.href" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"
if.bind="loggedIn">
${row.title}
<span class="caret"></span>
</a>
<ul if.bind="loggedIn" class="dropdown-menu">
<li repeat.for="menu of row.settings.nav">
<a href.bind="menu.href">${menu.title}</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
test ${loggedIn}
</template>
这是显示@computedFrom 和getter:
的navmenu.ts 视图模型 import { autoinject, inject, NewInstance } from "aurelia-framework";
import { computedFrom } from "aurelia-binding";
import { bindable } from "aurelia-templating";
import { LoggedInService } from "../components/auth/LoggedInService";
@autoinject
export class Navmenu {
constructor(private testAuthentication: LoggedInService) {
console.log("loggedin value: ", this.testAuthentication.isAuthenticated())
}
@computedFrom('testAuthentication.authenticated')
get loggedIn() {
console.log("loggedin value: ", this.testAuthentication.isAuthenticated())
return this.testAuthentication.isAuthenticated()
}
}
这是我的登录 class - 非常简单 - 关闭并在本地存储中获取一个值 - 如果它不存在它 returns false。
export class LoggedInService {
private LOGGED_IN = "loggedIn";
constructor() {}
isAuthenticated(): boolean {
var authenticated = localStorage.getItem(this.LOGGED_IN);
console.log("LOGGEDIN - typeof: ", authenticated);
if (authenticated != null) {
return true;
} else return false;
}
}
我的 console.logs 的 None 显示在控制台中,这意味着 none 的这些功能正在被击中。我不知道为什么..应该很简单..
有人可以查看一下并告诉我为什么它仍然无法正常工作吗?
更新
感谢 Jeremy 看一看,我已经着手实施了。这是我更新的 classes.
我已经更改了 classes 上的名称,但它们代表了 Jeremy 的建议。在这里,它们的顺序与他展示它们的顺序相同...
这是他的 "user.ts" 我的版本:
export class LoggedInService {
private LOGGED_IN = "loggedIn";
isLoggedIn: boolean = false;
userName: string = 'anonymous';
constructor() { }
isAuthenticated(): boolean {
var authenticated = localStorage.getItem(this.LOGGED_IN);
console.log("LOGGEDIN value HERE!: ", authenticated);
if (authenticated != null) {
return true;
} else {
return false;
}
}
}
我将 "isLoggedIn" 设置为 'false' 并将 "username" 设置为 'anonymous'。
这是我的 "navmenu.ts" 版本:
import { autoinject } from "aurelia-framework";
import { bindable } from "aurelia-templating";
import { LoggedInService } from "../components/auth/LoggedInService";
@autoinject
export class Navmenu {
constructor(public loggedInService: LoggedInService) { }
}
我假设这应该给我的 navmenu.html - 视图 - 访问这些值,在这里我不确定在 if.bind 中应该如何访问它们。我只是想使用以下方法对其进行测试:
<div if.bind="loggedInService.isLoggedIn">
working
</div>
这没用。
最后是我的 auth_service.ts 版本。这是进行提取以登录的地方 - 我在提取中设置了 loggedIn 和用户名的值:
constructor(
private login: userLogin,
private loggedinService: LoggedInService,
private tokenService: TokenService,
private userService: UserService,
private router: Router,
private http: HttpClient,
private controllerFactory: ValidationControllerFactory
) {
this.router = router;
this.controller = controllerFactory.createForCurrentScope();
this.controller.addRenderer(new BootstrapFormRenderer());
// Check if user is logged in
if (this.loggedinService.isAuthenticated()) {
loggedinService.isLoggedIn = true;
loggedinService.userName = this.userService.getUserName();
}
}
submitLogin() {
if (this.controller.validate()) {
// Lets do a fetch!
this.login.Username = this.username;
this.login.Password = this.password;
const task = fetch("/api/jwt", {
method: "POST",
body: JSON.stringify(this.login),
headers: new Headers({ 'content-type': 'application/json' })
})
.then(response => response.json())
.then(data => {
// First save the JWT and as well save it to loggedInService.
this.loggedinService.isLoggedIn = this.tokenService.saveJWT(data);
// Next go back to the api and get the username and save that to loggedInService also.
this.loggedinService.userName = this.userService.saveUserName();
// Finally redirect to home page.
this.router.navigate("home");
})
.catch(error => {
this.tokenService.clearJWT();
});
}
}
我仍然没有在导航菜单视图中看到任何类型的 activity.. 不确定我是否设置了这个 ok 想知道是否有人可以再看看这个.. 也许我没有在导航栏视图。我注意到 loggedInService 在导航菜单和 login.ts 视图模型中都是依赖项。这不应该工作还是搞砸了....
您可以对此进行稍微不同的建模,并避免所有脏检查和 computedFrom 内容。
为您当前的用户创建模型:
user.ts
export class User {
isLoggedIn = false;
name = 'anonymous';
}
然后在需要访问 isLoggedIn
状态或用户详细信息的视图模型中依赖于用户:
navmenu.ts
@autoinject
export class Navmenu {
constructor(public user: User) { }
}
执行登录工作或本地存储工作的服务也依赖于当前用户,在登录状态更改时更新其属性。
auth-service.ts
@autoinject
export class AuthService {
constructor(private user: User) {
if (... check local storage, etc ... ) {
user.isLoggedIn = true;
user.name = ....
}
}
login(username, password) {
return fetch('/api/login', { method: 'POST', body: { ... } })
.then(result => {
...
...
this.user.isLoggedIn = true;
this.user.name = username;
...
});
}
}
这可能是因为您根本没有使用视图模型。尝试检查您是否引用了模块 navmenu 视图模型或其视图 navmenu.html