mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
docs(deep-linker): update deep linker docs with new decorator
This commit is contained in:
@ -15,18 +15,17 @@ import { ViewController } from './view-controller';
|
||||
/**
|
||||
* @name DeepLinker
|
||||
* @description
|
||||
* DeepLinker handles registering and displaying specific views based on URLs. It's used
|
||||
* underneath NavController so you'll never have to interact with it directly. When a new
|
||||
* view is push'ed with NavController, the URL is updated to match the path back to this
|
||||
* page.
|
||||
* Deep linker handles registering and displaying specific pages based on URLs. It's used
|
||||
* underneath `NavController` so it will never have to be interacted with directly. When a new
|
||||
* page is pushed with `NavController`, the URL is updated to match the path to this page.
|
||||
*
|
||||
* Unlike traditional web apps, URLs don't dictate navigation in Ionic apps.
|
||||
* Instead, URLs help us link to specific pieces of content as a breadcrumb.
|
||||
* We keep the current URL updated as we navigate, but we use the NavController's
|
||||
* push and pop, or navPush to move around. This makes it much easier
|
||||
* to handle the kinds of complicated nested navigation native apps are known for.
|
||||
* The current URL gets updated as we navigate, but we use the `NavController`
|
||||
* push and pop, or `NavPush` and `NavPop` to move around. This makes it much easier
|
||||
* to handle complicated nested navigation.
|
||||
*
|
||||
* We refer to our URL system as a Deep Link system instead of a Router to encourage
|
||||
* We refer to our URL system as a deep link system instead of a router to encourage
|
||||
* Ionic developers to think of URLs as a breadcrumb rather than as the source of
|
||||
* truth in navigation. This encourages flexible navigation design and happy apps all
|
||||
* over the world.
|
||||
@ -34,88 +33,237 @@ import { ViewController } from './view-controller';
|
||||
*
|
||||
* @usage
|
||||
*
|
||||
* DeepLinker can be used in the `IonicModule.forRoot` method, as the third parameter
|
||||
* The first step to setting up deep links is to add the page that should be
|
||||
* a deep link in the `DeepLinkModule.forChild` import of the page's module.
|
||||
* For our examples, this will be `MyPage`:
|
||||
*
|
||||
* ```ts
|
||||
* imports: [
|
||||
* IonicModule.forRoot(MyApp, {}, {
|
||||
* links: []
|
||||
* })
|
||||
* @NgModule({
|
||||
* declarations: [
|
||||
* MyPage
|
||||
* ],
|
||||
* imports: [
|
||||
* DeepLinkModule.forChild(MyPage)
|
||||
* ],
|
||||
* entryComponents: [
|
||||
* MyPage
|
||||
* ]
|
||||
* })
|
||||
* export class MyPageModule {}
|
||||
* ```
|
||||
*
|
||||
* DeepLinker implements `DeepLinkerConfig`, which is an object with an array of links.
|
||||
* So for basic example based on the blank starter, a link setup like so:
|
||||
* Then, add the `@DeepLink` decorator to the component. The most simple usage is adding an
|
||||
* empty decorator:
|
||||
*
|
||||
* ```ts
|
||||
* imports: [
|
||||
* IonicModule.forRoot(MyApp, {}, {
|
||||
* links: [
|
||||
* { component: HomePage, name: 'Home', segment: 'home' }
|
||||
* ]
|
||||
* })
|
||||
* ]
|
||||
* @DeepLink()
|
||||
* @Component({
|
||||
* templateUrl: 'main.html'
|
||||
* })
|
||||
* export class MyPage {}
|
||||
* ```
|
||||
*
|
||||
* Since components/pages can be loaded anywhere in the app, DeepLinker lets you define their URL segment but
|
||||
* doesn't require a full URL route.
|
||||
*
|
||||
* So, at any point a Page becomes the active page, we just append the URL segment.
|
||||
*
|
||||
* ### Dynamic Links
|
||||
*
|
||||
* Since passing data around is common practice in an app, we can reflect that in our app's URL by
|
||||
* using the common `:param` syntax:
|
||||
* This will automatically create a link to the `MyPage` component using the same name as the class,
|
||||
* `name`: `'MyPage'`. The page can now be navigated to by using this name. For example:
|
||||
*
|
||||
* ```ts
|
||||
* links: [
|
||||
* { component: HomePage, name: 'Home', segment: 'home' },
|
||||
* { component: DetailPage, name: 'Detail', segment: 'detail/:userId' }
|
||||
* ]
|
||||
* ```
|
||||
* @Component({
|
||||
* templateUrl: 'another-page.html'
|
||||
* })
|
||||
* export class AnotherPage {
|
||||
* constructor(public navCtrl: NavController) {}
|
||||
*
|
||||
* In this case, when we `push` to a new instance of `DetailPage`, the `user` field of
|
||||
* the data we pass to `push` will be put into the URL.
|
||||
* goToMyPage() {
|
||||
* // go to the MyPage component
|
||||
* this.navCtrl.push('MyPage');
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The property needs to be something that can be serialized into a string by the DeepLinker.
|
||||
* The `@DeepLink` decorator accepts a `DeepLinkMetadataType` object. This object accepts
|
||||
* the following properties: `name`, `segment`, `defaultHistory`, and `priority`. All of them
|
||||
* are optional but can be used to create complex navigation links.
|
||||
*
|
||||
* So in a typical `navCtrl.push()` scenario, we'd do something like this:
|
||||
*
|
||||
* ### Changing Name
|
||||
*
|
||||
* As mentioned previously, the `name` property will be set to the class name if it isn't provided.
|
||||
* Changing the name of the link is extremely simple. To change the name used to link to the
|
||||
* component, simply pass it in the decorator like so:
|
||||
*
|
||||
* ```ts
|
||||
* pushPage(userInfo) {
|
||||
* this.navCtrl.push(DetailPage, {
|
||||
* 'userId': userInfo.id
|
||||
* })
|
||||
* @DeepLink({
|
||||
* name: 'my-page'
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* This will create a link to the `MyPage` component using the name `'my-page'`. Similar to the previous
|
||||
* example, the page can be navigated to by using the name:
|
||||
*
|
||||
* ```ts
|
||||
* goToMyPage() {
|
||||
* // go to the MyPage component
|
||||
* this.navCtrl.push('my-page');
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* ### Setting URL Path
|
||||
*
|
||||
* The `segment` property is used to set the URL to the page. If this property isn't provided, the
|
||||
* `segment` will use the value of `name`. Since components can be loaded anywhere in the app, the
|
||||
* `segment` doesn't require a full URL path. When a page becomes the active page, the `segment` is
|
||||
* appended to the URL.
|
||||
*
|
||||
* The `segment` can be changed to anything and doesn't have to match the `name`. For example, passing
|
||||
* a value for `name` and `segment`:
|
||||
*
|
||||
* ```ts
|
||||
* @DeepLink({
|
||||
* name: 'my-page',
|
||||
* segment: 'some-path'
|
||||
* })
|
||||
*
|
||||
* When navigating to this page as the first page in the app, the URL will look something like:
|
||||
*
|
||||
* ```
|
||||
* http://localhost:8101/#/some-path
|
||||
* ```
|
||||
*
|
||||
* However, navigating to the page will still use the `name` like the previous examples do.
|
||||
*
|
||||
*
|
||||
* ### Dynamic Links
|
||||
*
|
||||
* The `segment` property is useful for creating dynamic links. Sometimes the URL isn't known ahead
|
||||
* of time, so it can be passed as a variable.
|
||||
*
|
||||
* Since passing data around is common practice in an app, it can be reflected in the app's URL by
|
||||
* using the `:param` syntax. For example, set the `segment` in the `@DeepLink` decorator:
|
||||
*
|
||||
* ```ts
|
||||
* @DeepLink({
|
||||
* name: 'detail-page',
|
||||
* segment: 'detail/:id'
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* In this case, when we `push` to a new instance of `'detail-page'`, the value of `id` will
|
||||
* in the `detailInfo` data being passed to `push` will replace `:id` in the URL.
|
||||
*
|
||||
* Important: The property needs to be something that can be converted into a string, objects
|
||||
* are not supported.
|
||||
*
|
||||
* For example, to push the `'detail-page'` in the `ListPage` component, the following code could
|
||||
* be used:
|
||||
*
|
||||
* ```ts
|
||||
* @DeepLink({
|
||||
* name: 'list'
|
||||
* })
|
||||
* export class ListPage {
|
||||
* constructor(public navCtrl: NavController) {}
|
||||
*
|
||||
* pushPage(detailInfo) {
|
||||
* // Push an `id` to the `'detail-page'`
|
||||
* this.navCtrl.push('detail-page', {
|
||||
* 'id': detailInfo.id
|
||||
* })
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If the value of `detailInfo.id` is `12`, for example, the URL would end up looking like this:
|
||||
*
|
||||
* ```
|
||||
* http://localhost:8101/#/list/detail/12
|
||||
* ```
|
||||
*
|
||||
* Since this `id` will be used to pull in the data of the specific detail page, it's Important
|
||||
* that the `id` is unique.
|
||||
*
|
||||
* Note: Even though the `name` is `detail-page`, the `segment` uses `detail/:id`, and the URL
|
||||
* will use the `segment`.
|
||||
*
|
||||
*
|
||||
* ### Default History
|
||||
*
|
||||
* While pages can be navigated to anywhere and loaded at any time, what happens when an app is launched from a deeplink while cold or suspended?
|
||||
* Pages can be navigated to using deep links from anywhere in the app, but sometimes the app is
|
||||
* launched from a URL and the page needs to have the same history as if it were navigated to.
|
||||
*
|
||||
* By default, the page would be navigated to in the root NavController, but often the history stack is a UX design issue that you'll
|
||||
* want to tweak as you iterate on the UX of your app.
|
||||
* By default, the page would be navigated to as the first page in the stack with no prior history.
|
||||
* A good example is the App Store on iOS. Clicking on a URL to an application in the App Store will
|
||||
* load the details of the application with no back button, as if it were the first page ever viewed.
|
||||
*
|
||||
* An example here is the App Store app on iOS. If you navigate to an app link to the App Store app, the app decides to show
|
||||
* a single page for the app detail, and no back button. In constrast, opening an instagram link shows a back button that
|
||||
* goes back to the profile page of the user. The point is: this back button experience is totally up to you as the designer
|
||||
* of the app experience.
|
||||
* The default history of any page can be set in the `defaultHistory` property. This history will only
|
||||
* be used if the history doesn't already exist, meaning if you navigate to the page the history will
|
||||
* be the pages that were navigated from.
|
||||
*
|
||||
* This is where `defaultHistory` comes in.
|
||||
*
|
||||
* The `defaultHistory` property takes an array of components to create the initial history stack if none exists.
|
||||
* The `defaultHistory` property takes an array of strings. For example, setting the history of the
|
||||
* detail page to the list page where the `name` is `list`:
|
||||
*
|
||||
* ```ts
|
||||
* links: [
|
||||
* { component: HomePage, name: 'Home', segment: 'home' },
|
||||
* { component: DetailPage, name: 'Detail', segment: 'detail/:userId', defaultHistory: [HomePage] }
|
||||
* ]
|
||||
* ```
|
||||
* @DeepLink({
|
||||
* name: 'detail-page',
|
||||
* segment: 'detail/:id',
|
||||
* defaultHistory: ['list']
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* In this example, if the app is launched at `http://localhost:8101/#/detail/my-detail` the displayed page
|
||||
* will be the `'detail-page'` with an id of `my-detail` and it will show a back button that goes back to
|
||||
* the `'list'` page.
|
||||
*
|
||||
* An example of an application with a set history stack is the Instagram application. Opening a link
|
||||
* to an image on Instagram will show the details for that image with a back button to the user's profile
|
||||
* page. There is no "right" way of setting the history for a page, it is up to the application.
|
||||
*
|
||||
* ### Priority
|
||||
*
|
||||
* The `priority` property is only used during preloading. By default, preloading is turned off so setting
|
||||
* this property would do nothing. Preloading eagerly loads all deep links after the application boots
|
||||
* instead of on demand as needed. To enable preloading, set `preloadModules` in the main application module
|
||||
* config to `true`:
|
||||
*
|
||||
* ```ts
|
||||
* @NgModule({
|
||||
* declarations: [
|
||||
* MyApp
|
||||
* ],
|
||||
* imports: [
|
||||
* BrowserModule,
|
||||
* IonicModule.forRoot(MyApp, {
|
||||
* preloadModules: true
|
||||
* }),
|
||||
* HttpModule
|
||||
* ],
|
||||
* bootstrap: [IonicApp],
|
||||
* entryComponents: [
|
||||
* MyApp
|
||||
* ]
|
||||
* })
|
||||
* export class AppModule { }
|
||||
* ```
|
||||
*
|
||||
* If preloading is turned on, it will load the modules based on the value of `priority`. The following
|
||||
* values are possible for `priority`: `"high"`, `"low"`, and `"off"`. When there is no `priority`, it
|
||||
* will be set to `"low"`.
|
||||
*
|
||||
* All deep links with their priority set to `"high"` will be loaded first. Upon completion of loading the
|
||||
* `"high"` priority modules, all deep links with a priority of `"low"` (or no priority) will be loaded. If
|
||||
* the priority is set to `"off"` the link will not be preloaded. Setting the `priority` is as simple as
|
||||
* passing it to the `@DeepLink` decorator:
|
||||
*
|
||||
* ```ts
|
||||
* @DeepLink({
|
||||
* name: 'my-page',
|
||||
* priority: 'high'
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* We recommend setting the `priority` to `"high"` on the pages that will be viewed first when launching
|
||||
* the application.
|
||||
*
|
||||
* In this example above, if we launch the app at myapp.com/detail/4, then the user will see the DetailPage and then the back button will
|
||||
* go to the HomePage.
|
||||
*/
|
||||
export class DeepLinker {
|
||||
|
||||
|
Reference in New Issue
Block a user