使用AEM SPA編輯器開發 — Hello World教學課程

警告

本教學課程為​已廢止。 建議您遵循下列任一項:AEM SPA Editor and ReactAngular快速入門AEM SPA Editor and React快速入門

AEM SPA編輯器支援在內容內編輯單頁應用程式或SPA。 本教學課程介紹要與AEM SPA Editor JS SDK搭配使用的SPA開發。 本教學課程將新增自訂Hello World元件,以擴充We.Retail Journal應用程式。 使用者可使用React或Angular架構完成本教學課程。

注意

單頁應用程式(SPA)編輯器功能需要AEM 6.4 service pack 2或更新版本。

若專案需要SPA架構的用戶端轉譯(例如React或Angular),SPA Editor是建議的解決方案。

必備條件閱讀

本教學課程旨在反白顯示將SPA元件對應至AEM元件以啟用內容內編輯所需的步驟。 開始本教學課程的使用者應熟悉Adobe Experience Manager、AEM的開發基本概念,以及透過React開發Angular架構。 本教學課程涵蓋後端和前端開發工作。

開始本教學課程之前,建議先檢閱下列資源:

本機開發環境

本教學課程的設計目的:

Adobe Experience Manager 6.5Adobe Experience Manager 6.4 + Service Pack 5

在本教學課程中,應安裝下列技術和工具:

  1. Java 11
  2. Apache Maven - 3.3.1+
  3. Node.js - 8.11.1+ 和npm 5.6.0+(npm隨node.js安裝)

開啟新終端並運行以下程式,仔細檢查上述工具的安裝:

$ java -version
java version "11 +"

$ mvn -version
Apache Maven 3.3.9

$ node --version
v8.11.1

$ npm --version
6.1.0

概覽

基本概念是將SPA元件對應至AEM元件。 AEM元件,執行伺服器端,以JSON格式匯出內容。 SPA會使用JSON內容,在瀏覽器中執行用戶端。 系統會建立SPA元件與AEM元件之間的1:1對應。

SPA元件對應

熱門架構React JSAngular可立即使用。 使用者可以透過Angular或React完成本教學課程,無論其最熟悉的架構為何。

專案設定

SPA開發只有一步之遙,另一步之遙。 目標是讓SPA開發能獨立進行,且(大多)不受AEM限制。

  • SPA專案在前端開發期間可獨立於AEM專案運作。
  • 前端建置工具和技術(如Webpack、NPM、Grunt和Gulp)繼續使用。
  • 若要為AEM建置,系統會編譯SPA專案並自動加入AEM專案。
  • 用於將SPA部署至AEM的標準AEM套件。

對象和部署概述

SPA開發只有一步是AEM開發,另一步則是開發 — 讓SPA開發能獨立進行,且(大多)不受AEM限制。

本教學課程的目標是使用新元件擴充We.Retail日誌應用程式。 首先,下載We.Retail Journal應用程式的原始碼,並部署至本機AEM。

  1. ​從GitHub下 載最新的We.Retail日誌代碼

    或從命令列複製存放庫:

    $ git clone git@github.com:adobe/aem-sample-we-retail-journal.git
    
    注意

    本教學課程將針對​master​分支使用​1.2.1-SNAPSHOT​版本的專案。

  2. 下列結構應可見:

    專案資料夾結構

    專案包含下列Maven模組:

    • all:將整個專案內嵌並安裝在單一套件中。
    • bundles:包含兩個OSGi套件組合:包含和其他Java程式碼 Sling Models 的公域和核心。
    • ui.apps:包含專案的/apps部分、ie JS與CSS clientlibs、元件、執行模式特定設定。
    • ui.content:包含結構內容和設定(/content/conf)
    • react-app:We.Retail Journal React應用程式。這既是Maven模組,也是Webpack專案。
    • angular-app:We.Retail JournalAngular應用程式。這既是Maven模組,也是Webpack專案。
  3. 開啟新的終端機視窗並執行下列命令,以建立整個應用程式並部署至在http://localhost:4502上執行的本機AEM執行個體。

    $ cd <src>/aem-sample-we-retail-journal
    $ mvn -PautoInstallSinglePackage clean install
    
    注意

    在本專案中,要建立並封裝整個專案的Maven設定檔為autoInstallSinglePackage

    注意

    如果您在建置期間收到錯誤,請確保您的Maven settings.xml檔案包含Adobe的Maven工件存放庫

  4. 導航到:

    We.Retail日誌應用程式應顯示在AEM Sites編輯器中。

  5. 在編輯模式中,選擇要編輯的元件並對內容進行更新。

    編輯元件

  6. 選擇頁面屬性圖示以開啟頁面屬性。 選擇編輯模板以開啟頁面的模板。

    頁面屬性功能表

  7. 在最新版SPA編輯器中,可編輯的範本的使用方式與傳統Sites實施相同。 我們稍後將透過自訂元件重新審視此項目。

    注意

    只有AEM 6.5和AEM 6.4 + Service Pack 5​支援可編輯的範本。

開發概述

概述開發

SPA開發反覆項目會獨立於AEM進行。 當SPA準備好部署至AEM時,會進行下列高階步驟(如上圖所示)。

  1. 系統會叫用AEM專案組建,而這會觸發SPA專案的組建。 We.Retail Journal使用​frontend-maven-plugin
  2. SPA專案的​aem-clientlib-generator將編譯的SPA內嵌為AEM專案中的AEM Client Library。
  3. AEM專案會產生AEM套件,包括已編譯的SPA,以及任何其他支援AEM程式碼。

建立AEM元件

角色:AEM開發人員

首先會建立AEM元件。 AEM元件負責轉譯React元件讀取的JSON屬性。 AEM元件也負責提供元件的任何可編輯屬性的對話方塊。

使用Eclipse或其他IDE,匯入We.Retail Journal Maven專案。

  1. 更新reactor pom.xml​以移除Apache Rat外掛程式。 此外掛程式會檢查每個檔案,以確保有「授權」標題。 為了我們的目的,我們不需要關注此功能。

    在​aem-sample-we-retail-journal/pom.xml​中,移除​apache-rate-plugin:

    <!-- Remove apache-rat-plugin -->
    <plugin>
            <groupId>org.apache.rat</groupId>
            <artifactId>apache-rat-plugin</artifactId>
            <configuration>
                <excludes combine.children="append">
                    <exclude>*</exclude>
                        ...
                </excludes>
            </configuration>
            <executions>
                    <execution>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                </execution>
            </executions>
        </plugin>
    
  2. 在​we-retail-journal-content(<src>/aem-sample-we-retail-journal/ui.apps)模組中,在​helloworld​下建立一個名為​cq:Component​的新節點。ui.apps/jcr_root/apps/we-retail-journal/components

  3. 將下列屬性新增至​helloworld​元件,如下XML(/helloworld/.content.xml)所示:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
        jcr:description="Hello World Component for We.Retail Journal"
        jcr:primaryType="cq:Component"
        jcr:title="Hello World"
        componentGroup="We.Retail Journal" />
    

    Hello World元件

    注意

    為了說明「可編輯的範本」功能,我們故意設定componentGroup="Custom Components"。 在真實專案中,最好將元件群組的數量減到最少,因此較好的群組是「We.Retail Journal」,以符合其他內容元件。

    只有AEM 6.5和AEM 6.4 + Service Pack 5​支援可編輯的範本。

  4. 接下來將建立對話框,以允許為​Hello World​元件配置自定義消息。 在/apps/we-retail-journal/components/helloworld下方添加​nt:unstructured​的節點名稱​cq:dialog

  5. cq:dialog​將顯示一個將文本保存到名為​message​的屬性的文本欄位。 在新建立的​cq:dialog​下方新增下列節點和屬性,如下方的XML(helloworld/_cq_dialog/.content.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" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured"
        jcr:title="We.Retail Journal - Hello World"
        sling:resourceType="cq/gui/components/authoring/dialog">
        <content
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/container">
            <items jcr:primaryType="nt:unstructured">
                <tabs
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/tabs"
                    maximized="{Boolean}true">
                    <items jcr:primaryType="nt:unstructured">
                        <properties
                            jcr:primaryType="nt:unstructured"
                            jcr:title="Properties"
                            sling:resourceType="granite/ui/components/coral/foundation/container"
                            margin="{Boolean}true">
                            <items jcr:primaryType="nt:unstructured">
                                <columns
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                                    margin="{Boolean}true">
                                    <items jcr:primaryType="nt:unstructured">
                                        <column
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/container">
                                            <items jcr:primaryType="nt:unstructured">
                                                <message
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    fieldLabel="Message"
                                                    name="./message"
                                                    required="{Boolean}true"/>
                                            </items>
                                        </column>
                                    </items>
                                </columns>
                            </items>
                        </properties>
                    </items>
                </tabs>
            </items>
        </content>
    </jcr:root>
    

    檔案結構

    上述XML節點定義將建立一個對話框,其中包含一個文本欄位,該欄位將允許用戶輸入「消息」。 記下<message />節點內的屬性name="./message"。 這是將儲存在AEM內JCR中之屬性的名稱。

  6. 接下來將建立空策略對話框(cq:design_dialog)。 需要「策略」對話框才能在模板編輯器中查看元件。 對於這個簡單的使用案例,它將是空白的對話方塊。

    /apps/we-retail-journal/components/helloworld下方添加nt:unstructured的節點名cq:design_dialog

    配置以下的XML表示(helloworld/_cq_design_dialog/.content.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" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
    jcr:primaryType="nt:unstructured" />
    
  7. 從命令列將程式碼基底部署至AEM:

    $ cd <src>/aem-sample-we-retail-journal/content
    $ mvn -PautoInstallPackage clean install
    

    CRXDE Lite中,檢查/apps/we-retail-journal/components:下的資料夾,以驗證元件已部署

    部署的元件結構(CRXDE Lite)

建立Sling模型

角色:AEM開發人員

接下來建立Sling Model以備份Hello World元件。 在傳統WCM使用案例中,Sling Model會實作任何商業邏輯,而伺服器端轉譯指令碼(HTL)會呼叫Sling Model。 這可讓轉譯指令碼相對簡單。

Sling Models 也用於SPA使用案例,以實作伺服器端業務邏輯。差異在於在SPA使用案例中,Sling Models會以序列化JSON形式顯示其方法。

注意

開發人員應盡可能使用AEM核心元件,這才是最佳作法。 核心元件提供「SPA就緒」的Sling Models JSON輸出,可讓開發人員將更多精力放在前端簡報上。

  1. 在您選擇的編輯器中,開啟​we-retail-journal-commons​專案(<src>/aem-sample-we-retail-journal/bundles/commons)。

  2. 在包com.adobe.cq.sample.spa.commons.impl.models中:

    • 建立名為HelloWorld的新類。
    • com.adobe.cq.export.json.ComponentExporter.新增實作介面

    新建Java類嚮導

    必須實作ComponentExporter介面,Sling Model才能與AEM Content Services相容。

     package com.adobe.cq.sample.spa.commons.impl.models;
    
     import com.adobe.cq.export.json.ComponentExporter;
    
     public class HelloWorld implements ComponentExporter {
    
         @Override
         public String getExportedType() {
             return null;
         }
     }
    
  3. 添加名為RESOURCE_TYPE的靜態變數以標識HelloWorld元件的資源類型:

     ...
     public class HelloWorld implements ComponentExporter {
    
         static final String RESOURCE_TYPE = "we-retail-journal/components/helloworld";
    
         ...
     }
    
  4. @Model@Exporter添加OSGi注釋。 @Model注釋將類註冊為Sling Model。 @Exporter附註會使用Jackson Exporter架構將方法公開為序列化JSON。

    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.models.annotations.Exporter;
    import org.apache.sling.models.annotations.Model;
    import com.adobe.cq.export.json.ExporterConstants;
    ...
    
    @Model(
            adaptables = SlingHttpServletRequest.class,
            adapters = {ComponentExporter.class},
            resourceType = HelloWorld.RESOURCE_TYPE
    )
    @Exporter(
            name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, 
            extensions = ExporterConstants.SLING_MODEL_EXTENSION
    )
    public class HelloWorld implements ComponentExporter {
    
    ...
    
  5. 實作方法getDisplayMessage()以傳回JCR屬性message。 使用@ValueMapValue的Sling Model注釋,可輕鬆檢索儲存在元件下的屬性message@Optional注釋很重要,因為元件首次新增至頁面時,將不會填入message

    作為業務邏輯的一部分,字串"Hello"將會加到消息前面。

    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
    import org.apache.sling.models.annotations.Optional;
    
    ...
    
    public class HelloWorld implements ComponentExporter {
    
       static final String RESOURCE_TYPE = "we-retail-journal/components/helloworld";
    
       private static final String PREPEND_MSG = "Hello";
    
        @ValueMapValue @Optional
        private String message;
    
        public String getDisplayMessage() {
            if(message != null && message.length() > 0) {
                return PREPEND_MSG + " "  + message;
            }
            return null;
        }
    
    ...
    
    注意

    方法名稱getDisplayMessage很重要。 使用Jackson Exporter序列化Sling Model時,它會以JSON屬性公開:displayMessage。 Jackson Exporter將序列化並公開所有未採用參數的getter方法(除非明確標籤為忽略)。 稍後在React /Angular應用程式中,我們會讀取此屬性值,並將其顯示為應用程式的一部分。

    方法getExportedType也很重要。 元件resourceType的值將用來「對應」JSON資料至前端元件(Angular/ React)。 我們將在下一節中探討此內容。

  6. 實作方法getExportedType()以傳回HelloWorld元件的資源類型。

     @Override
        public String getExportedType() {
            return RESOURCE_TYPE;
        }
    

    您可以在此處找到​HelloWorld.java​的完整代碼。

  7. 使用Apache Maven將程式碼部署至AEM:

    $ cd <src>/sample-we-retail-spa-content/bundles/commons
    $ mvn -PautoInstallPackage clean install
    

    導覽至OSGi主控台中的Status > Sling Models,驗證Sling Model的部署和註冊。

    您應會看到HelloWorld Sling Model已系結至we-retail-journal/components/helloworld Sling資源類型,且已註冊為Sling Model Exporter Servlet:

    com.adobe.cq.sample.spa.commons.impl.models.HelloWorld - we-retail-journal/components/helloworld
    com.adobe.cq.sample.spa.commons.impl.models.HelloWorld exports 'we-retail-journal/components/helloworld' with selector 'model' and extension '[Ljava.lang.String;@6480f3e5' with exporter 'jackson'
    

建立React元件

角色:前端開發人員

接下來,將建立React元件。 使用您選擇的編輯器開啟​react-app​模組(<src>/aem-sample-we-retail-journal/react-app)。

注意

如果您只對Angular開發感興趣,歡迎跳過此部分。

  1. react-app資料夾內導覽至其src資料夾。 展開元件資料夾以檢視現有的React元件檔案。

    react元件檔案結構

  2. 在名為HelloWorld.js的元件資料夾下添加新檔案。

  3. 開啟 HelloWorld.js. 新增匯入陳述式以匯入React元件程式庫。 添加第二個導入語句以導入Adobe提供的MapTo幫助程式。 MapTo協助程式提供React元件與AEM元件JSON的對應。

    import React, {Component} from 'react';
    import {MapTo} from '@adobe/cq-react-editable-components';
    
  4. 在匯入下方建立名為HelloWorld的新類,該類擴展了React Component介面。 將所需的render()方法新增至HelloWorld類別。

    import React, {Component} from 'react';
    import {MapTo} from '@adobe/cq-react-editable-components';
    
    class HelloWorld extends Component {
    
        render() {
    
        }
    }
    
  5. MapTo協助程式會自動包含名為cqModel的物件,作為React元件prop的一部分。 cqModel包含Sling Model公開的所有屬性。

    請記住,先前建立的Sling Model包含方法getDisplayMessage()getDisplayMessage() 在輸出時會轉譯為JSON displayMessage 索引鍵。

    實作render()方法以輸出包含displayMessage值的h1標籤。 JSX是JavaScript的語法擴充功能,可用來傳回元件的最終標籤。

    ...
    
    class HelloWorld extends Component {
        render() {
    
            if(this.props.displayMessage) {
                return (
                    <div className="cmp-helloworld">
                        <h1 className="cmp-helloworld_message">{this.props.displayMessage}</h1>
                    </div>
                );
            }
            return null;
        }
    }
    
  6. 實作編輯設定方法。 此方法會透過MapTo協助程式傳遞,並提供AEM編輯器資訊以在元件為空時顯示預留位置。 元件新增至SPA但尚未撰寫時,即會發生此情況。 在HelloWorld類別下方新增下列項目:

    ...
    
    class HelloWorld extends Component {
        ...
    }
    
    const HelloWorldEditConfig = {
    
        emptyLabel: 'Hello World',
    
        isEmpty: function(props) {
            return !props || !props.displayMessage || props.displayMessage.trim().length < 1;
        }
    };
    
    ...
    
  7. 在檔案結尾,呼叫MapTo協助程式,傳遞HelloWorld類別和HelloWorldEditConfig。 這會根據AEM元件的資源類型,將React元件對應至AEM元件:we-retail-journal/components/helloworld

    MapTo('we-retail-journal/components/helloworld')(HelloWorld, HelloWorldEditConfig);
    

    您可以在此處找到​HelloWorld.js​的已完成代碼。

  8. 開啟檔案ImportComponents.js。 可在<src>/aem-sample-we-retail-journal/react-app/src/ImportComponents.js找到。

    添加一行以要求HelloWorld.js以及編譯的JavaScript包中的其他元件:

    ...
      require('./components/Text');
      require('./components/Image');
      require('./components/HelloWorld');
    ...
    
  9. components資料夾中,建立名為HelloWorld.css的新檔案,作為HelloWorld.js.的同級檔案,使用以下內容填入檔案,為HelloWorld元件建立一些基本樣式:

    /* HelloWorld.css to style HelloWorld component */
    
    .cmp-helloworld_message {
        text-align: center;
        color: #ff505e;
        text-transform: unset;
        letter-spacing: unset;
    }
    
  10. 重新開啟HelloWorld.js並更新匯入陳述式下方以要求HelloWorld.css:

    import React, {Component} from 'react';
    import {MapTo} from '@adobe/cq-react-editable-components';
    
    require('./HelloWorld.css');
    
    ...
    
  11. 使用Apache Maven將程式碼部署至AEM:

    $ cd <src>/sample-we-retail-spa-content
    $ mvn -PautoInstallSinglePackage clean install
    
  12. CRXDE-Lite中開啟/apps/we-retail-journal/react/clientlibs/we-retail-journal-react/js/app.js。 在app.js中執行HelloWorld快速搜尋,以確認已編譯應用程式中已包含React元件。

    注意

    app. jsis整合的React應用程式。程式碼不再是人類看得懂的。 npm run build命令已觸發最佳化組建,會輸出已編譯的JavaScript,供現代瀏覽器解譯。

建立Angular元件

角色:前端開發人員

注意

如果您只對React開發感興趣,歡迎略過本節。

接著,將建立Angular元件。 使用您選擇的編輯器開啟​angular-app​模組(<src>/aem-sample-we-retail-journal/angular-app)。

  1. angular-app資料夾內,導覽至其src資料夾。 展開元件資料夾以檢視現有的Angular元件檔案。

    Angular檔案結構

  2. 在名為helloworld的元件資料夾下添加新資料夾。 在helloworld資料夾下方新增名為helloworld.component.css, helloworld.component.html, helloworld.component.ts的新檔案。

    /angular-app
        /src
            /app
                /components
    +                /helloworld
    +                    helloworld.component.css
    +                    helloworld.component.html
    +                    helloworld.component.ts
    
  3. 開啟 helloworld.component.ts. 添加導入語句以導入AngularComponentInput類。 建立新元件,將styleUrlstemplateUrl指向helloworld.component.csshelloworld.component.html。 最後,導出類HelloWorldComponent,預期輸入為displayMessage

    //helloworld.component.ts
    
    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'app-helloworld',
      host: { 'class': 'cmp-helloworld' },
      styleUrls:['./helloworld.component.css'],
      templateUrl: './helloworld.component.html',
    })
    
    export class HelloWorldComponent {
      @Input() displayMessage: string;
    }
    
    注意

    如果您回想一下先前建立的Sling Model,會發現一個方法​getDisplayMessage()。 此方法的序列化JSON將是​displayMessage,我們目前正在Angular應用程式中讀取。

  4. 開啟helloworld.component.html以包含將打印displayMessage屬性的h1標籤:

    <h1 *ngIf="displayMessage" class="cmp-helloworld_message">
        {{displayMessage}}
    </h1>
    
  5. 更新helloworld.component.css以包含元件的一些基本樣式。

    :host-context {
        display: block;
    };
    
    .cmp-helloworld {
        display:block;
    }
    .cmp-helloworld_message {
        text-align: center;
        color: #ff505e;
        text-transform: unset;
        letter-spacing: unset;
    }
    
  6. 使用以下測試台更新helloworld.component.spec.ts:

    import { async, ComponentFixture, TestBed } from '@angular/core/testing';
    
    import { HelloWorldComponent } from './helloworld.component';
    
        describe('HelloWorld', () => {
        let component: HelloWorldComponent;
        let fixture: ComponentFixture<HelloWorldComponent>;
    
        beforeEach(async(() => {
            TestBed.configureTestingModule({
            declarations: [ HelloWorldComponent ]
            })
            .compileComponents();
        }));
    
        beforeEach(() => {
            fixture = TestBed.createComponent(HelloWorldComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
        });
    
        it('should create', () => {
            expect(component).toBeTruthy();
        });
    });
    
  7. 下次更新src/components/mapping.ts以包含HelloWorldComponent。 新增HelloWorldEditConfig,在設定元件之前,在AEM編輯器中標示預留位置。 最後,新增一行以使用MapTo協助程式將AEM元件對應至Angular元件。

    // src/components/mapping.ts
    
    import { HelloWorldComponent } from "./helloworld/helloworld.component";
    
    ...
    
    const HelloWorldEditConfig = {
    
        emptyLabel: 'Hello World',
    
        isEmpty: function(props) {
            return !props || !props.displayMessage || props.displayMessage.trim().length < 1;
        }
    };
    
    ...
    
    MapTo('we-retail-journal/components/helloworld')(HelloWorldComponent, HelloWorldEditConfig);
    

    您可以在此處找到​mapping.ts​的完整代碼。

  8. 更新src/app.module.ts以更新​NgModule。 將​HelloWorldComponent​新增為​declaration,屬於​AppModule。 也會將HelloWorldComponent新增為​entryComponent,以便在處理JSON模型時將其編譯並動態納入應用程式中。

    import { HelloWorldComponent } from './components/helloworld/helloworld.component';
    
    ...
    
    @NgModule({
      imports: [BrowserModule.withServerTransition({ appId: 'we-retail-sample-angular' }),
        SpaAngularEditableComponentsModule,
      AngularWeatherWidgetModule.forRoot({
        key: "37375c33ca925949d7ba331e52da661a",
        name: WeatherApiName.OPEN_WEATHER_MAP,
        baseUrl: 'http://api.openweathermap.org/data/2.5'
      }),
        AppRoutingModule,
        BrowserTransferStateModule],
      providers: [ModelManagerService,
        { provide: APP_BASE_HREF, useValue: '/' }],
      declarations: [AppComponent,
        TextComponent,
        ImageComponent,
        WeatherComponent,
        NavigationComponent,
        MenuComponent,
        MainContentComponent,
        HelloWorldComponent],
      entryComponents: [TextComponent,
        ImageComponent,
        WeatherComponent,
        NavigationComponent,
        MainContentComponent,
        HelloWorldComponent],
      bootstrap: [AppComponent]
     })
    

    您可在此處找到​app.module.ts​的已完成代碼。

  9. 使用Maven將程式碼部署至AEM:

    $ cd <src>/sample-we-retail-spa-content
    $ mvn -PautoInstallSinglePackage clean install
    
  10. CRXDE-Lite中開啟/apps/we-retail-journal/angular/clientlibs/we-retail-journal-angular/js/main.js。 在main.js中對​HelloWorld​執行快速搜索,以驗證已包含Angular元件。

    注意

    main. jsis套件Angular應用程式。程式碼不再是人類看得懂的。 npm run build命令已觸發最佳化組建,會輸出已編譯的JavaScript,供現代瀏覽器解譯。

更新範本

  1. 導覽至React和/或Angular版本的可編輯範本:

  2. 選擇主佈局容器並選擇策略表徵圖以開啟其策略:

    選擇佈局策略

    在「屬性 > 允許的元件」下,執行​Custom Components​的搜索。 應該會看到​Hello World​元件,請選取它。 按一下右上角的核取方塊,儲存您的變更。

    配置容器策略配置

  3. 儲存後,應該會在配置容器中將​HelloWorld​元件顯示為允許的元件。

    已更新允許的元件

    注意

    只有AEM 6.5和AEM 6.4.5支援SPA編輯器的「可編輯範本」功能。 如果使用AEM 6.4,您需要透過CRXDE Lite手動設定「允許的元件」的原則:/conf/we-retail-journal/react/settings/wcm/policies/wcm/foundation/components/responsivegrid/default/conf/we-retail-journal/angular/settings/wcm/policies/wcm/foundation/components/responsivegrid/default

    CRXDE Lite顯示佈局容器中允許的元件的更新策略配置:

    CRXDE Lite顯示「佈局容器」中「允許的元件」的更新策略配置

把它們放在一起

  1. 導覽至「Angular」或「React」頁面:

  2. 找到​Hello World​元件,並將​Hello World​元件拖放至頁面。

    hello world drag + drop

    預留位置應會出現。

    《你好世界》排名單

  3. 選取元件並在對話方塊中新增訊息,例如「World」或「Your Name」。 儲存變更。

    已呈現元件

    請注意,字串"Hello"一律會加在訊息前面。 這是HelloWorld.java Sling Model中邏輯的結果。

後續步驟

HelloWorld元件的已完成解決方案

疑難排解

無法在Eclipse中建立專案

錯誤: 將專案匯入Eclipse以執行無 We.Retail Journal 法識別的目標時發生錯誤:

Execution npm install, Execution npm run build, Execution default-analyze-classes*

eclipe錯誤精靈

解決方法:按一下「完成」以稍後解決這些問題。這不應妨礙教學課程的完成。

錯誤:React模組在Maven react-app組建期間未成功建置。

解決方法: 嘗試刪 node_modules 除react-app 下方的資料夾。從專案的根目錄重新執行Apache Maven命令mvn clean install -PautoInstallSinglePackage

AEM中未滿足的相依性

包管理器依賴關係錯誤

如果不滿足AEM相依性,在​AEM封裝管理器​中,或在​AEM Web Console(Felix Console)中,表示SPA編輯器功能不可用。

元件未顯示

錯誤:即使成功部署並驗證編譯的React/Angular應用程式版本有更新的元件 helloworld 後,我將元件拖曳至頁面時,元件仍不會顯示。我可以在AEM UI中看到元件。

解決方法:清除瀏覽器的歷史記錄/快取和/或開啟新瀏覽器或使用無痕模式。如果無法運作,請使本機AEM例項上的用戶端程式庫快取失效。 AEM會嘗試快取大型clientlibrary以提高效率。 有時需要手動使快取失效,以修正快取過期代碼的問題。

導覽至:http://localhost:4502/libs/granite/ui/content/dumplibs.rebuild.html ,然後按一下「使快取無效」。 返回您的React/Angular頁面並重新整理頁面。

重建客戶端庫

本頁內容