問題描述
前台在的菜單,需要向後台進行請求,但是這樣就造成每次點擊一個菜單都會重新請求,造成菜單會出現短暫閃爍的情況,所以考慮使用service的單例模式來解決這個問題。
service 單例模式
在angularjs中,service默認都是單例的,但是在angular中,取消了這種默認。雖然我們説單例模式是好的,但是很多時候我們真的需要service是單例的嗎?
比如我們經常使用的表格,大部分情況下,我們只是需要將信息展示出來,並不需要使用service對其進行緩存,因為它不會被別的模塊所使用。
那麼,在angular中如何使service為單例的呢?
實現
其實,在angular6之前,如何我們想聲明一個service供全局使用,是這樣設置的:
服務:
export class TestService { }
根模塊:
@NgModule({
declarations: [...],
providers: [TestService],
bootstrap: [AppComponent]
})
export class AppModule {}
我們需要在@NgModule中去聲明providers,將service共全局使用,成為單例。
但是從angular6開始,單例模式又變成了一個首選方式。
所以,只要我們使用angular-cli的命令創建service的時候,就會默認創建如下部分:
@Injectable({
providedIn: 'root',
})
這時,就聲明該service在整個項目的模塊下是單例的了。
當然,此時使用原來在@NgModule中providers的方式也是可以的。
我的應用
我的目的是避免重複請求後台,所以基本思路就是在一次請求後台之後,將請求結果交給service保管,然後,然後下次請求就直接獲取service中的數據就可以了。
@Injectable({
providedIn: 'root',
})
export class MenuService {
private baseUrl = 'menu';
private currentMenuList: Array<Menu>; // 這裏存儲所有的菜單
constructor(private http: HttpClient) {
}
/**
* 請求後台,獲取所有菜單
*/
getAll() {
return this.http.get<Menu[]>(this.baseUrl);
}
/**
* 設置當前菜單列表
* @param menuList 菜單列表
*/
setMenuList(menuList: Array<Menu>) {
this.currentMenuList = menuList;
}
/**
* 獲取當前菜單列表
*/
getMenuList() {
return this.currentMenuList;
}
}
export class LeftControlComponent implements OnInit {
menuList: Menu[]; // 菜單
constructor(private userService: UserService,
private menuService: MenuService) {
}
ngOnInit() {
this.initMenu();
}
/**
* 初始化菜單
*/
initMenu() {
// 當前菜單為空的時候,重新請求菜單
if (!this.menuService.getMenuList() || this.menuService.getMenuList().length === 0) {
this.userService.getCurrentLoginUser()
.subscribe((data: User) => {
this.menuList = data.role.menuList;
// 將獲取的菜單交由service保存
this.menuService.setMenuList(this.menuList);
}, () => console.log('network error!'));
} else {
// 直接使用保存的菜單
this.menuList = this.menuService.getMenuList();
}
}
}
這樣,只用在登錄進行系統的時候獲取一次菜單,後面都不用進行向後台的請求了。閃爍的問題也就消失了。
相關參考:
https://segmentfault.com/a/11...
https://angular.cn/guide/sing...