🎯 Рекомендуемые коллекции
Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать
Примеры Ionic
Примеры гибридного фреймворка мобильных приложений Ionic, включая компоненты, навигацию, управление состоянием и нативную интеграцию
💻 Hello World на Ionic typescript
🟢 simple
Базовые примеры приложений Ionic с компонентами, страницами, маршрутизацией и фундаментальными концепциями для Angular, React и Vue
// Ionic Hello World Examples
// ============ IONIC ANGULAR EXAMPLES ============
// 1. Basic Ionic Angular App Structure
// src/app/app.component.ts
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss'],
})
export class AppComponent {
constructor(private platform: Platform) {
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
console.log('Platform ready');
});
}
}
// src/app/app.component.html
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>
// 2. Basic Hello World Page
// src/app/pages/hello-world/hello-world.page.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-hello-world',
templateUrl: './hello-world.page.html',
styleUrls: ['./hello-world.page.scss'],
})
export class HelloWorldPage {
title = 'Hello Ionic!';
subtitle = 'Welcome to the hybrid mobile development framework';
constructor() {}
showMessage() {
console.log('Hello from Ionic!');
}
}
// src/app/pages/hello-world/hello-world.page.html
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>Hello World</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">{{ title }}</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
<h1>{{ title }}</h1>
<p>{{ subtitle }}</p>
<ion-button expand="block" (click)="showMessage()">
<ion-icon slot="start" name="hand-left-outline"></ion-icon>
Say Hello
</ion-button>
</div>
</ion-content>
// src/app/pages/hello-world/hello-world.page.scss
ion-content {
--background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
h1 {
color: #fff;
text-align: center;
margin-bottom: 20px;
}
p {
color: rgba(255, 255, 255, 0.8);
text-align: center;
margin-bottom: 30px;
}
ion-button {
margin-top: 20px;
}
// 3. Ionic Angular Counter Component
// src/app/components/counter/counter.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
styleUrls: ['./counter.component.scss'],
})
export class CounterComponent {
@Input() initialValue: number = 0;
count: number = 0;
constructor() {
this.count = this.initialValue;
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
reset() {
this.count = this.initialValue;
}
}
// src/app/components/counter/counter.component.html
<div class="counter-container">
<h2>Counter: {{ count }}</h2>
<div class="button-group">
<ion-button color="danger" (click)="decrement()">
<ion-icon name="remove"></ion-icon>
</ion-button>
<ion-button color="warning" (click)="reset()">
<ion-icon name="refresh"></ion-icon>
</ion-button>
<ion-button color="success" (click)="increment()">
<ion-icon name="add"></ion-icon>
</ion-button>
</div>
</div>
// src/app/components/counter/counter.component.scss
.counter-container {
text-align: center;
padding: 20px;
h2 {
color: #fff;
margin-bottom: 20px;
}
.button-group {
display: flex;
justify-content: center;
gap: 10px;
}
}
// 4. Interactive User Profile
// src/app/pages/profile/profile.page.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-profile',
templateUrl: './profile.page.html',
styleUrls: ['./profile.page.scss'],
})
export class ProfilePage {
user = {
name: 'John Doe',
email: '[email protected]',
age: 28,
bio: 'Mobile app developer passionate about hybrid apps',
avatar: 'https://via.placeholder.com/150'
};
isEditing = false;
editUser = { ...this.user };
constructor() {}
toggleEdit() {
this.isEditing = !this.isEditing;
if (!this.isEditing) {
this.editUser = { ...this.user };
}
}
saveProfile() {
this.user = { ...this.editUser };
this.isEditing = false;
}
cancelEdit() {
this.editUser = { ...this.user };
this.isEditing = false;
}
}
// src/app/pages/profile/profile.page.html
<ion-header [translucent]="true">
<ion-toolbar>
<ion-buttons slot="end">
<ion-button (click)="toggleEdit()">
<ion-icon [name]="isEditing ? 'save' : 'create'"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>User Profile</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<div class="ion-padding">
<!-- Avatar Section -->
<div class="avatar-section">
<ion-avatar>
<img [src]="user.avatar" [alt]="user.name">
</ion-avatar>
<ion-chip color="primary">
<ion-icon name="star"></ion-icon>
<ion-label>Pro User</ion-label>
</ion-chip>
</div>
<!-- User Information -->
<ion-card>
<ion-card-header>
<ion-card-title>User Information</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-list>
<ion-item>
<ion-label position="stacked">Name</ion-label>
<ion-input
*ngIf="isEditing"
[(ngModel)]="editUser.name"
type="text">
</ion-input>
<h3 *ngIf="!isEditing">{{ user.name }}</h3>
</ion-item>
<ion-item>
<ion-label position="stacked">Email</ion-label>
<ion-input
*ngIf="isEditing"
[(ngModel)]="editUser.email"
type="email">
</ion-input>
<p *ngIf="!isEditing">{{ user.email }}</p>
</ion-item>
<ion-item>
<ion-label position="stacked">Age</ion-label>
<ion-input
*ngIf="isEditing"
[(ngModel)]="editUser.age"
type="number">
</ion-input>
<p *ngIf="!isEditing">{{ user.age }} years old</p>
</ion-item>
</ion-list>
</ion-card-content>
</ion-card>
<!-- Bio Section -->
<ion-card>
<ion-card-header>
<ion-card-title>About</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-textarea
*ngIf="isEditing"
[(ngModel)]="editUser.bio"
placeholder="Tell us about yourself..."
rows="4">
</ion-textarea>
<p *ngIf="!isEditing">{{ user.bio }}</p>
</ion-card-content>
</ion-card>
<!-- Action Buttons -->
<div class="action-buttons" *ngIf="isEditing">
<ion-button expand="block" color="success" (click)="saveProfile()">
<ion-icon name="checkmark" slot="start"></ion-icon>
Save Changes
</ion-button>
<ion-button expand="block" fill="outline" (click)="cancelEdit()">
<ion-icon name="close" slot="start"></ion-icon>
Cancel
</ion-button>
</div>
</div>
</ion-content>
// ============ IONIC REACT EXAMPLES ============
// 1. Basic Ionic React App
// src/App.tsx
import React from 'react';
import { IonApp, IonRouterOutlet } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { Route, Redirect } from 'react-router-dom';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';
/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';
import HelloPage from './pages/HelloPage';
import CounterPage from './pages/CounterPage';
import ProfilePage from './pages/ProfilePage';
const App: React.FC = () => (
<IonApp>
<IonReactRouter>
<IonRouterOutlet>
<Route exact path="/hello" component={HelloPage} />
<Route exact path="/counter" component={CounterPage} />
<Route exact path="/profile" component={ProfilePage} />
<Route exact path="/">
<Redirect to="/hello" />
</Route>
</IonRouterOutlet>
</IonReactRouter>
</IonApp>
);
export default App;
// 2. Hello World Page with React
// src/pages/HelloPage.tsx
import React, { useState } from 'react';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonButton,
IonIcon,
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonItem,
IonLabel,
IonBadge,
IonChip,
} from '@ionic/react';
import { heart, star, thumbsUp } from 'ionicons/icons';
const HelloPage: React.FC = () => {
const [likeCount, setLikeCount] = useState(0);
const [isLiked, setIsLiked] = useState(false);
const handleLike = () => {
setLikeCount(prev => prev + (isLiked ? -1 : 1));
setIsLiked(!isLiked);
};
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Hello Ionic React</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Welcome</IonTitle>
</IonToolbar>
</IonHeader>
<div className="ion-padding">
<div className="welcome-section">
<h1>Hello, Ionic!</h1>
<p>Welcome to the hybrid mobile framework with React</p>
<IonChip color="primary">
<IonIcon icon={star} />
<IonLabel>React</IonLabel>
</IonChip>
<IonChip color="secondary">
<IonIcon icon={heart} />
<IonLabel>TypeScript</IonLabel>
</IonChip>
</div>
<IonCard>
<IonCardHeader>
<IonCardTitle>Interactive Demo</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<IonItem>
<IonLabel>
<h3>Like this page!</h3>
<p>Click the button to show your appreciation</p>
</IonLabel>
<IonBadge color="primary">{likeCount}</IonBadge>
</IonItem>
<div className="button-container">
<IonButton
expand="block"
fill={isLiked ? "solid" : "outline"}
color={isLiked ? "danger" : "primary"}
onClick={handleLike}
>
<IonIcon icon={thumbsUp} slot="start" />
{isLiked ? 'Liked!' : 'Like'}
</IonButton>
</div>
</IonCardContent>
</IonCard>
<IonCard>
<IonCardHeader>
<IonCardTitle>Features</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<IonItem>
<IonIcon icon={heart} color="danger" slot="start" />
<IonLabel>Cross-platform development</IonLabel>
</IonItem>
<IonItem>
<IonIcon icon={star} color="warning" slot="start" />
<IonLabel>Beautiful UI components</IonLabel>
</IonItem>
<IonItem>
<IonIcon icon={thumbsUp} color="success" slot="start" />
<IonLabel>Native app performance</IonLabel>
</IonItem>
</IonCardContent>
</IonCard>
</div>
</IonContent>
</IonPage>
);
};
export default HelloPage;
// 3. Counter Component with React Hooks
// src/pages/CounterPage.tsx
import React, { useState, useEffect } from 'react';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonButton,
IonIcon,
IonCard,
IonCardContent,
IonCardHeader,
IonCardTitle,
IonItem,
IonLabel,
IonGrid,
IonRow,
IonCol,
IonRange,
IonProgressBar,
IonChip,
} from '@ionic/react';
import { add, remove, refresh, stats } from 'ionicons/icons';
interface CounterHistory {
id: number;
action: string;
value: number;
timestamp: Date;
}
const CounterPage: React.FC = () => {
const [count, setCount] = useState(0);
const [step, setStep] = useState(1);
const [history, setHistory] = useState<CounterHistory[]>([]);
const [maxValue, setMaxValue] = useState(100);
useEffect(() => {
// Calculate progress
const progress = (Math.abs(count) / maxValue) * 100;
console.log(`Progress: ${progress}%`);
}, [count, maxValue]);
const addToHistory = (action: string, value: number) => {
const newEntry: CounterHistory = {
id: Date.now(),
action,
value,
timestamp: new Date(),
};
setHistory(prev => [newEntry, ...prev].slice(0, 10));
};
const increment = () => {
const newValue = count + step;
setCount(newValue);
addToHistory('increment', newValue);
};
const decrement = () => {
const newValue = count - step;
setCount(newValue);
addToHistory('decrement', newValue);
};
const reset = () => {
setCount(0);
addToHistory('reset', 0);
};
const getCountColor = () => {
if (count > 0) return 'success';
if (count < 0) return 'danger';
return 'primary';
};
const getProgress = () => {
const progress = (Math.abs(count) / maxValue) * 100;
return Math.min(progress, 100);
};
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Counter</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Interactive Counter</IonTitle>
</IonToolbar>
</IonHeader>
<div className="ion-padding">
<IonCard>
<IonCardHeader>
<IonCardTitle>Counter Value</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<div className="counter-display">
<IonChip color={getCountColor()}>
<IonIcon icon={stats} />
<IonLabel>{count}</IonLabel>
</IonChip>
</div>
<IonProgressBar
value={getProgress() / 100}
color={getCountColor()}
className="ion-margin-top"
/>
<p className="ion-text-center">
Progress: {getProgress().toFixed(1)}%
</p>
</IonCardContent>
</IonCard>
<IonCard>
<IonCardHeader>
<IonCardTitle>Controls</IonCardTitle>
</IonCardHeader>
<IonCardContent>
<IonItem>
<IonLabel position="stacked">Step Size</IonLabel>
<IonRange
min={1}
max={10}
value={step}
onIonChange={e => setStep(parseInt(e.detail.value as string))}
snaps
ticks
>
<IonLabel slot="start">{step}</IonLabel>
<IonLabel slot="end">{step}</IonLabel>
</IonRange>
</IonItem>
<IonItem>
<IonLabel position="stacked">Max Value</IonLabel>
<IonRange
min={50}
max={200}
step={10}
value={maxValue}
onIonChange={e => setMaxValue(parseInt(e.detail.value as string))}
snaps
>
<IonLabel slot="start">{maxValue}</IonLabel>
<IonLabel slot="end">{maxValue}</IonLabel>
</IonRange>
</IonItem>
<IonGrid>
<IonRow>
<IonCol>
<IonButton
expand="block"
color="danger"
onClick={decrement}
disabled={count <= -maxValue}
>
<IonIcon icon={remove} slot="start" />
Decrease
</IonButton>
</IonCol>
<IonCol>
<IonButton
expand="block"
color="warning"
onClick={reset}
>
<IonIcon icon={refresh} slot="start" />
Reset
</IonButton>
</IonCol>
<IonCol>
<IonButton
expand="block"
color="success"
onClick={increment}
disabled={count >= maxValue}
>
<IonIcon icon={add} slot="start" />
Increase
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</IonCardContent>
</IonCard>
<IonCard>
<IonCardHeader>
<IonCardTitle>History</IonCardTitle>
</IonCardHeader>
<IonCardContent>
{history.length > 0 ? (
history.map(item => (
<IonItem key={item.id}>
<IonLabel>
<h3>{item.action}</h3>
<p>New value: {item.value}</p>
</IonLabel>
<IonLabel slot="end">
{item.timestamp.toLocaleTimeString()}
</IonLabel>
</IonItem>
))
) : (
<p className="ion-text-center ion-color-medium">
No actions yet. Start counting!
</p>
)}
</IonCardContent>
</IonCard>
</div>
</IonContent>
</IonPage>
);
};
export default CounterPage;
// ============ IONIC VUE EXAMPLES ============
// 1. Basic Ionic Vue App
// src/main.ts
import { createApp } from 'vue';
import { IonicVue } from '@ionic/vue';
import router from './router';
import App from './App.vue';
import '@ionic/vue/css/core.css';
import '@ionic/vue/css/normalize.css';
import '@ionic/vue/css/structure.css';
import '@ionic/vue/css/typography.css';
import '@ionic/vue/css/padding.css';
import '@ionic/vue/css/float-elements.css';
import '@ionic/vue/css/text-alignment.css';
import '@ionic/vue/css/text-transformation.css';
import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';
const app = createApp(App).use(IonicVue).use(router);
app.mount('#app');
// 2. Hello World Page with Vue 3 Composition API
// src/views/HelloWorld.vue
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-title>Hello Ionic Vue</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">{{ title }}</ion-title>
</ion-toolbar>
</ion-header>
<div class="ion-padding">
<div class="welcome-container">
<h1>{{ title }}</h1>
<p>{{ subtitle }}</p>
<ion-chip color="primary">
<ion-icon :icon="starOutline" />
<ion-label>Vue 3</ion-label>
</ion-chip>
<ion-chip color="secondary">
<ion-icon :icon="codeSlash" />
<ion-label>TypeScript</ion-label>
</ion-chip>
<ion-chip color="tertiary">
<ion-icon :icon="phonePortrait" />
<ion-label>Mobile</ion-label>
</ion-chip>
</div>
<ion-card>
<ion-card-header>
<ion-card-title>Interactive Features</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-list>
<ion-item>
<ion-thumbnail slot="start">
<img src="https://via.placeholder.com/50" alt="Feature 1" />
</ion-thumbnail>
<ion-label>
<h3>Cross-platform</h3>
<p>Build once, deploy everywhere</p>
</ion-label>
</ion-item>
<ion-item>
<ion-thumbnail slot="start">
<img src="https://via.placeholder.com/50" alt="Feature 2" />
</ion-thumbnail>
<ion-label>
<h3>Native Performance</h3>
<p>Fast, smooth user experience</p>
</Ion-label>
</ion-item>
</ion-list>
<div class="button-group">
<ion-button
expand="block"
color="primary"
@click="showAlert"
>
<ion-icon :icon="heart" slot="start" />
Show Alert
</ion-button>
<ion-button
expand="block"
fill="outline"
color="secondary"
@click="navigateToCounter"
>
<ion-icon :icon="trendingUp" slot="start" />
Try Counter
</ion-button>
</div>
</ion-card-content>
</ion-card>
</div>
</ion-content>
</ion-page>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
alertController,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonChip,
IonLabel,
IonIcon,
IonCard,
IonCardHeader,
IonCardTitle,
IonCardContent,
IonList,
IonItem,
IonThumbnail,
IonButton
} from '@ionic/vue';
import { useRouter } from 'vue-router';
import {
starOutline,
codeSlash,
phonePortrait,
heart,
trendingUp
} from 'ionicons/icons';
const router = useRouter();
const title = ref('Hello, Ionic!');
const subtitle = ref('Welcome to the hybrid mobile development framework with Vue 3');
const showAlert = async () => {
const alert = await alertController.create({
header: 'Welcome!',
message: 'This is an Ionic alert dialog in Vue 3!',
buttons: ['OK'],
});
await alert.present();
};
const navigateToCounter = () => {
router.push('/counter');
};
</script>
<style scoped>
.welcome-container {
text-align: center;
margin-bottom: 30px;
}
.welcome-container h1 {
color: #fff;
margin-bottom: 10px;
}
.welcome-container p {
color: rgba(255, 255, 255, 0.8);
margin-bottom: 20px;
}
.button-group {
margin-top: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
ion-content {
--background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
</style>
// 3. Reactive Counter with Vue Composition API
// src/views/Counter.vue
<template>
<ion-page>
<ion-header :translucent="true">
<ion-toolbar>
<ion-title>Counter</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<div class="ion-padding">
<ion-card>
<ion-card-header>
<ion-card-title>Reactive Counter</ion-card-title>
</ion-card-header>
<ion-card-content>
<div class="counter-display">
<ion-chip :color="counterColor">
<ion-icon :icon="stats" />
<ion-label>{{ count }}</ion-label>
</ion-chip>
</div>
<ion-progress-bar
:value="progress"
:color="counterColor"
class="ion-margin-top"
/>
<p class="ion-text-center">
{{ progressText }}
</p>
</ion-card-content>
</ion-card>
<ion-card>
<ion-card-header>
<ion-card-title>Statistics</ion-cardTitle>
</ion-card-header>
<ion-card-content>
<ion-grid>
<ion-row>
<ion-col>
<div class="stat-item">
<h2>{{ incrementCount }}</h2>
<p>Increments</p>
</div>
</ion-col>
<ion-col>
<div class="stat-item">
<h2>{{ decrementCount }}</h2>
<p>Decrements</p>
</div>
</ion-col>
<ion-col>
<div class="stat-item">
<h2>{{ resetCount }}</h2>
<p>Resets</p>
</div>
</ion-col>
</ion-row>
</ion-grid>
</ion-card-content>
</ion-card>
<ion-card>
<ion-card-header>
<ion-cardTitle>Controls</ion-cardTitle>
</ion-cardHeader>
<ion-cardContent>
<ion-range
v-model="stepSize"
:min="1"
:max="10"
:step="1"
:snaps="true"
:ticks="true"
>
<ion-label slot="start">Step: {{ stepSize }}</ion-label>
<ion-label slot="end">{{ stepSize }}</ion-label>
</ion-range>
<ion-grid class="ion-margin-top">
<ion-row>
<ion-col>
<ion-button
expand="block"
color="danger"
@click="decrement"
:disabled="count <= -maxValue"
>
<ion-icon :icon="remove" slot="start" />
Decrease
</ion-button>
</ion-col>
<ion-col>
<ion-button
expand="block"
color="warning"
@click="reset"
>
<ion-icon :icon="refresh" slot="start" />
Reset
</ion-button>
</ion-col>
<ion-col>
<ion-button
expand="block"
color="success"
@click="increment"
:disabled="count >= maxValue"
>
<ion-icon :icon="add" slot="start" />
Increase
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
</ion-cardContent>
</ion-card>
</div>
</ion-content>
</ion-page>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonCard,
IonCardHeader,
IonCardTitle,
IonCardContent,
IonChip,
IonLabel,
IonIcon,
IonProgressBar,
IonGrid,
IonRow,
IonCol,
IonRange,
IonButton
} from '@ionic/vue';
import {
stats,
add,
remove,
refresh
} from 'ionicons/icons';
// Reactive state
const count = ref(0);
const stepSize = ref(1);
const maxValue = ref(100);
// Statistics
const incrementCount = ref(0);
const decrementCount = ref(0);
const resetCount = ref(0);
// Computed properties
const counterColor = computed(() => {
if (count.value > 0) return 'success';
if (count.value < 0) return 'danger';
return 'primary';
});
const progress = computed(() => {
const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
return Math.min(progressValue / 100, 1);
});
const progressText = computed(() => {
const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
return `Progress: ${progressValue.toFixed(1)}%`;
});
// Methods
const increment = () => {
if (count.value < maxValue.value) {
count.value += stepSize.value;
incrementCount.value++;
}
};
const decrement = () => {
if (count.value > -maxValue.value) {
count.value -= stepSize.value;
decrementCount.value++;
}
};
const reset = () => {
count.value = 0;
resetCount.value++;
};
</script>
<style scoped>
.counter-display {
text-align: center;
margin: 20px 0;
}
.stat-item {
text-align: center;
}
.stat-item h2 {
margin: 0;
font-size: 24px;
font-weight: bold;
}
.stat-item p {
margin: 4px 0 0 0;
color: var(--ion-color-medium);
}
</style>
// ============ SHARED TYPES AND INTERFACES ============
// types/interfaces.ts
export interface User {
id: string;
name: string;
email: string;
age: number;
bio: string;
avatar?: string;
}
export interface TodoItem {
id: string;
title: string;
description: string;
completed: boolean;
createdAt: Date;
dueDate?: Date;
priority: 'low' | 'medium' | 'high';
}
export interface CounterState {
count: number;
step: number;
maxValue: number;
history: HistoryEntry[];
}
export interface HistoryEntry {
id: string;
action: 'increment' | 'decrement' | 'reset';
value: number;
timestamp: Date;
}
// ============ ROUTING CONFIGURATION ============
// Angular Routing - app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: 'home',
loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule { }
// React Routing - App.tsx (shown above)
// Vue Router - router/index.ts (shown above)
// ============ MAIN ENTRIES ============
// Use these main functions to run different framework examples:
// For Angular:
// npm run start (in Ionic Angular project)
// For React:
// npm run start (in Ionic React project)
// For Vue:
// npm run dev (in Ionic Vue project)