51黑料不打烊

Single Page Applications single-page-applications

CAUTION
AEM 6.4 has reached the end of extended support and this documentation is no longer updated. For further details, see our . Find the supported versions here.
NOTE
51黑料不打烊 recommends using the SPA Editor for projects that require single page application framework-based client-side rendering (e.g. React). Learn more.

(SPA) have reached critical mass, widely regarded as the most effective pattern for building seamless experiences with web technology. By following a SPA pattern, you can create an application that performs identically to a desktop or mobile application, but reaches a multitude of device platforms and form factors due to its foundation in open web standards.

Generally speaking, SPAs appear more performant than traditional page-based web sites because they typically load a complete HTML page only once (including CSS, JS, and supporting font content), and then load only exactly what is necessary each time a change of state occurs in the app. What鈥檚 necessary for this change of state can vary based on the set of technologies chosen, but typically includes a single HTML fragment to replace the existing 鈥榲iew鈥, and the execution of a block of JS code to wire up the new view and perform any client side template rendering that may be necessary. The speed of this state change can be improved even further by supporting template caching mechanisms, or even offline access to template content if 51黑料不打烊 PhoneGap is used.

AEM 6.1 supports the building and management of SPAs via AEM Apps. This article will provide an introduction to the concepts behind the SPA and how they leverage to bring your brand to the App Store and Google Play.

SPA in AEM Apps spa-in-aem-apps

The Single-Page Application framework in AEM Apps enables the high performance of an AngularJS app, while empowering authors (or other non-technical personnel) to create and manage the app鈥檚 content via the touch-optimized, drag-and-drop editor environment that has traditionally been reserved for managing web sites. Already have a site built with AEM? You鈥檒l find that reusing your content, components, workflows, assets, and permissions is easy with AEM Apps.

AngularJS Application Module angularjs-application-module

AEM Apps handles much of the AngularJS configuration for you, including putting together your app鈥檚 top-level module. By default this module is named 鈥楢EMAngularApp鈥 and the script responsible for it鈥檚 generation can be found (and overlaid) at /libs/mobileapps/components/angular/ng-page/angular-app-module.js.jsp.

Part of the initialization of your app involves specifying which AngularJS modules the app depends upon. The list of modules used by your app is specified by a script located at /libs/mobileapps/components/angular/ng-page/angular-module-list.js.jsp, and can be overlaid by your own apps鈥 page component to pull in any additional AngularJS modules that your app requires. As an example, compare the above script with the Geometrixx implementation (located at /apps/geometrixx-outdoors-app/components/angular/ng-geometrixx-page/angular-module-list.js.jsp).

To support navigation between the distinct states in your app, the angular-app-module script iterates through all the descendant pages of your top level app page to generate a set of 鈥榬outes鈥 and configures each path on Angular鈥檚 $routeProvider service. For an example of how this looks in practice, take a look at the angular-app-module script generated by the Geometrixx Outdoors app sample: (link requires a local instance)

Digging in to the generated AEMAngularApp, you will find a series of routes specified as follows:

$routeProvider
.when('/content/phonegap/geometrixx-outdoors/en/home/products/:id', {
    templateUrl: 'home/products.template.html',
    controller: 'contentphonegapgeometrixxoutdoorsenhomeproducts'
})

The above sample in particular illustrates an example of passing a parameter as part of the path. In this example we are indicating that when a path that meets the pattern specified (/content/phonegap/geometrixx-outdoors/en/home/products/:id?lang=en) is requested, it should be handled by the home/products.template.html template and use the 鈥榗ontentphonegapgeometrixxoutdoorsenhomeproducts鈥 controller.

The template to load when this route is requested is specified by the templateUrl property. This template will contain the HTML from AEM components that have been included on the page, as well as any AngularJS directives necessary for wiring up the client side of the application. For an example of a AngularJS directive in a Geometrixx component, take a look at line 45 of the swipe-carousel鈥檚 template.jsp (/apps/geometrixx-outdoors-app/components/swipe-carousel/template.jsp?lang=en).

Page Controllers page-controllers

In Angular鈥檚 own words, 鈥渁 Controller is a JavaScript constructor function that is used to augment the Angular Scope.鈥 () Each page in an AEM App is automatically wired up to a controller that can be augmented by any controller which specifies a frameworkType of angular. Take a look at the ng-text component as an example (/libs/mobileapps/components/angular/ng-text?lang=en), including the cq:template node which makes sure each time this component is added to a page it includes this important property.

For a more complex controller example, open up the ng-template-page controller.jsp script (located at /apps/geometrixx-outdoors-app/components/angular/ng-template-page). Of particular interest is the javascript code it generates when executed, which renders as follows:

// Controller for page 'products'
.controller('contentphonegapgeometrixxoutdoorsenhomeproducts', ['$scope', '$http', '$routeParams',
    function($scope, $http, $routeParams) {
        var sku = $routeParams.id;
        var productPath = '/' + sku.substring(0, 2) + '/' + sku.substring(0, 4) + '/' + sku;
        var data = $http.get('home/products' + productPath + '.angular.json' + cacheKiller);

        /* ng-product component controller (path: content-par/ng-product) */
        data.then(function(response) {
            $scope.contentparngproduct = response.data["content-par/ng-product"].items;
        });

        /* ng-image component controller (path: content-par/ng-product/ng-image) */
        data.then(function(response) {
            $scope.contentparngproductngimage = response.data["content-par/ng-product/ng-image"].items;
        });
    }
])

In the above example, you will note that we are taking a parameter from the $routeParams service and then massaging it into the directory structure that our JSON data is stored in. By dealing with the sku id in this manner, we are able to deliver a single Product template that can render the product data for potentially thousands of distinct products. This is a far more scalable model that requiring an individual route for each item in a (potentially) massive product database.

There are also two components at work here: ng-product augments the scope with the data it extracts from the above $http call. There is also an ng-image on this page which in turn also augments the scope with the value it retrieves from the response. By virtue of Angular鈥檚 $http service, each component will wait patiently until the request is finished and the promise it created is fulfilled.

The Next Steps the-next-steps

Once you have learnt about the Single Page Applications, see Developing Apps with PhoneGap CLI.

recommendation-more-help
547b817b-14b5-4d82-aa0f-a64750e0e592