新增導覽和路由 navigation-routing

IMPORTANT
新專案中已棄用 SPA 編輯器。Adobe 仍支援現有專案使用此編輯器,但不應用於新專案。目前,AEM 中用於管理 Headless 內容的首選編輯器為:

瞭解如何使用AEM頁面和SPA Editor SDK支援SPA中的多個檢視。 動態導覽是使用Angular路由實作,並新增到現有的頁首元件。

目標

  1. 瞭解使用SPA編輯器時可用的SPA模型路由選項。
  2. 瞭解如何使用Angular路由在SPA的不同檢視之間導覽。
  3. 實作由AEM頁面階層驅動的動態導覽。

您將要建置的內容

本章將導覽功能表新增至現有的Header元件。 導覽功能表是由AEM頁面階層所驅動,並使用導覽核心元件提供的JSON模型。

已實作導覽

先決條件

檢閱設定本機開發環境所需的工具與指示。

取得程式碼

  1. 透過Git下載本教學課程的起點:

    code language-shell
    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/navigation-routing-start
    
  2. 使用Maven將程式碼庫部署到本機AEM執行個體:

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage
    

    如果使用AEM 6.x,請新增classic設定檔:

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. 安裝傳統WKND參考站台的完成套件。 由WKND參考網站提供的影像會在WKND SPA上重複使用。 可以使用AEM的封裝管理員來安裝封裝。

    封裝管理員安裝wknd.all

您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/navigation-routing-solution在本機取出程式碼。

檢查HeaderComponent更新 inspect-header

在先前的章節中,HeaderComponent元件已新增為透過app.component.html包含的純Angular元件。 在本章中,HeaderComponent元件已從應用程式移除,並透過範本編輯器新增。 這可讓使用者從AEM中設定HeaderComponent的導覽功能表。

NOTE
程式碼庫已進行數個CSS和JavaScript更新,以便開始本章的編寫。 為了專注於核心概念,不會討論​ 所有 ​的程式碼變更。 您可以在這裡檢視完整變更。
  1. 在您選擇的IDE中,開啟本章的SPA入門專案。

  2. ui.frontend模組下方,於ui.frontend/src/app/components/header/header.component.ts檢查檔案header.component.ts

    已進行數個更新,包括新增HeaderEditConfigMapTo,以便讓元件對應至AEM元件wknd-spa-angular/components/header

    code language-js
    /* header.component.ts */
    ...
    const HeaderEditConfig = {
        ...
    };
    
    @Component({
    selector: 'app-header',
    templateUrl: './header.component.html',
    styleUrls: ['./header.component.scss']
    })
    export class HeaderComponent implements OnInit {
    @Input() items: object[];
        ...
    }
    ...
    MapTo('wknd-spa-angular/components/header')(withRouter(Header), HeaderEditConfig);
    

    記下items@Input()註解。 items將包含從AEM傳入的導覽物件陣列。

  3. ui.apps模組中檢查AEM Header元件的元件定義: ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/header/.content.xml

    code language-xml
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
        xmlns:jcr="http://www.jcp.org/jcr/1.0"
        jcr:primaryType="cq:Component"
        jcr:title="Header"
        sling:resourceSuperType="wknd-spa-angular/components/navigation"
        componentGroup="WKND SPA Angular - Structure"/>
    

    AEM Header元件將透過sling:resourceSuperType屬性繼承導覽核心元件的所有功能。

將HeaderComponent新增至SPA範本 add-header-template

  1. 開啟瀏覽器並登入AEM,http://localhost:4502/。 起始程式碼基底應該已經部署。

  2. 導覽至​SPA頁面範本http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html

  3. 選取最外層的​根配置容器,然後按一下它的​ 原則 ​圖示。 請注意,not​選取​ 配置容器 ​已解除製作鎖定。

    選取根配置容器原則圖示

  4. 複製目前的原則並建立名為​ SPA結構 ​的新原則:

    SPA結構原則

    在​允許的元件 > 一般 >下,選取​ 配置容器 ​元件。

    在​允許的元件 > WKND SPA ANGULAR — 結構 >選取​ 標題 ​元件下:

    選取標頭元件

    在​允許的元件 > WKND SPA ANGULAR - Content >選取​ 影像 ​和​ 文字 ​元件。 您總共應選取4個元件。

    按一下「完成」以儲存變更。

  5. 重新整理​頁面。 在解除鎖定的​ 配置容器 ​上方新增​ Header ​元件:

    新增Header元件至範本

  6. 選取​ Header ​元件,然後按一下其​ 原則 ​圖示以編輯原則。

    按一下標頭原則

  7. 使用​ "WKND SPA標頭" ​的​ 原則標題 ​建立新原則。

    在​ 屬性 ​下:

    • 將​ 導覽根目錄 ​設定為/content/wknd-spa-angular/us/en
    • 將「排除根層級」設定為「1」。
    • 取消勾選​收集所有子頁面
    • 將「導覽結構深度」設定為「3」。

    設定標頭原則

    這會收集位於/content/wknd-spa-angular/us/en下方的導覽2層級。

  8. 儲存變更後,您應該會看到填入的Header成為範本的一部分:

    已填入標頭元件

建立子頁面

接下來,在AEM中建立其他頁面,這些頁面將用作SPA中的不同檢視。 我們也會檢查AEM所提供JSON模型的階層結構。

  1. 導覽至​ 網站 ​主控台: http://localhost:4502/sites.html/content/wknd-spa-angular/us/en/home。 選取​WKND SPA Angular首頁,然後按一下​建立 > 頁面

    建立新頁面

  2. 在​ 範本 ​下,選取​SPA頁面。 在「屬性」下,輸入​ Title ​的​ "Page 1" ​和​ "page-1" ​作為名稱。

    輸入初始頁面屬性

    按一下「建立」,然後在對話方塊快顯視窗中按一下「開啟」,在AEM SPA編輯器中開啟頁面。

  3. 將新的​ Text ​元件新增至主要​配置容器。 編輯元件並輸入文字: 「Page 1」 (使用RTE和​ H1 ​元素) (您必須進入全熒幕模式才能變更段落元素)

    範例內容頁面1

    您可以隨意新增其他內容,例如影像。

  4. 返回AEM Sites主控台並重複上述步驟,建立名為​ 「第2頁」 ​的第二個頁面作為​ 第1 ​頁的同層級。 將內容新增至​ 第2 ​頁,以便輕鬆識別。

  5. 最後建立第三個頁面,「第3頁」,但做為​ 第2 ​頁的​子項。 完成後,網站階層應如下所示:

    範例網站階層

  6. 在新標籤中,開啟AEM提供的JSON模型API: http://localhost:4502/content/wknd-spa-angular/us/en.model.json。 SPA首次載入時會請求此JSON內容。 外部結構如下所示:

    code language-json
    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {},
        "/content/wknd-spa-angular/us/en/home/page-2/page-3": {}
        }
    }
    

    :children底下,您應該會看到每個已建立頁面的專案。 所有頁面的內容都在此初始JSON請求中。 一旦導覽路由實作後,SPA的後續檢視就會快速載入,因為內容在使用者端已可供使用。

    在初始JSON要求中載入SPA的​ 所有 ​內容是不明智的,因為這會減慢初始頁面載入的速度。 接下來,讓我們看看如何收集頁面的階層式深度。

  7. 導覽至​ SPA Root ​範本,位於: http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-app-template/structure.html

    按一下​頁面屬性功能表 > 頁面原則

    開啟SPA根目錄的頁面原則

  8. SPA Root​範本有一個額外的​ 階層結構 ​標籤,可控制所收集的JSON內容。 結構深度​決定網站階層中要多深才能收集​ root ​下的子頁面。 您也可以使用​ 結構模式 ​欄位,根據規則運算式篩選出其他頁面。

    將​ 結構深度 ​更新為​"2"

    更新結構深度

    按一下​ 完成 ​儲存原則的變更。

  9. 重新開啟JSON模型http://localhost:4502/content/wknd-spa-angular/us/en.model.json

    code language-json
    {
    "language": "en",
    "title": "en",
    "templateName": "spa-app-template",
    "designPath": "/libs/settings/wcm/designs/default",
    "cssClassNames": "spa page basicpage",
    ":type": "wknd-spa-angular/components/spa",
    ":items": {},
    ":itemsOrder": [],
    ":hierarchyType": "page",
    ":path": "/content/wknd-spa-angular/us/en",
    ":children": {
        "/content/wknd-spa-angular/us/en/home": {},
        "/content/wknd-spa-angular/us/en/home/page-1": {},
        "/content/wknd-spa-angular/us/en/home/page-2": {}
        }
    }
    

    請注意,頁面3​路徑已從初始JSON模型中移除: /content/wknd-spa-angular/us/en/home/page-2/page-3

    稍後,我們將觀察AEM SPA Editor SDK如何以動態方式載入其他內容。

Implement the navigation

Next, implement the navigation menu with a new NavigationComponent. We could add the code directly in header.component.html but a better practice is to avoid large components. Instead, implement a NavigationComponent that could potentially be re-used later.

  1. Review the JSON exposed by the AEM Header component at http://localhost:4502/content/wknd-spa-angular/us/en.model.json:

    code language-json
    ...
    "header": {
        "items": [
        {
        "level": 0,
        "active": true,
        "path": "/content/wknd-spa-angular/us/en/home",
        "description": null,
        "url": "/content/wknd-spa-angular/us/en/home.html",
        "lastModified": 1589062597083,
        "title": "WKND SPA Angular Home Page",
        "children": [
                {
                "children": [],
                "level": 1,
                "active": false,
                "path": "/content/wknd-spa-angular/us/en/home/page-1",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-1.html",
                "lastModified": 1589429385100,
                "title": "Page 1"
                },
                {
                "level": 1,
                "active": true,
                "path": "/content/wknd-spa-angular/us/en/home/page-2",
                "description": null,
                "url": "/content/wknd-spa-angular/us/en/home/page-2.html",
                "lastModified": 1589429603507,
                "title": "Page 2",
                "children": [
                    {
                    "children": [],
                    "level": 2,
                    "active": false,
                    "path": "/content/wknd-spa-angular/us/en/home/page-2/page-3",
                    "description": null,
                    "url": "/content/wknd-spa-angular/us/en/home/page-2/page-3.html",
                    "lastModified": 1589430413831,
                    "title": "Page 3"
                    }
                ],
                }
            ]
            }
        ],
    ":type": "wknd-spa-angular/components/header"
    

    The hierarchical nature of the AEM pages are modeled in the JSON that can be used to populate a navigation menu. Recall that the Header component inherits all of the functionality of the Navigation Core Component and the content exposed through the JSON is automatically mapped to the Angular @Input annotation.

  2. Open a new terminal window and navigate to the ui.frontend folder of the SPA project. Create a new NavigationComponent using the Angular CLI tool:

    code language-shell
    $ cd ui.frontend
    $ ng generate component components/navigation
    CREATE src/app/components/navigation/navigation.component.scss (0 bytes)
    CREATE src/app/components/navigation/navigation.component.html (25 bytes)
    CREATE src/app/components/navigation/navigation.component.spec.ts (656 bytes)
    CREATE src/app/components/navigation/navigation.component.ts (286 bytes)
    UPDATE src/app/app.module.ts (2032 bytes)
    
  3. Next create a class named NavigationLink using the Angular CLI in the newly created components/navigation directory:

    code language-shell
    $ cd src/app/components/navigation/
    $ ng generate class NavigationLink
    CREATE src/app/components/navigation/navigation-link.spec.ts (187 bytes)
    CREATE src/app/components/navigation/navigation-link.ts (32 bytes)
    
  4. Return to the IDE of your choice and open the file at navigation-link.ts at /src/app/components/navigation/navigation-link.ts.

    Open navigation-link.ts file

  5. 以下列專案填入navigation-link.ts

    code language-js
    export class NavigationLink {
    
        title: string;
        path: string;
        url: string;
        level: number;
        children: NavigationLink[];
        active: boolean;
    
        constructor(data) {
            this.path = data.path;
            this.title = data.title;
            this.url = data.url;
            this.level = data.level;
            this.active = data.active;
            this.children = data.children.map( item => {
                return new NavigationLink(item);
            });
        }
    }
    

    This is a simple class to represent an individual navigation link. In the class constructor we expect data to be the JSON object passed in from AEM. This class is used within both the NavigationComponent and HeaderComponent to easily populate the navigation structure.

    No data transformation is performed, this class is primarily created to strongly type the JSON model. Notice that this.children is typed as NavigationLink[] and that the constructor recursively creates new NavigationLink objects for each of the items in the children array. Recall that JSON model for the Header is hierarchical.

  6. 開啟檔案 navigation-link.spec.ts。 This is the test file for the NavigationLink class. Update it with the following:

    code language-js
    import { NavigationLink } from './navigation-link';
    
    describe('NavigationLink', () => {
        it('should create an instance', () => {
            const data = {
                children: [],
                level: 1,
                active: false,
                path: '/content/wknd-spa-angular/us/en/home/page-1',
                description: null,
                url: '/content/wknd-spa-angular/us/en/home/page-1.html',
                lastModified: 1589429385100,
                title: 'Page 1'
            };
            expect(new NavigationLink(data)).toBeTruthy();
        });
    });
    

    Notice that const data follows the same JSON model inspected earlier for a single link. This is far from a robust unit test, however it should suffice to test the constructor of NavigationLink.

  7. 開啟檔案 navigation.component.ts。 Update it with the following:

    code language-js
    import { Component, OnInit, Input } from '@angular/core';
    import { NavigationLink } from './navigation-link';
    
    @Component({
    selector: 'app-navigation',
    templateUrl: './navigation.component.html',
    styleUrls: ['./navigation.component.scss']
    })
    export class NavigationComponent implements OnInit {
    
        @Input() items: object[];
    
        constructor() { }
    
        get navigationLinks(): NavigationLink[] {
    
            if (this.items && this.items.length > 0) {
                return this.items.map(item => {
                    return new NavigationLink(item);
                });
            }
    
            return null;
        }
    
        ngOnInit() {}
    
    }
    

    NavigationComponent expects an object[] named items that is the JSON model from AEM. 此類別公開單一方法get navigationLinks(),它傳回NavigationLink物件的陣列。

  8. 開啟檔案navigation.component.html,並以下列專案更新它:

    code language-html
    <ul *ngIf="navigationLinks && navigationLinks.length > 0" class="navigation__group">
        <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: navigationLinks }"></ng-container>
    </ul>
    

    這會產生初始<ul>,並從navigation.component.ts呼叫get navigationLinks()方法。 <ng-container>用來呼叫名為recursiveListTmpl的範本,並將navigationLinks傳遞為名為links的變數。

    接著新增recursiveListTmpl

    code language-html
    <ng-template #recursiveListTmpl let-links="links">
        <li *ngFor="let link of links" class="{{'navigation__item navigation__item--' + link.level}}">
            <a [routerLink]="link.url" class="navigation__item-link" [title]="link.title" [attr.aria-current]="link.active">
                {{link.title}}
            </a>
            <ul *ngIf="link.children && link.children.length > 0">
                <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ links: link.children }"></ng-container>
            </ul>
        </li>
    </ng-template>
    

    接著會實作導覽連結的其餘轉譯。 請注意,變數link的型別為NavigationLink,且此類別建立的所有方法/屬性都可供使用。 已使用[routerLink],而非一般的href屬性。 這可讓我們連結至應用程式中的特定路由,不需要重新整理整頁。

    如果目前的link具有非空白的children陣列,則導覽的遞回部分也會透過建立另一個<ul>來實作。

  9. 更新navigation.component.spec.ts以新增RouterTestingModule的支援:

    code language-diff
     ...
    + import { RouterTestingModule } from '@angular/router/testing';
     ...
     beforeEach(async(() => {
        TestBed.configureTestingModule({
    +   imports: [ RouterTestingModule ],
        declarations: [ NavigationComponent ]
        })
        .compileComponents();
     }));
     ...
    

    需要新增RouterTestingModule,因為元件使用[routerLink]

  10. 更新navigation.component.scss以新增一些基本樣式至NavigationComponent

@import "~src/styles/variables";

$link-color: $black;
$link-hover-color: $white;
$link-background: $black;

:host-context {
    display: block;
    width: 100%;
}

.navigation__item {
    list-style: none;
}

.navigation__item-link {
    color: $link-color;
    font-size: $font-size-large;
    text-transform: uppercase;
    padding: $gutter-padding;
    display: flex;
    border-bottom: 1px solid $gray;

    &:hover {
        background: $link-background;
        color: $link-hover-color;
    }

}

更新標題元件

現在NavigationComponent已實作,必須更新HeaderComponent以參考它。

  1. 開啟終端機,並導覽至SPA專案中的ui.frontend資料夾。 啟動​webpack開發伺服器

    code language-shell
    $ npm start
    
  2. 開啟瀏覽器索引標籤並導覽至http://localhost:4200/

    webpack開發伺服器​應該設定為從AEM (ui.frontend/proxy.conf.json)的本機執行個體代理JSON模型。 這可讓我們直接針對教學課程中先前在AEM中建立的內容進行編碼。

    功能表切換正在運作

    HeaderComponent目前已經實作功能表切換功能。 接著,新增導覽元件。

  3. 返回您選擇的IDE,並在ui.frontend/src/app/components/header/header.component.ts開啟檔案header.component.ts

  4. 更新setHomePage()方法以移除硬式編碼字串並使用AEM元件傳入的動態prop:

    code language-js
    /* header.component.ts */
    import { NavigationLink } from '../navigation/navigation-link';
    ...
     setHomePage() {
        if (this.hasNavigation) {
            const rootNavigationLink: NavigationLink = new NavigationLink(this.items[0]);
            this.isHome = rootNavigationLink.path === this.route.snapshot.data.path;
            this.homePageUrl = rootNavigationLink.url;
        }
    }
    ...
    

    NavigationLink的新執行個體是根據items[0]建立的,這是從AEM傳入的導覽JSON模型的根目錄。 this.route.snapshot.data.path會傳回目前Angular路由的路徑。 此值用於判斷目前的路由是否為​首頁this.homePageUrl是用來填入​ 標誌 ​上的錨點連結。

  5. 開啟header.component.html並將導覽的靜態預留位置取代為新建立的NavigationComponent的參考:

    code language-diff
        <div class="header-navigation">
            <div class="navigation">
    -            Navigation Placeholder
    +           <app-navigation [items]="items"></app-navigation>
            </div>
        </div>
    

    [items]=items屬性會將@Input() itemsHeaderComponent傳遞至NavigationComponent,以建立導覽。

  6. 開啟header.component.spec.ts並為NavigationComponent新增宣告:

    code language-diff
        /* header.component.spect.ts */
    +   import { NavigationComponent } from '../navigation/navigation.component';
    
        describe('HeaderComponent', () => {
        let component: HeaderComponent;
        let fixture: ComponentFixture<HeaderComponent>;
    
        beforeEach(async(() => {
            TestBed.configureTestingModule({
            imports: [ RouterTestingModule ],
    +       declarations: [ HeaderComponent, NavigationComponent ]
            })
            .compileComponents();
        }));
    

    由於NavigationComponent現在已用作HeaderComponent的一部分,因此需要將其宣告為測試平台的一部分。

  7. 儲存任何開啟檔案的變更並返回​webpack開發伺服器http://localhost:4200/

    已完成頁首導覽

    按一下功能表切換即可開啟導覽,且您應會看到已填入的導覽連結。 您應該能夠導覽至SPA的不同檢視。

瞭解SPA路由

現在導覽已實施,請在AEM中檢查路由。

  1. 在IDE中,在ui.frontend/src/app開啟檔案app-routing.module.ts

    code language-js
    /* app-routing.module.ts */
    import { AemPageDataResolver, AemPageRouteReuseStrategy } from '@adobe/cq-angular-editable-components';
    import { NgModule } from '@angular/core';
    import { RouteReuseStrategy, RouterModule, Routes, UrlMatchResult, UrlSegment } from '@angular/router';
    import { PageComponent } from './components/page/page.component';
    
    export function AemPageMatcher(url: UrlSegment[]): UrlMatchResult {
        if (url.length) {
            return {
                consumed: url,
                posParams: {
                    path: url[url.length - 1]
                }
            };
        }
    }
    
    const routes: Routes = [
        {
            matcher: AemPageMatcher,
            component: PageComponent,
            resolve: {
                path: AemPageDataResolver
            }
        }
    ];
    @NgModule({
        imports: [RouterModule.forRoot(routes)],
        exports: [RouterModule],
        providers: [
            AemPageDataResolver,
            {
            provide: RouteReuseStrategy,
            useClass: AemPageRouteReuseStrategy
            }
        ]
    })
    export class AppRoutingModule {}
    

    routes: Routes = [];陣列定義Angular元件對應的路由或導覽路徑。

    AemPageMatcher是自訂Angular路由器UrlMatcher,符合此Angular應用程式中AEM任何「看起來」頁面的內容。

    PageComponent是Angular元件,代表AEM中的頁面,用來呈現相符的路由。 在稍後的教學課程中會檢閱PageComponent

    AemPageDataResolver由AEM SPA Editor JS SDK提供,是自訂Angular路由器解析器,用來將路由URL (AEM中包含.html副檔名的路徑)轉換為AEM中的資源路徑(不含副檔名的頁面路徑)。

    例如,AemPageDataResolver會將路由的URL content/wknd-spa-angular/us/en/home.html轉換為/content/wknd-spa-angular/us/en/home的路徑。 用於根據JSON模型API中的路徑解析頁面內容。

    由AEM SPA Editor JS SDK提供的AemPageRouteReuseStrategy是自訂RouteReuseStrategy,可防止跨路由重複使用PageComponent。 否則,頁面「A」中的內容可能會在導覽至頁面「B」時顯示。

  2. ui.frontend/src/app/components/page/開啟檔案page.component.ts

    code language-js
    ...
    export class PageComponent {
        items;
        itemsOrder;
        path;
    
        constructor(
            private route: ActivatedRoute,
            private modelManagerService: ModelManagerService
        ) {
            this.modelManagerService
            .getData({ path: this.route.snapshot.data.path })
            .then(data => {
                this.path = data[Constants.PATH_PROP];
                this.items = data[Constants.ITEMS_PROP];
                this.itemsOrder = data[Constants.ITEMS_ORDER_PROP];
            });
        }
    }
    

    PageComponent是處理從AEM擷取的JSON所必需,並當作Angular元件來轉譯路由。

    由Angular路由器模組提供的ActivatedRoute包含指出哪個AEM頁面的JSON內容應載入此Angular頁面元件執行個體的狀態。

    ModelManagerService,根據路由取得JSON資料,並將資料對應到類別變數pathitemsitemsOrder。 然後這些資料將傳遞至AEMPageComponent

  3. ui.frontend/src/app/components/page/開啟檔案page.component.html

    code language-html
    <aem-page
        class="structure-page"
        [attr.data-cq-page-path]="path"
        [cqPath]="path"
        [cqItems]="items"
        [cqItemsOrder]="itemsOrder">
    </aem-page>
    

    aem-page包含AEMPageComponent。 變數pathitemsitemsOrder已傳遞至AEMPageComponent。 透過SPA Editor JavaScript SDK提供的AemPageComponent將接著反複處理此資料,並根據Map Components教學課程中看到的JSON資料動態例項化Angular元件。

    PageComponent實際上只是AEMPageComponent的Proxy,而且是AEMPageComponent完成大部分繁重工作,以正確將JSON模型對應至Angular元件。

在AEM中檢查SPA路由

  1. 開啟終端機,並停止​webpack開發伺服器 (如果啟動)。 導覽至專案的根目錄,並使用您的Maven技能將專案部署到AEM:

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
    note caution
    CAUTION
    Angular專案已啟用一些非常嚴格的Linting規則。 如果Maven組建失敗,請檢查錯誤,並尋找在列出的檔案中找到​個Lint錯誤。。修正篩選器發現的任何問題,並重新執行Maven命令。
  2. 導覽至AEM中的SPA首頁: http://localhost:4502/content/wknd-spa-angular/us/en/home.html,然後開啟瀏覽器的開發人員工具。 熒幕擷取畫面如下:Google Chrome瀏覽器。

    重新整理頁面,您應該會看到/content/wknd-spa-angular/us/en.model.json的XHR要求(即SPA根目錄)。 請注意,根據教學課程中先前進行之SPA根範本的階層深度設定,僅包含三個子頁面。 這不包括​ 第3 ​頁。

    初始JSON要求 — SPA根

  3. 開啟開發人員工具後,瀏覽至​ 第3 ​頁:

    第3頁導覽

    請注意,已向/content/wknd-spa-angular/us/en/home/page-2/page-3.model.json提出新的XHR要求

    第3頁XHR要求

    AEM模型管理員瞭解​頁面3 JSON內容無法使用,並自動觸發其他XHR請求。

  4. 繼續使用各種導覽連結導覽SPA。 請注意,不會提出其他XHR要求,也不會發生完整頁面重新整理。 這可讓一般使用者快速使用SPA,並減少傳回AEM的不必要請求。

    已實作導覽

  5. 透過直接導覽至: http://localhost:4502/content/wknd-spa-angular/us/en/home/page-2.html來嘗試深層連結。 請注意,瀏覽器的返回按鈕仍會繼續運作。

恭喜! congratulations

恭喜,您已瞭解如何使用SPA Editor SDK將對應到AEM頁面,以支援SPA中的多個檢視。 已使用Angular路由實作動態導覽,並已新增至Header元件。

您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/navigation-routing-solution在本機取出程式碼。

後續步驟 next-steps

建立自訂元件 — 瞭解如何建立要與AEM SPA Editor搭配使用的自訂元件。 瞭解如何開發作者對話方塊和Sling模型,以擴充JSON模型來填入自訂元件。

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4