mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
feat(route): adds route-link
This commit is contained in:
21
packages/core/src/components.d.ts
vendored
21
packages/core/src/components.d.ts
vendored
@ -2546,31 +2546,30 @@ declare global {
|
||||
|
||||
|
||||
import {
|
||||
RouteLink as IonRouteLink
|
||||
RouteLink as IonAnchor
|
||||
} from './components/route-link/route-link';
|
||||
|
||||
declare global {
|
||||
interface HTMLIonRouteLinkElement extends IonRouteLink, HTMLStencilElement {
|
||||
interface HTMLIonAnchorElement extends IonAnchor, HTMLStencilElement {
|
||||
}
|
||||
var HTMLIonRouteLinkElement: {
|
||||
prototype: HTMLIonRouteLinkElement;
|
||||
new (): HTMLIonRouteLinkElement;
|
||||
var HTMLIonAnchorElement: {
|
||||
prototype: HTMLIonAnchorElement;
|
||||
new (): HTMLIonAnchorElement;
|
||||
};
|
||||
interface HTMLElementTagNameMap {
|
||||
"ion-route-link": HTMLIonRouteLinkElement;
|
||||
"ion-anchor": HTMLIonAnchorElement;
|
||||
}
|
||||
interface ElementTagNameMap {
|
||||
"ion-route-link": HTMLIonRouteLinkElement;
|
||||
"ion-anchor": HTMLIonAnchorElement;
|
||||
}
|
||||
namespace JSX {
|
||||
interface IntrinsicElements {
|
||||
"ion-route-link": JSXElements.IonRouteLinkAttributes;
|
||||
"ion-anchor": JSXElements.IonAnchorAttributes;
|
||||
}
|
||||
}
|
||||
namespace JSXElements {
|
||||
export interface IonRouteLinkAttributes extends HTMLAttributes {
|
||||
router?: any;
|
||||
url?: string;
|
||||
export interface IonAnchorAttributes extends HTMLAttributes {
|
||||
href?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
|
||||
import { CssClassMap } from '../../index';
|
||||
import { BlurEvent, FocusEvent } from '../../utils/input-interfaces';
|
||||
import { getButtonClassMap, getElementClassMap } from '../../utils/theme';
|
||||
import { getButtonClassMap, getElementClassMap, openURL } from '../../utils/theme';
|
||||
|
||||
|
||||
@Component({
|
||||
@ -133,16 +133,16 @@ export class Button {
|
||||
|
||||
const attrs = (TagType === 'button')
|
||||
? { type: this.type }
|
||||
: {};
|
||||
: { href: this.href };
|
||||
|
||||
return (
|
||||
<TagType
|
||||
{...attrs}
|
||||
class={buttonClasses}
|
||||
disabled={this.disabled}
|
||||
href={this.href}
|
||||
onFocus={this.onFocus.bind(this)}
|
||||
onKeyUp={this.onKeyUp.bind(this)}
|
||||
onClick={(ev) => openURL(this.href, ev)}
|
||||
onBlur={this.onBlur.bind(this)}>
|
||||
<span class='button-inner'>
|
||||
<slot name='icon-only'></slot>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Component, Element, Listen, Prop, State } from '@stencil/core';
|
||||
import { createThemedClasses, getElementClassMap } from '../../utils/theme';
|
||||
import { createThemedClasses, getElementClassMap, openURL } from '../../utils/theme';
|
||||
import { CssClassMap } from '../../index';
|
||||
|
||||
|
||||
@ -104,10 +104,10 @@ export class Item {
|
||||
|
||||
const clickable = !!(this.href || this.onclick || this.tappable);
|
||||
|
||||
let TagType = 'div';
|
||||
if (clickable) {
|
||||
TagType = this.href ? 'a' : 'button';
|
||||
}
|
||||
const TagType = clickable
|
||||
? this.href ? 'a' : 'button'
|
||||
: 'div';
|
||||
|
||||
const attrs = (TagType === 'button')
|
||||
? {type: 'button'}
|
||||
: {href: this.href};
|
||||
@ -125,7 +125,10 @@ export class Item {
|
||||
this.hasStyleChange = false;
|
||||
|
||||
return (
|
||||
<TagType class={themedClasses} {...attrs}>
|
||||
<TagType
|
||||
{...attrs}
|
||||
class={themedClasses}
|
||||
onClick={(ev) => openURL(this.href, ev)}>
|
||||
<slot name='start'></slot>
|
||||
<div class='item-inner'>
|
||||
<div class='input-wrapper'>
|
||||
|
@ -7,24 +7,14 @@
|
||||
|
||||
## Properties
|
||||
|
||||
#### router
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### url
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
#### router
|
||||
|
||||
any
|
||||
|
||||
|
||||
#### url
|
||||
#### href
|
||||
|
||||
string
|
||||
|
||||
|
@ -1,12 +1,17 @@
|
||||
import { Component, Prop } from '@stencil/core';
|
||||
import { openURL } from '../../utils/theme';
|
||||
|
||||
|
||||
@Component({
|
||||
tag: 'ion-route-link'
|
||||
tag: 'ion-anchor'
|
||||
})
|
||||
export class RouteLink {
|
||||
@Prop() url: string;
|
||||
|
||||
// The instance of the router
|
||||
@Prop() router: any;
|
||||
@Prop() href: string;
|
||||
|
||||
render() {
|
||||
return <a
|
||||
href={this.href}
|
||||
onClick={(ev) => openURL(this.href, ev)}><slot/></a>;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ string
|
||||
boolean
|
||||
|
||||
|
||||
## Methods
|
||||
|
||||
#### pushURL()
|
||||
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component, Element, Listen, Prop } from '@stencil/core';
|
||||
import { Component, Element, Listen, Method, Prop } from '@stencil/core';
|
||||
import { Config, DomController } from '../../index';
|
||||
import { flattenRouterTree, readRoutes } from './utils/parser';
|
||||
import { readNavState, writeNavState } from './utils/dom';
|
||||
import { chainToPath, readPath, writePath } from './utils/path';
|
||||
import { chainToPath, parsePath, readPath, writePath } from './utils/path';
|
||||
import { RouteChain } from './utils/interfaces';
|
||||
import { routerIDsToChain, routerPathToChain } from './utils/matching';
|
||||
|
||||
@ -42,10 +42,7 @@ export class Router {
|
||||
this.state++;
|
||||
window.history.replaceState(this.state, document.title, document.location.href);
|
||||
}
|
||||
if (!this.busy) {
|
||||
console.debug('[OUT] hash changed -> write nav state');
|
||||
this.writeNavStateRoot();
|
||||
}
|
||||
this.writeNavStateRoot();
|
||||
}
|
||||
|
||||
@Listen('body:ionNavChanged')
|
||||
@ -63,21 +60,34 @@ export class Router {
|
||||
}
|
||||
|
||||
const isPop = ev.detail.isPop === true;
|
||||
this.writePath(chain, isPop);
|
||||
const path = chainToPath(chain);
|
||||
this.writePath(path, isPop);
|
||||
}
|
||||
|
||||
@Method()
|
||||
pushURL(url: string) {
|
||||
this.writePath(parsePath(url), false);
|
||||
return this.writeNavStateRoot();
|
||||
}
|
||||
|
||||
private writeNavStateRoot(): Promise<any> {
|
||||
const node = document.querySelector('ion-app');
|
||||
const currentPath = this.readPath();
|
||||
const direction = window.history.state >= this.state ? 1 : -1;
|
||||
if (currentPath) {
|
||||
const {chain} = routerPathToChain(currentPath, this.routes);
|
||||
return this.writeNavState(node, chain, direction);
|
||||
if (this.busy) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.resolve();
|
||||
const currentPath = this.readPath();
|
||||
if (!currentPath) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
const direction = window.history.state >= this.state ? 1 : -1;
|
||||
const node = document.querySelector('ion-app');
|
||||
const {chain} = routerPathToChain(currentPath, this.routes);
|
||||
return this.writeNavState(node, chain, direction);
|
||||
}
|
||||
|
||||
private writeNavState(node: any, chain: RouteChain, direction: number): Promise<any> {
|
||||
if (this.busy) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
this.busy = true;
|
||||
return writeNavState(node, chain, 0, direction)
|
||||
.catch(err => console.error(err))
|
||||
@ -89,8 +99,7 @@ export class Router {
|
||||
return readNavState(root);
|
||||
}
|
||||
|
||||
private writePath(chain: RouteChain, isPop: boolean) {
|
||||
const path = chainToPath(chain);
|
||||
private writePath(path: string[], isPop: boolean) {
|
||||
this.state = writePath(window.history, this.base, this.useHash, path, isPop, this.state);
|
||||
}
|
||||
|
||||
|
@ -62,3 +62,14 @@ export function getClassMap(classes: string | undefined): CssClassMap {
|
||||
return map;
|
||||
}
|
||||
|
||||
export function openURL(url: string, ev: Event) {
|
||||
if (url && url.indexOf('://') === -1) {
|
||||
const router = document.querySelector('ion-router');
|
||||
if (router) {
|
||||
ev && ev.preventDefault();
|
||||
return router.componentOnReady().then(() => router.pushURL(url));
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user