在 Angular 套版時應注意多層次選單超連結的使用
我們許多專案,都會有網頁設計師設計版型,然後再交由前端工程師套版。不過有很多版型,都會留有<a href="#"></a>
這樣的空連結,比較常見的用途都是在「多層次選單」的上層連結。但這樣的連結,在套用至多頁面路由的 SPA 應用程式中時,就會出現問題。由於 SPA 網頁在設計的時候,都會套用<base href="...">
元素,設定網頁中所有連結的基礎位址 (Base URL),當使用者點選<a href="#">
這樣的連結時,就會導致網頁重新整理!本篇文章將解說幾個可能的解決方案。
避免觸發超連結事件的幾種做法
我們一般比較常見的寫法有幾種:
-
直接使用
#
當作超連結這種技巧對於靜態版型還可行,許多網頁設計師也很習慣這樣寫,但是當使用者點選連結後,卻會在目前網址後方加上一個
#
符號。一來,我個人相當不喜歡這種作法,因為網址會發生改變;二來,這種寫法會讓 SPA (單一頁面應用程式) 的路由發生異常,所以應該避免。 -
使用特殊的
javascript:void(0)
當作超連結這種寫法通常是前端工程師以及對 UX 特別要求的設計師愛用,原因無他,就是網址列不會出現怪怪的
#
符號。這種寫法同時也對 SPA 網頁應用程式相當友善,所以推薦使用。但唯一的缺點,就是比#
多打太多字了! -
使用特殊的
javascript:;
當作超連結這種寫法跟
javascript:void(0)
如出一轍,但硬是少打了 6 個字元,如果學會他,你這輩子可能有機會打超過 1000 次這種連結,就可以少打 6000 個按鍵,不無小補啦。
透過 Angular 自訂指令元件 (Directive) 實現
身為前端工程師,在 JavaScript 可以控制到的地方,幾乎沒有不可能的事。所以我們當然可以透過 Angular 自訂 Directive 來將許多版型常見的<a href="#">
連結,自動修復成沒有問題的連結,好讓設計師們不用改變長久以來的設計習慣,繼續使用#
當成預設超連結。
你可以先建立一個a.directive.ts
檔案,放在/src/app/
目錄下:
import { Directive, HostListener } from '@angular/core'; @Directive({ selector: 'a[href="#"]' }) export class ADirective { @HostListener('click', ['$event']) onClick(e) { e.preventDefault(); } }
接著,再到AppModule
模組中,將上述ADirective
元件類別加入到@NgModule
裝飾器的declarations
屬性中,如下範例:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { HelloComponent } from './hello.component'; import { ADirective } from './a.directive'; @NgModule({ ... declarations: [AppComponent, HelloComponent, ADirective], bootstrap: [AppComponent] ... }) export class AppModule { }
就這樣簡單兩個步驟,即可讓你所有的 Angular 元件樣板,不用再害怕出現有#
超連結的情況。
相關連結
- ofollow,noindex" target="_blank">本文章的完整範例專案 (可線上測試執行)
- Angular - Attribute Directives
- Angular - HostListener
- HostListener/HostBinding decorators versus host metadata