ตัวอย่างการสร้าง Single Page Application ด้วย Now.js Framework
ตัวอย่างนี้แสดงการสร้าง SPA:
- Client-Side Routing - เปลี่ยนหน้าโดยไม่ reload
- History Mode - URL สะอาด ไม่มี hash (#)
- Template Loading - โหลด template จากไฟล์แยก
- Navigation - data-route สำหรับ link
- Responsive Menu - เมนูที่รองรับ mobile
- Page Transitions - animation เมื่อเปลี่ยนหน้า
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="now.core.min.css">
</head>
<body>
<!-- Navigation -->
<nav>
<a href="/" data-route="/">Home</a>
<a href="/about" data-route="/about">About</a>
<a href="/portfolio" data-route="/portfolio">Portfolio</a>
<a href="/contact" data-route="/contact">Contact</a>
</nav>
<!-- Router injects content here -->
<main id="main" role="main"></main>
<!-- Footer (stays static) -->
<footer>...</footer>
<script src="now.core.min.js"></script>
<script src="main.js"></script>
</body>
</html>await Now.init({
environment: 'production',
paths: {
templates: './templates'
},
router: {
enabled: true,
mode: 'history', // 'hash' or 'history'
base: '/examples/spa/',
autoDetectBase: true,
routes: {
'/': {
template: 'index.html'
},
'/about': {
template: 'about.html'
},
'/portfolio': {
template: 'portfolio.html'
},
'/contact': {
template: 'contact.html'
}
}
}
});สร้างไฟล์ใน templates/ folder:
templates/index.html:
<div class="hero">
<h1>Welcome to My SPA</h1>
<p>Built with Now.js Framework</p>
<a href="/about" data-route="/about" class="btn">Learn More</a>
</div>templates/about.html:
<section class="page">
<h1>About Me</h1>
<p>This is the about page content.</p>
</section>router: {
enabled: true, // เปิด/ปิด router
mode: 'history', // 'history' (clean URLs) หรือ 'hash' (#/path)
base: '/', // Base path ของ application
autoDetectBase: true, // ตรวจจับ base path อัตโนมัติ
routes: {
'/path': {
template: 'file.html', // Template file
title: 'Page Title', // ชื่อหน้า (optional)
data: {} // ข้อมูลที่ส่งให้ template (optional)
}
}
}ใช้ data-route แทน JavaScript onclick:
<!-- Navigation links -->
<a href="/about" data-route="/about">About</a>
<a href="/contact" data-route="/contact">Contact</a>
<!-- Buttons -->
<button data-route="/portfolio">View Portfolio</button>// Navigate to route
Now.router.navigate('/about');
// Navigate with replace (no history entry)
Now.router.navigate('/about', { replace: true });
// Go back
Now.router.back();
// Go forward
Now.router.forward();Router เพิ่ม class active ให้ link ที่ตรงกับ route ปัจจุบัน:
.nav-link {
color: var(--color-text);
}
.nav-link.active {
color: var(--color-primary);
font-weight: bold;
}เพิ่ม animation เมื่อเปลี่ยนหน้า:
/* Fade in animation */
.fade-in {
animation: fadeIn 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Slide animations */
.slide-in-left {
animation: slideInLeft 0.4s ease-out;
}
@keyframes slideInLeft {
from { opacity: 0; transform: translateX(-20px); }
to { opacity: 1; transform: translateX(0); }
}ใช้ใน template:
<div class="hero fade-in">
<h1>Welcome</h1>
</div>
<div class="card slide-in-left">
<h3>Feature 1</h3>
</div>สำหรับ history mode ต้อง config server ให้ redirect ทุก path ไป index.html:
RewriteEngine On
RewriteBase /examples/spa/
# If not a file or directory, redirect to index.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.html [L,QSA]location /examples/spa/ {
try_files $uri $uri/ /examples/spa/index.html;
}ถ้าไม่สามารถ config server ได้ ใช้ hash mode:
router: {
mode: 'hash' // URLs จะเป็น /#/about, /#/contact
}// Listen to route changes
document.addEventListener('router:navigate', (e) => {
console.log('Navigated to:', e.detail.path);
});
// Before route change
document.addEventListener('router:beforeNavigate', (e) => {
console.log('About to navigate:', e.detail.path);
// e.preventDefault(); // Cancel navigation
});
// After route loaded
document.addEventListener('router:afterNavigate', (e) => {
console.log('Route rendered:', e.detail.path);
});spa/
├── index.html # Main HTML (shell)
├── main.js # Router configuration
├── styles.css # Styles
├── .htaccess # Apache redirect config
└── templates/ # Page templates
├── index.html # Home page
├── about.html # About page
├── portfolio.html # Portfolio page
└── contact.html # Contact page
<!-- Main index.html -->
<head>
<title>My SPA - Now.js</title>
<meta name="description" content="Description for SEO">
<meta property="og:title" content="My SPA">
<meta property="og:description" content="Built with Now.js">
</head><nav class="topmenu responsive-menu" data-component="menu">
<ul>
<li><a href="/" data-route="/">Home</a></li>
<li><a href="/about" data-route="/about">About</a></li>
</ul>
</nav>
<!-- Mobile toggle button -->
<button class="menu-toggle topmenu-toggle">
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
<span class="toggle-bar"></span>
</button>Now.js Framework- Core framework with Router- No additional routing library required