viewlogic 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +359 -641
- package/dist/viewlogic-router.js +237 -7
- package/dist/viewlogic-router.js.map +2 -2
- package/dist/viewlogic-router.min.js +3 -3
- package/dist/viewlogic-router.min.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# ViewLogic Router
|
|
1
|
+
# ViewLogic Router v1.1.1
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://github.com/hopegiver/viewlogic">
|
|
@@ -12,40 +12,52 @@
|
|
|
12
12
|
</a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
> A revolutionary Vue 3 routing system with
|
|
15
|
+
> A revolutionary Vue 3 routing system with View-Logic separation and Zero Build Development
|
|
16
|
+
|
|
17
|
+
## 🆕 Latest Updates (v1.1.1)
|
|
18
|
+
|
|
19
|
+
- ✨ **Automatic Form Handling** - Revolutionary form submission with `{paramName}` variable parameters
|
|
20
|
+
- 🔄 **Multiple API Support** - Parallel data fetching from multiple APIs with named data storage
|
|
21
|
+
- 🛡️ **Enhanced Validation** - HTML5 + custom function validation with graceful error handling
|
|
22
|
+
- 🚀 **Component Loading Resilience** - Router continues to work even if components fail to load
|
|
23
|
+
- 📝 **Comprehensive Documentation** - Extensive real-world examples and usage patterns
|
|
16
24
|
|
|
17
25
|
## 🎯 Core Philosophy: Simplicity Through Design
|
|
18
26
|
|
|
19
|
-
ViewLogic Router revolutionizes Vue development with two core principles:
|
|
27
|
+
ViewLogic Router revolutionizes Vue development with two fundamental core principles:
|
|
20
28
|
|
|
21
29
|
### 🎭 View-Logic Separation
|
|
22
|
-
|
|
30
|
+
**Complete separation between View (presentation) and Logic (business logic)**. Views are pure HTML templates, logic is pure JavaScript components, making your code more maintainable, testable, and scalable.
|
|
23
31
|
|
|
24
|
-
###
|
|
25
|
-
**
|
|
32
|
+
### 🚀 Zero Build Development
|
|
33
|
+
**Zero build step required in development mode**. Work directly with source files, see changes instantly without any compilation, bundling, or build processes. True real-time development experience.
|
|
26
34
|
|
|
27
|
-
## ✨ Features
|
|
35
|
+
## ✨ Key Features
|
|
28
36
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
37
|
+
- 🚀 **Ultra-Lightweight** - Complete routing system in just 13KB gzipped (48KB minified)
|
|
38
|
+
- 🔄 **Multiple API Support** - Parallel data fetching from multiple APIs with named data storage
|
|
39
|
+
- 📝 **Automatic Form Handling** - Revolutionary form submission with `{paramName}` variable parameters
|
|
40
|
+
- 🛠️ **Built-in Components** - Preloaded UI components including revolutionary DynamicInclude & HtmlInclude
|
|
41
|
+
- 🔗 **Query-Based Parameter System** - Simple query-only parameters (`/users?id=123`) instead of complex path parameters
|
|
31
42
|
- ⚡ **Optimized Production** - Pre-built individual route bundles for lightning-fast production
|
|
32
43
|
- 📁 **Intuitive Structure** - Organized folder structure for views, logic, styles, layouts, and components
|
|
33
|
-
- 🔄 **Hot Development** - See changes instantly without compilation
|
|
34
|
-
- 📦 **Smart Production Build** - Each route becomes an optimized JavaScript bundle
|
|
35
|
-
- 🛠️ **Built-in Components** - Preloaded UI components including revolutionary DynamicInclude & HtmlInclude
|
|
36
|
-
- 🌐 **i18n Ready** - Built-in internationalization support
|
|
37
|
-
- 🔐 **Authentication** - Built-in auth management system
|
|
38
44
|
- 💾 **Smart Caching** - Intelligent route and component caching
|
|
39
|
-
-
|
|
45
|
+
- 🔐 **Authentication** - Built-in auth management system
|
|
46
|
+
- 🌐 **i18n Ready** - Built-in internationalization support
|
|
40
47
|
|
|
41
48
|
## 📦 Installation
|
|
42
49
|
|
|
50
|
+
Create a new ViewLogic project with our complete template:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm create viewlogic my-app
|
|
54
|
+
cd my-app
|
|
55
|
+
# Ready to go! No additional setup needed
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or manually install the router only:
|
|
43
59
|
```bash
|
|
44
60
|
npm install viewlogic
|
|
45
|
-
# or
|
|
46
|
-
yarn add viewlogic
|
|
47
|
-
# or
|
|
48
|
-
pnpm add viewlogic
|
|
49
61
|
```
|
|
50
62
|
|
|
51
63
|
## 🚀 Quick Start
|
|
@@ -71,7 +83,7 @@ pnpm add viewlogic
|
|
|
71
83
|
// Development mode - loads files directly from src/
|
|
72
84
|
ViewLogicRouter({
|
|
73
85
|
environment: 'development',
|
|
74
|
-
})
|
|
86
|
+
});
|
|
75
87
|
</script>
|
|
76
88
|
</body>
|
|
77
89
|
</html>
|
|
@@ -100,7 +112,7 @@ pnpm add viewlogic
|
|
|
100
112
|
environment: 'production',
|
|
101
113
|
useI18n: true,
|
|
102
114
|
logLevel: 'error' // Only log errors
|
|
103
|
-
})
|
|
115
|
+
});
|
|
104
116
|
</script>
|
|
105
117
|
</body>
|
|
106
118
|
</html>
|
|
@@ -248,294 +260,105 @@ const config = {
|
|
|
248
260
|
};
|
|
249
261
|
```
|
|
250
262
|
|
|
251
|
-
## 📖 API
|
|
252
|
-
|
|
253
|
-
### Router Instance Methods
|
|
254
|
-
|
|
255
|
-
```javascript
|
|
256
|
-
// Navigation
|
|
257
|
-
router.navigateTo('routeName', { param: 'value' });
|
|
258
|
-
router.navigateTo({ route: 'products', params: { id: 123 } });
|
|
259
|
-
|
|
260
|
-
// Get current route
|
|
261
|
-
const currentRoute = router.getCurrentRoute();
|
|
262
|
-
|
|
263
|
-
// Unified parameter system - all parameters are query-based
|
|
264
|
-
router.queryManager.setQueryParams({ id: 123, category: 'electronics' });
|
|
265
|
-
const params = router.queryManager.getParams(); // Gets all parameters
|
|
266
|
-
const userId = router.queryManager.getParam('id', 1); // Get specific parameter with default
|
|
267
|
-
router.queryManager.removeQueryParams(['category']);
|
|
263
|
+
## 📖 Complete API Documentation
|
|
268
264
|
|
|
269
|
-
|
|
270
|
-
router.authManager.login(token);
|
|
271
|
-
router.authManager.logout();
|
|
272
|
-
const isAuth = router.authManager.isAuthenticated();
|
|
265
|
+
For comprehensive API documentation including all methods, configuration options, and detailed examples, see:
|
|
273
266
|
|
|
274
|
-
|
|
275
|
-
router.i18nManager.setLanguage('en');
|
|
276
|
-
const t = router.i18nManager.translate('welcome.message');
|
|
267
|
+
**📚 [Complete API Reference →](./docs/index.md)**
|
|
277
268
|
|
|
278
|
-
|
|
279
|
-
router.cacheManager.clearAll();
|
|
280
|
-
|
|
281
|
-
// Cleanup
|
|
282
|
-
router.destroy();
|
|
283
|
-
```
|
|
284
|
-
|
|
285
|
-
### Global Functions Available in Route Components
|
|
286
|
-
|
|
287
|
-
Every route component automatically has access to these global functions:
|
|
269
|
+
### Quick API Overview
|
|
288
270
|
|
|
289
271
|
```javascript
|
|
272
|
+
// Basic router usage
|
|
273
|
+
const router = new ViewLogicRouter({ environment: 'development' });
|
|
274
|
+
router.navigateTo('products', { id: 123, category: 'electronics' });
|
|
275
|
+
const current = router.getCurrentRoute();
|
|
276
|
+
|
|
277
|
+
// In route components - global methods automatically available:
|
|
290
278
|
export default {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// Get all parameters (both route and query parameters)
|
|
299
|
-
const allParams = this.getParams();
|
|
300
|
-
|
|
301
|
-
// Get specific parameter with default value
|
|
302
|
-
const categoryId = this.getParam('categoryId', 1);
|
|
303
|
-
const sortBy = this.getParam('sort', 'name');
|
|
304
|
-
|
|
305
|
-
// Navigation
|
|
306
|
-
this.navigateTo('product-detail', { id: 123 });
|
|
307
|
-
|
|
308
|
-
// Check authentication
|
|
309
|
-
if (this.$isAuthenticated()) {
|
|
310
|
-
// User is logged in
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Internationalization
|
|
314
|
-
const title = this.$t('product.title');
|
|
315
|
-
|
|
316
|
-
// Data automatically fetched if dataURL is defined in component
|
|
317
|
-
// this.$fetchData() is called automatically in mounted()
|
|
318
|
-
console.log('Auto-loaded data:', this.products); // From dataURL
|
|
319
|
-
},
|
|
320
|
-
methods: {
|
|
321
|
-
handleProductClick(productId) {
|
|
322
|
-
// Navigate with parameters
|
|
323
|
-
this.navigateTo('product-detail', {
|
|
324
|
-
id: productId,
|
|
325
|
-
category: this.getParam('category')
|
|
326
|
-
});
|
|
327
|
-
},
|
|
328
|
-
|
|
329
|
-
handleLogout() {
|
|
330
|
-
this.$logout(); // Will navigate to login page
|
|
331
|
-
},
|
|
332
|
-
|
|
333
|
-
async loadUserData() {
|
|
334
|
-
// Get authentication token
|
|
335
|
-
const token = this.$getToken();
|
|
336
|
-
if (token) {
|
|
337
|
-
// Make authenticated API call
|
|
338
|
-
const response = await fetch('/api/user', {
|
|
339
|
-
headers: { 'Authorization': `Bearer ${token}` }
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
},
|
|
343
|
-
|
|
344
|
-
changeLanguage() {
|
|
345
|
-
// Change language and get translated text
|
|
346
|
-
const greeting = this.$t('common.greeting');
|
|
347
|
-
}
|
|
279
|
+
dataURL: '/api/products', // Auto-fetch data
|
|
280
|
+
mounted() {
|
|
281
|
+
const id = this.getParam('id'); // Get parameter
|
|
282
|
+
this.navigateTo('detail', { id }); // Navigate
|
|
283
|
+
console.log('Data loaded:', this.products); // From dataURL
|
|
284
|
+
if (this.$isAuthenticated()) { /* auth check */ }
|
|
285
|
+
const text = this.$t('welcome.message'); // i18n
|
|
348
286
|
}
|
|
349
287
|
};
|
|
350
288
|
```
|
|
351
289
|
|
|
352
|
-
###
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
-
|
|
356
|
-
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
- `getParams()` - Get all parameters (route + query)
|
|
360
|
-
- `getParam(key, defaultValue)` - Get specific parameter with default
|
|
361
|
-
|
|
362
|
-
#### Authentication Functions
|
|
363
|
-
- `$isAuthenticated()` - Check if user is authenticated
|
|
364
|
-
- `$logout()` - Logout and navigate to login page
|
|
365
|
-
- `$loginSuccess(target)` - Handle successful login navigation
|
|
366
|
-
- `$checkAuth(route)` - Check authentication for a route
|
|
367
|
-
- `$getToken()` - Get access token
|
|
368
|
-
- `$setToken(token, options)` - Set access token
|
|
369
|
-
- `$removeToken(storage)` - Remove access token
|
|
370
|
-
- `$getAuthCookie()` - Get authentication cookie
|
|
371
|
-
- `$getCookie(name)` - Get specific cookie value
|
|
372
|
-
|
|
373
|
-
#### Internationalization Functions
|
|
374
|
-
- `$t(key, params)` - Translate text with optional parameters
|
|
375
|
-
|
|
376
|
-
#### Data Management Functions
|
|
377
|
-
- `$fetchData()` - Fetch data from dataURL (if defined in component)
|
|
378
|
-
|
|
379
|
-
### Component Data Properties
|
|
380
|
-
|
|
381
|
-
Every route component also has access to these reactive data properties:
|
|
290
|
+
### Key Global Methods (Auto-available in all route components)
|
|
291
|
+
- **Navigation**: `navigateTo()`, `getCurrentRoute()`
|
|
292
|
+
- **Parameters**: `getParams()`, `getParam(key, defaultValue)`
|
|
293
|
+
- **Data Fetching**: `$fetchData()`, `$fetchAllData()` (with dataURL)
|
|
294
|
+
- **Authentication**: `$isAuthenticated()`, `$getToken()`, `$logout()`
|
|
295
|
+
- **Forms**: Auto-binding with `action` attribute and `{param}` templates
|
|
296
|
+
- **i18n**: `$t(key, params)` for translations
|
|
382
297
|
|
|
298
|
+
### Auto-Injected Properties
|
|
383
299
|
```javascript
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
// Your custom data
|
|
387
|
-
products: [],
|
|
388
|
-
|
|
389
|
-
// Automatically available properties
|
|
390
|
-
currentRoute: 'home', // Current route name
|
|
391
|
-
$query: {}, // Current query parameters
|
|
392
|
-
$lang: 'ko', // Current language
|
|
393
|
-
$dataLoading: false // Data loading state
|
|
394
|
-
};
|
|
395
|
-
}
|
|
300
|
+
// Automatically available in every route component:
|
|
301
|
+
// currentRoute, $query, $lang, $dataLoading
|
|
396
302
|
```
|
|
397
303
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
After initialization, the router is available globally:
|
|
304
|
+
## 🎯 View-Logic Separation: Core Philosophy in Action
|
|
401
305
|
|
|
402
|
-
|
|
403
|
-
// UMD build automatically sets window.router
|
|
404
|
-
window.router.navigateTo('about');
|
|
405
|
-
|
|
406
|
-
// Also available as
|
|
407
|
-
window.createRouter(config);
|
|
408
|
-
window.ViewLogicRouter(config);
|
|
409
|
-
```
|
|
306
|
+
ViewLogic Router's fundamental philosophy of **View-Logic Separation** creates clear boundaries between concerns:
|
|
410
307
|
|
|
411
|
-
|
|
308
|
+
### Philosophy Benefits
|
|
309
|
+
- **🎨 Pure Presentation**: Views contain only HTML - no mixed logic or scripts
|
|
310
|
+
- **🧠 Pure Logic**: JavaScript components focus solely on business logic
|
|
311
|
+
- **⚡ Zero Build Required**: Work directly with separate files in development
|
|
312
|
+
- **🔄 Hot Reload**: Instant changes without compilation or bundling
|
|
412
313
|
|
|
413
|
-
###
|
|
314
|
+
### File Structure (Core Philosophy)
|
|
315
|
+
- **View**: `src/views/products.html` - Pure HTML template
|
|
316
|
+
- **Logic**: `src/logic/products.js` - Pure Vue component logic
|
|
317
|
+
- **Style**: `src/styles/products.css` - Pure CSS styles
|
|
414
318
|
|
|
415
|
-
|
|
416
|
-
```html
|
|
417
|
-
<div class="products-page">
|
|
418
|
-
<h1>{{ title }}</h1>
|
|
419
|
-
<div class="product-grid">
|
|
420
|
-
<div v-for="product in products" :key="product.id" class="product-card">
|
|
421
|
-
<img :src="product.image" :alt="product.name">
|
|
422
|
-
<h3>{{ product.name }}</h3>
|
|
423
|
-
<p class="price">{{ formatPrice(product.price) }}</p>
|
|
424
|
-
<button @click="viewDetail(product.id)">View Detail</button>
|
|
425
|
-
</div>
|
|
426
|
-
</div>
|
|
427
|
-
</div>
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
#### Logic File (src/logic/products/list.js)
|
|
319
|
+
### Example: Philosophy in Practice
|
|
431
320
|
```javascript
|
|
321
|
+
// src/logic/products.js - Pure business logic
|
|
432
322
|
export default {
|
|
433
323
|
name: 'ProductsList',
|
|
434
|
-
dataURL: '/api/products', //
|
|
324
|
+
dataURL: '/api/products', // Auto-fetch data
|
|
435
325
|
data() {
|
|
436
|
-
return {
|
|
437
|
-
title: 'Our Products'
|
|
438
|
-
// products: [] - No need! Auto-populated from dataURL
|
|
439
|
-
};
|
|
440
|
-
},
|
|
441
|
-
mounted() {
|
|
442
|
-
// Products already loaded from dataURL!
|
|
443
|
-
console.log('Products loaded:', this.products);
|
|
444
|
-
console.log('Loading state:', this.$dataLoading);
|
|
326
|
+
return { title: 'Our Products' };
|
|
445
327
|
},
|
|
446
328
|
methods: {
|
|
447
|
-
formatPrice(price) {
|
|
448
|
-
return new Intl.NumberFormat('ko-KR', {
|
|
449
|
-
style: 'currency',
|
|
450
|
-
currency: 'KRW'
|
|
451
|
-
}).format(price);
|
|
452
|
-
},
|
|
453
329
|
viewDetail(id) {
|
|
454
|
-
this.navigateTo('
|
|
455
|
-
},
|
|
456
|
-
async refreshProducts() {
|
|
457
|
-
// Manual refresh if needed
|
|
458
|
-
await this.$fetchData();
|
|
330
|
+
this.navigateTo('product-detail', { id });
|
|
459
331
|
}
|
|
460
332
|
}
|
|
461
333
|
};
|
|
462
334
|
```
|
|
463
335
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
.products-page {
|
|
467
|
-
padding: 20px;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
.product-grid {
|
|
471
|
-
display: grid;
|
|
472
|
-
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
473
|
-
gap: 20px;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
.product-card {
|
|
477
|
-
border: 1px solid #e0e0e0;
|
|
478
|
-
border-radius: 8px;
|
|
479
|
-
padding: 15px;
|
|
480
|
-
transition: transform 0.2s;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
.product-card:hover {
|
|
484
|
-
transform: translateY(-2px);
|
|
485
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
.price {
|
|
489
|
-
font-weight: bold;
|
|
490
|
-
color: #2196F3;
|
|
491
|
-
}
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
### Production Mode (Built Bundle)
|
|
495
|
-
|
|
496
|
-
After build, these files are automatically combined into a single optimized bundle:
|
|
497
|
-
|
|
498
|
-
```javascript
|
|
499
|
-
// routes/products/list.js (Auto-generated)
|
|
500
|
-
export default {
|
|
501
|
-
name: 'ProductsList',
|
|
502
|
-
template: `<div class="products-page">...`, // View injected
|
|
503
|
-
_style: `.products-page { ... }`, // Style injected
|
|
504
|
-
// ... logic code
|
|
505
|
-
}
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
## 🔄 Development vs Production Mode
|
|
336
|
+
### Production: Automatic Optimization
|
|
337
|
+
All separate files automatically combine into optimized bundles in `routes/` folder - maintaining the development philosophy while optimizing for production.
|
|
509
338
|
|
|
510
|
-
|
|
511
|
-
- **No Build Required**: Edit files and refresh browser to see changes
|
|
512
|
-
- **Clear Separation**: View, Logic, and Style in separate files for better organization
|
|
513
|
-
- **Easy Debugging**: Source maps and unminified code
|
|
514
|
-
- **Real-time Updates**: Changes reflect immediately without compilation
|
|
515
|
-
- **⚠️ Performance Trade-off**: Multiple file requests per route (view.html + logic.js + style.css + layout.html)
|
|
339
|
+
## 🔄 Zero Build Development vs Optimized Production
|
|
516
340
|
|
|
517
|
-
|
|
518
|
-
- **Optimized Bundles**: Each route is a single, minified JavaScript file
|
|
519
|
-
- **⚡ Superior Performance**: Single file request per route (all assets pre-bundled)
|
|
520
|
-
- **Faster Loading**: Pre-built bundles eliminate compilation overhead
|
|
521
|
-
- **Reduced Requests**: Combined view + logic + style in one file
|
|
522
|
-
- **CDN Ready**: Individual route files can be cached and served from CDN
|
|
523
|
-
- **Minimal Bundle Size**: Each route file contains only what's needed for that specific route
|
|
341
|
+
ViewLogic Router's **Zero Build Development** (core philosophy) vs optimized production:
|
|
524
342
|
|
|
525
|
-
|
|
343
|
+
| Mode | Philosophy | Files | Requests | Experience |
|
|
344
|
+
|------|------------|-------|----------|------------|
|
|
345
|
+
| **Development** | **Zero Build Required** | Separate files | 4 per route | **Real-time, instant changes** |
|
|
346
|
+
| **Production** | **Optimized Performance** | Single bundle | 1 per route | **Lightning-fast loading** |
|
|
526
347
|
|
|
527
348
|
```javascript
|
|
528
|
-
// Development
|
|
529
|
-
ViewLogicRouter({
|
|
530
|
-
environment: 'development',
|
|
531
|
-
});
|
|
349
|
+
// Zero Build Development (Core Philosophy)
|
|
350
|
+
ViewLogicRouter({ environment: 'development' }); // Work directly with source files
|
|
532
351
|
|
|
533
|
-
// Production
|
|
534
|
-
ViewLogicRouter({
|
|
535
|
-
environment: 'production',
|
|
536
|
-
});
|
|
352
|
+
// Optimized Production
|
|
353
|
+
ViewLogicRouter({ environment: 'production' }); // Use pre-built bundles
|
|
537
354
|
```
|
|
538
355
|
|
|
356
|
+
### Zero Build Development Benefits
|
|
357
|
+
- ⚡ **Instant Changes** - Edit HTML/JS/CSS and see changes immediately
|
|
358
|
+
- 🚀 **Zero Setup** - No webpack, vite, or build tools required
|
|
359
|
+
- 🎯 **True Hot Reload** - Files load directly from src/ folder
|
|
360
|
+
- 🛠️ **Pure Development** - Focus on code, not build configuration
|
|
361
|
+
|
|
539
362
|
## 🪶 Ultra-Lightweight Bundle
|
|
540
363
|
|
|
541
364
|
ViewLogic Router provides a complete routing solution in an incredibly small package:
|
|
@@ -556,6 +379,7 @@ ViewLogic Router provides a complete routing solution in an incredibly small pac
|
|
|
556
379
|
- ✅ Development/production modes
|
|
557
380
|
- ✅ **Automatic data fetching with dataURL**
|
|
558
381
|
- ✅ **Revolutionary DynamicInclude & HtmlInclude components**
|
|
382
|
+
- ✅ **Automatic form handling with variable parameters**
|
|
559
383
|
- ✅ **10+ Built-in UI components (Button, Modal, Card, etc.)**
|
|
560
384
|
|
|
561
385
|
### Why So Small?
|
|
@@ -570,46 +394,7 @@ ViewLogic Router provides a complete routing solution in an incredibly small pac
|
|
|
570
394
|
- **Mobile Optimized** - Perfect for mobile-first applications
|
|
571
395
|
- **CDN Friendly** - Small size ideal for CDN distribution
|
|
572
396
|
|
|
573
|
-
##
|
|
574
|
-
|
|
575
|
-
### Development Mode Performance
|
|
576
|
-
```
|
|
577
|
-
Route Loading Process:
|
|
578
|
-
├── 1️⃣ Load logic file (products/list.js)
|
|
579
|
-
├── 2️⃣ Load view file (products/list.html)
|
|
580
|
-
├── 3️⃣ Load style file (products/list.css)
|
|
581
|
-
└── 4️⃣ Load layout file (default.html)
|
|
582
|
-
|
|
583
|
-
Total: 4 HTTP requests per route
|
|
584
|
-
Best for: Development and debugging
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
### Production Mode Performance
|
|
588
|
-
```
|
|
589
|
-
Route Loading Process:
|
|
590
|
-
└── 1️⃣ Load single bundle (products/list.js)
|
|
591
|
-
├── ✅ View template (pre-bundled)
|
|
592
|
-
├── ✅ Business logic (minified)
|
|
593
|
-
└── ✅ Styles (inline CSS)
|
|
594
|
-
|
|
595
|
-
Total: 1 HTTP request per route
|
|
596
|
-
Best for: Production deployment
|
|
597
|
-
```
|
|
598
|
-
|
|
599
|
-
### Performance Impact
|
|
600
|
-
| Mode | Requests per Route | Bundle Size | Load Time | Use Case |
|
|
601
|
-
|------|-------------------|-------------|-----------|----------|
|
|
602
|
-
| **Development** | 4 files | Unminified | Slower | Real-time development |
|
|
603
|
-
| **Production** | 1 file | Minified | **75% Faster** | Live deployment |
|
|
604
|
-
|
|
605
|
-
### Why Production is Faster
|
|
606
|
-
- **Single Request**: No multiple file fetching overhead
|
|
607
|
-
- **Pre-bundled Assets**: View, logic, and styles combined at build time
|
|
608
|
-
- **Minified Code**: Smaller file sizes for faster network transfer
|
|
609
|
-
- **Optimized Parsing**: Browser parses one optimized bundle instead of multiple files
|
|
610
|
-
- **Better Caching**: Single file per route enables more efficient browser/CDN caching
|
|
611
|
-
|
|
612
|
-
## 🏆 Performance vs Other Router Systems
|
|
397
|
+
## 🏆 Performance Comparison
|
|
613
398
|
|
|
614
399
|
### Bundle Size Comparison
|
|
615
400
|
| Router System | Bundle Size (Gzipped) | Features Included |
|
|
@@ -711,6 +496,10 @@ ViewLogic Router includes groundbreaking components that revolutionize how you h
|
|
|
711
496
|
- **Script Execution** - Optional JavaScript execution in HTML content
|
|
712
497
|
|
|
713
498
|
### Automatic Data Fetching with dataURL
|
|
499
|
+
|
|
500
|
+
ViewLogic Router includes revolutionary automatic data fetching that eliminates manual API calls in component lifecycle hooks.
|
|
501
|
+
|
|
502
|
+
#### Single API (Simple Usage)
|
|
714
503
|
```javascript
|
|
715
504
|
// src/logic/products/list.js
|
|
716
505
|
export default {
|
|
@@ -736,397 +525,326 @@ export default {
|
|
|
736
525
|
};
|
|
737
526
|
```
|
|
738
527
|
|
|
739
|
-
|
|
740
|
-
- **Zero-Config API Calls** - Just define `dataURL` and data is automatically fetched
|
|
741
|
-
- **Query Parameter Integration** - Current route parameters are automatically sent to API
|
|
742
|
-
- **Loading State Management** - `$dataLoading` property automatically managed
|
|
743
|
-
- **Error Handling** - Built-in error handling with events
|
|
744
|
-
- **Data Merging** - API response automatically merged into component data
|
|
745
|
-
- **Event Support** - `@data-loaded` and `@data-error` events available
|
|
746
|
-
|
|
747
|
-
### Why These Components Are Revolutionary
|
|
748
|
-
|
|
749
|
-
#### Traditional Approach Problems
|
|
528
|
+
#### Multiple APIs (Advanced Usage) - 🆕 Revolutionary!
|
|
750
529
|
```javascript
|
|
751
|
-
//
|
|
530
|
+
// src/logic/dashboard/main.js
|
|
752
531
|
export default {
|
|
532
|
+
name: 'DashboardMain',
|
|
533
|
+
dataURL: {
|
|
534
|
+
products: '/api/products',
|
|
535
|
+
categories: '/api/categories',
|
|
536
|
+
stats: '/api/dashboard/stats',
|
|
537
|
+
user: '/api/user/profile'
|
|
538
|
+
}, // ✨ Multiple APIs with named data!
|
|
753
539
|
data() {
|
|
754
540
|
return {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
541
|
+
title: 'Dashboard'
|
|
542
|
+
// products: [], categories: [], stats: {}, user: {}
|
|
543
|
+
// All auto-populated from respective APIs!
|
|
758
544
|
};
|
|
759
545
|
},
|
|
760
|
-
|
|
761
|
-
|
|
546
|
+
mounted() {
|
|
547
|
+
// All APIs called in parallel, data available by name!
|
|
548
|
+
console.log('Products:', this.products);
|
|
549
|
+
console.log('Categories:', this.categories);
|
|
550
|
+
console.log('Stats:', this.stats);
|
|
551
|
+
console.log('User:', this.user);
|
|
552
|
+
console.log('Loading state:', this.$dataLoading);
|
|
762
553
|
},
|
|
763
554
|
methods: {
|
|
764
|
-
async
|
|
765
|
-
|
|
766
|
-
this
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
console.error('Failed to load products:', error);
|
|
776
|
-
} finally {
|
|
777
|
-
this.loading = false;
|
|
778
|
-
}
|
|
555
|
+
async refreshProducts() {
|
|
556
|
+
// Refresh specific API only
|
|
557
|
+
await this.$fetchData('products');
|
|
558
|
+
},
|
|
559
|
+
async refreshStats() {
|
|
560
|
+
// Refresh specific API only
|
|
561
|
+
await this.$fetchData('stats');
|
|
562
|
+
},
|
|
563
|
+
async refreshAllData() {
|
|
564
|
+
// Refresh all APIs
|
|
565
|
+
await this.$fetchAllData();
|
|
779
566
|
}
|
|
780
567
|
}
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
// For dynamic content loading - even more complex
|
|
784
|
-
async loadDynamicContent() {
|
|
785
|
-
this.loading = true;
|
|
786
|
-
try {
|
|
787
|
-
const response = await fetch(`/api/content/${this.contentId}`);
|
|
788
|
-
const data = await response.json();
|
|
789
|
-
this.content = data.html;
|
|
790
|
-
this.$nextTick(() => {
|
|
791
|
-
// Manual DOM manipulation needed
|
|
792
|
-
this.bindEvents();
|
|
793
|
-
});
|
|
794
|
-
} catch (error) {
|
|
795
|
-
this.error = error;
|
|
796
|
-
} finally {
|
|
797
|
-
this.loading = false;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
568
|
+
};
|
|
800
569
|
```
|
|
801
570
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
571
|
+
**Features:**
|
|
572
|
+
- **Zero-Config API Calls** - Just define `dataURL` and data is automatically fetched
|
|
573
|
+
- **🆕 Multiple API Support** - Define multiple APIs with custom names
|
|
574
|
+
- **🚀 Parallel Processing** - Multiple APIs called simultaneously for best performance
|
|
575
|
+
- **🎯 Selective Refresh** - Refresh specific APIs independently
|
|
576
|
+
- **Query Parameter Integration** - Current route parameters are automatically sent to all APIs
|
|
577
|
+
- **Loading State Management** - `$dataLoading` property automatically managed
|
|
578
|
+
- **Advanced Error Handling** - Per-API error handling with detailed events
|
|
579
|
+
- **Named Data Storage** - Each API result stored with its defined name
|
|
580
|
+
- **Event Support** - `@data-loaded` and `@data-error` events with detailed info
|
|
581
|
+
|
|
582
|
+
### Why These Components Are Revolutionary
|
|
583
|
+
|
|
584
|
+
**Traditional Approach**: 30+ lines of loading states, error handling, and manual API calls.
|
|
585
|
+
|
|
586
|
+
**ViewLogic Approach**: `dataURL: '/api/products'` - That's it! Data automatically fetched and available as `this.products`.
|
|
587
|
+
|
|
588
|
+
### Common Use Cases
|
|
589
|
+
- **Single API**: `dataURL: '/api/products'` - Product listings, user profiles, articles
|
|
590
|
+
- **Multiple APIs**: `dataURL: { stats: '/api/stats', users: '/api/users' }` - Dashboards, admin panels
|
|
591
|
+
- **Dynamic Content**: `<DynamicInclude page="login" :params="{ theme: 'compact' }" />`
|
|
592
|
+
- **HTML Includes**: `<HtmlInclude src="/widgets/weather.html" :sanitize="true" />`
|
|
593
|
+
|
|
594
|
+
### Advantages
|
|
595
|
+
- ✅ **Auto Data Fetching** with `dataURL` property (others: manual logic)
|
|
596
|
+
- ✅ **Parameter Integration** - Query params sent automatically
|
|
597
|
+
- ✅ **Loading States** - `$dataLoading` auto-managed
|
|
598
|
+
- ✅ **Built-in Security** - HTML sanitization included
|
|
599
|
+
- ✅ **Zero Setup** - Works immediately without configuration
|
|
600
|
+
|
|
601
|
+
## 📝 Automatic Form Handling with Variable Parameters
|
|
602
|
+
|
|
603
|
+
ViewLogic Router includes revolutionary automatic form handling that eliminates the need for manual form submission logic. Just define your forms with `action` attributes and the router handles the rest!
|
|
604
|
+
|
|
605
|
+
### Basic Form Handling
|
|
606
|
+
|
|
607
|
+
```html
|
|
608
|
+
<!-- src/views/contact.html -->
|
|
609
|
+
<div class="contact-page">
|
|
610
|
+
<h1>Contact Us</h1>
|
|
611
|
+
<form action="/api/contact" method="POST">
|
|
612
|
+
<input type="text" name="name" required placeholder="Your Name">
|
|
613
|
+
<input type="email" name="email" required placeholder="Your Email">
|
|
614
|
+
<textarea name="message" required placeholder="Your Message"></textarea>
|
|
615
|
+
<button type="submit">Send Message</button>
|
|
616
|
+
</form>
|
|
617
|
+
</div>
|
|
819
618
|
```
|
|
820
619
|
|
|
821
|
-
### Use Cases
|
|
822
|
-
|
|
823
|
-
#### Automatic Data Fetching (dataURL)
|
|
824
|
-
- **🛒 Product Listings** - `dataURL: '/api/products'` automatically loads and populates product data
|
|
825
|
-
- **👤 User Profiles** - `dataURL: '/api/user'` fetches user information with authentication
|
|
826
|
-
- **📊 Dashboard Data** - `dataURL: '/api/dashboard/stats'` loads analytics data
|
|
827
|
-
- **📰 Article Content** - `dataURL: '/api/articles'` populates blog posts or news
|
|
828
|
-
- **🔍 Search Results** - Query parameters automatically sent to search API
|
|
829
|
-
|
|
830
|
-
#### Dynamic Components
|
|
831
|
-
- **📰 Dynamic Content Management** - Load blog posts, news articles dynamically
|
|
832
|
-
- **🛒 Product Details** - Fetch product information on-demand
|
|
833
|
-
- **📊 Dashboard Widgets** - Load dashboard components from APIs
|
|
834
|
-
- **📝 Form Builders** - Dynamic form generation from configuration
|
|
835
|
-
- **🎨 Template Systems** - CMS-driven content rendering
|
|
836
|
-
- **📱 Micro-frontends** - Load remote components seamlessly
|
|
837
|
-
|
|
838
|
-
### Advantages Over Other Solutions
|
|
839
|
-
| Feature | ViewLogic Router | React Suspense | Vue Async Components |
|
|
840
|
-
|---------|------------------|----------------|----------------------|
|
|
841
|
-
| **Auto Data Fetching** | ✅ `dataURL` property | ❌ Manual fetch logic | ❌ Manual fetch logic |
|
|
842
|
-
| **Query Parameter Integration** | ✅ Automatic API params | ❌ Manual URL building | ❌ Manual URL building |
|
|
843
|
-
| **Dynamic URLs** | ✅ Built-in | ❌ Manual implementation | ❌ Manual implementation |
|
|
844
|
-
| **Parameter Injection** | ✅ Automatic | ❌ Manual | ❌ Manual |
|
|
845
|
-
| **Loading State Management** | ✅ `$dataLoading` auto-managed | ✅ Suspense | ❌ Manual state |
|
|
846
|
-
| **Error Boundaries** | ✅ Built-in slots + events | ✅ ErrorBoundary | ❌ Manual |
|
|
847
|
-
| **HTML Sanitization** | ✅ Built-in | ❌ External library | ❌ External library |
|
|
848
|
-
| **Cache Integration** | ✅ Automatic | ❌ Manual | ❌ Manual |
|
|
849
|
-
|
|
850
|
-
These components eliminate the need for complex state management and manual DOM manipulation, making dynamic content loading as simple as using a regular component.
|
|
851
|
-
|
|
852
|
-
## 🔗 Revolutionary Query-Only Parameter System
|
|
853
|
-
|
|
854
|
-
ViewLogic Router takes a radically different approach to URL parameters - **everything is query-based**. This design decision brings unprecedented simplicity and flexibility.
|
|
855
|
-
|
|
856
|
-
### Traditional Routing Problems
|
|
857
620
|
```javascript
|
|
858
|
-
//
|
|
859
|
-
const routes = [
|
|
860
|
-
{ path: '/users/:id', component: UserDetail },
|
|
861
|
-
{ path: '/users/:id/posts/:postId', component: PostDetail },
|
|
862
|
-
{ path: '/categories/:category/products/:productId', component: ProductDetail }
|
|
863
|
-
]
|
|
864
|
-
|
|
865
|
-
// Accessing parameters is inconsistent and complex
|
|
621
|
+
// src/logic/contact.js
|
|
866
622
|
export default {
|
|
623
|
+
name: 'ContactPage',
|
|
867
624
|
mounted() {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
// Complex parameter access logic needed
|
|
873
|
-
if (userId && page) {
|
|
874
|
-
// Load data...
|
|
875
|
-
}
|
|
625
|
+
// Forms are automatically bound - no additional code needed!
|
|
626
|
+
// Form submission will automatically POST to /api/contact
|
|
627
|
+
console.log('Form handling is automatic!');
|
|
876
628
|
}
|
|
877
|
-
}
|
|
629
|
+
};
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Variable Parameter Forms - 🆕 Revolutionary!
|
|
633
|
+
|
|
634
|
+
The most powerful feature is **variable parameter support** in action URLs. You can use simple template syntax to inject dynamic values:
|
|
635
|
+
|
|
636
|
+
```html
|
|
637
|
+
<!-- Dynamic form actions with variable parameters -->
|
|
638
|
+
<form action="/api/users/{userId}/posts" method="POST"
|
|
639
|
+
data-success="handlePostSuccess"
|
|
640
|
+
data-error="handlePostError">
|
|
641
|
+
<input type="text" name="title" required placeholder="Post Title">
|
|
642
|
+
<textarea name="content" required placeholder="Post Content"></textarea>
|
|
643
|
+
<button type="submit">Create Post</button>
|
|
644
|
+
</form>
|
|
645
|
+
|
|
646
|
+
<!-- Order update with dynamic order ID -->
|
|
647
|
+
<form action="/api/orders/{orderId}/update" method="PUT"
|
|
648
|
+
data-success="orderUpdated"
|
|
649
|
+
data-redirect="/orders">
|
|
650
|
+
<input type="number" name="quantity" required>
|
|
651
|
+
<select name="status">
|
|
652
|
+
<option value="pending">Pending</option>
|
|
653
|
+
<option value="processing">Processing</option>
|
|
654
|
+
<option value="completed">Completed</option>
|
|
655
|
+
</select>
|
|
656
|
+
<button type="submit">Update Order</button>
|
|
657
|
+
</form>
|
|
658
|
+
|
|
659
|
+
<!-- File upload support -->
|
|
660
|
+
<form action="/api/profile/{userId}/avatar" method="POST" enctype="multipart/form-data"
|
|
661
|
+
data-success="avatarUploaded">
|
|
662
|
+
<input type="file" name="avatar" accept="image/*" required>
|
|
663
|
+
<button type="submit">Upload Avatar</button>
|
|
664
|
+
</form>
|
|
878
665
|
```
|
|
879
666
|
|
|
880
|
-
### ViewLogic Router Solution - Pure Simplicity
|
|
881
667
|
```javascript
|
|
882
|
-
//
|
|
883
|
-
// Just navigate with parameters
|
|
884
|
-
router.navigateTo('users', { id: 123 }); // /users?id=123
|
|
885
|
-
router.navigateTo('posts', {
|
|
886
|
-
userId: 123,
|
|
887
|
-
postId: 456
|
|
888
|
-
}); // /posts?userId=123&postId=456
|
|
889
|
-
|
|
890
|
-
// In your route component - unified parameter access
|
|
668
|
+
// Component logic - parameters are resolved automatically
|
|
891
669
|
export default {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
if (userId) {
|
|
899
|
-
this.loadUserData(userId);
|
|
900
|
-
}
|
|
670
|
+
name: 'UserProfile',
|
|
671
|
+
data() {
|
|
672
|
+
return {
|
|
673
|
+
userId: 123, // {userId} will be replaced with this value
|
|
674
|
+
orderId: 456 // {orderId} will be replaced with this value
|
|
675
|
+
};
|
|
901
676
|
},
|
|
902
677
|
methods: {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
678
|
+
handlePostSuccess(response) {
|
|
679
|
+
console.log('Post created successfully!', response);
|
|
680
|
+
},
|
|
681
|
+
orderUpdated(response) {
|
|
682
|
+
console.log('Order updated!', response);
|
|
906
683
|
}
|
|
907
684
|
}
|
|
908
|
-
}
|
|
685
|
+
};
|
|
909
686
|
```
|
|
910
687
|
|
|
911
|
-
###
|
|
688
|
+
### How Parameter Resolution Works
|
|
912
689
|
|
|
913
|
-
|
|
914
|
-
```javascript
|
|
915
|
-
// Traditional: Complex nested routes
|
|
916
|
-
const routes = [
|
|
917
|
-
{
|
|
918
|
-
path: '/products/:category',
|
|
919
|
-
component: ProductList,
|
|
920
|
-
children: [
|
|
921
|
-
{ path: ':id', component: ProductDetail },
|
|
922
|
-
{ path: ':id/reviews/:reviewId', component: ReviewDetail }
|
|
923
|
-
]
|
|
924
|
-
}
|
|
925
|
-
];
|
|
690
|
+
Parameters are resolved automatically from multiple sources in this order:
|
|
926
691
|
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
692
|
+
1. **Route Parameters**: `this.getParam('paramName')` - from URL query parameters
|
|
693
|
+
2. **Component Data**: `this.paramName` - from component's data properties
|
|
694
|
+
3. **Computed Properties**: `this.paramName` - from component's computed properties
|
|
930
695
|
|
|
931
|
-
#### 2. **Consistent Parameter Access**
|
|
932
696
|
```javascript
|
|
933
|
-
//
|
|
697
|
+
// Component example
|
|
934
698
|
export default {
|
|
699
|
+
name: 'UserProfile',
|
|
700
|
+
data() {
|
|
701
|
+
return {
|
|
702
|
+
userId: 123, // Available as {userId} in action URLs
|
|
703
|
+
productId: 456 // Available as {productId} in action URLs
|
|
704
|
+
};
|
|
705
|
+
},
|
|
706
|
+
computed: {
|
|
707
|
+
currentOrderId() { // Available as {currentOrderId} in action URLs
|
|
708
|
+
return this.getParam('orderId') || this.defaultOrderId;
|
|
709
|
+
}
|
|
710
|
+
},
|
|
935
711
|
mounted() {
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
// Need complex logic to handle both types
|
|
712
|
+
// Route parameters also work: /user-profile?userId=789
|
|
713
|
+
// {userId} will use 789 from URL, or fall back to data() value of 123
|
|
939
714
|
}
|
|
940
|
-
}
|
|
715
|
+
};
|
|
716
|
+
```
|
|
941
717
|
|
|
942
|
-
|
|
718
|
+
### Event Handlers
|
|
719
|
+
```html
|
|
720
|
+
<form action="/api/subscribe" method="POST"
|
|
721
|
+
data-success="subscriptionSuccess" data-error="subscriptionError">
|
|
722
|
+
<input type="email" name="email" required>
|
|
723
|
+
<button type="submit">Subscribe</button>
|
|
724
|
+
</form>
|
|
725
|
+
```
|
|
726
|
+
```javascript
|
|
943
727
|
export default {
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
// Clean and simple - no $route needed!
|
|
728
|
+
methods: {
|
|
729
|
+
subscriptionSuccess(response) { this.$toast('Success!', 'success'); },
|
|
730
|
+
subscriptionError(error) { this.$toast('Failed!', 'error'); }
|
|
948
731
|
}
|
|
949
|
-
}
|
|
732
|
+
};
|
|
950
733
|
```
|
|
951
734
|
|
|
952
|
-
|
|
953
|
-
```
|
|
954
|
-
|
|
955
|
-
|
|
735
|
+
### Form Options
|
|
736
|
+
```html
|
|
737
|
+
<form action="/api/resource/{id}" method="POST"
|
|
738
|
+
data-success="handleSuccess" data-error="handleError"
|
|
739
|
+
data-redirect="/success" data-confirm="Sure?"
|
|
740
|
+
enctype="multipart/form-data">
|
|
741
|
+
<input name="title" required>
|
|
742
|
+
<input type="file" name="file" accept=".pdf">
|
|
743
|
+
<button type="submit">Submit</button>
|
|
744
|
+
</form>
|
|
745
|
+
```
|
|
956
746
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
747
|
+
### Authentication Integration
|
|
748
|
+
```html
|
|
749
|
+
<!-- Auth tokens automatically included for authenticated users -->
|
|
750
|
+
<form action="/api/protected/resource" method="POST">
|
|
751
|
+
<input name="data" required>
|
|
752
|
+
<button type="submit">Save</button>
|
|
753
|
+
</form>
|
|
754
|
+
<!-- Authorization: Bearer <token> header added automatically -->
|
|
960
755
|
```
|
|
961
756
|
|
|
962
|
-
|
|
963
|
-
```
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
const currentPage = this.getParam('page', 1);
|
|
971
|
-
},
|
|
972
|
-
methods: {
|
|
973
|
-
applyFilters() {
|
|
974
|
-
// Easy navigation with parameters
|
|
975
|
-
this.navigateTo('products', {
|
|
976
|
-
category: 'electronics',
|
|
977
|
-
sort: 'price',
|
|
978
|
-
page: 2
|
|
979
|
-
});
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
}
|
|
757
|
+
### Form Validation
|
|
758
|
+
```html
|
|
759
|
+
<!-- HTML5 + custom validation -->
|
|
760
|
+
<form action="/api/register" method="POST">
|
|
761
|
+
<input type="email" name="email" required pattern="...">
|
|
762
|
+
<input type="password" name="password" minlength="8" required>
|
|
763
|
+
<button type="submit">Register</button>
|
|
764
|
+
</form>
|
|
983
765
|
```
|
|
984
766
|
|
|
985
|
-
### Real-World
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
767
|
+
### Real-World Form Examples
|
|
768
|
+
```html
|
|
769
|
+
<!-- User profile with dynamic parameters -->
|
|
770
|
+
<form action="/api/users/{userId}" method="PUT" data-success="profileUpdated">
|
|
771
|
+
<input name="firstName" required>
|
|
772
|
+
<button type="submit">Update</button>
|
|
773
|
+
</form>
|
|
774
|
+
|
|
775
|
+
<!-- Order management -->
|
|
776
|
+
<form action="/api/orders/{orderId}/status" method="PUT">
|
|
777
|
+
<select name="status" required>
|
|
778
|
+
<option value="pending">Pending</option>
|
|
779
|
+
<option value="shipped">Shipped</option>
|
|
780
|
+
</select>
|
|
781
|
+
<button type="submit">Update</button>
|
|
782
|
+
</form>
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
### Form Handling Advantages
|
|
786
|
+
- ✅ **Zero Setup** - Just add `action` attribute vs manual event handlers
|
|
787
|
+
- ✅ **Variable Parameters** - `{userId}` template syntax vs manual interpolation
|
|
788
|
+
- ✅ **Auto Authentication** - Tokens injected automatically
|
|
789
|
+
- ✅ **File Uploads** - Automatic multipart support
|
|
790
|
+
- ✅ **Built-in Validation** - HTML5 + custom functions
|
|
791
|
+
|
|
792
|
+
### Code Comparison
|
|
793
|
+
**Traditional**: 30+ lines of boilerplate for forms, API calls, loading states
|
|
794
|
+
**ViewLogic**: 5 lines with `action` attribute + callback method
|
|
795
|
+
**Result**: 80% less code, more features included
|
|
796
|
+
|
|
797
|
+
## 🔗 Query-Based Parameter System: Revolutionary Simplicity
|
|
798
|
+
|
|
799
|
+
ViewLogic Router's **Query-Based Parameter System** is a key feature that eliminates routing complexity:
|
|
800
|
+
|
|
801
|
+
**Philosophy**: **Everything is query-based** - no complex path parameters like `/users/:id`. Just simple, clean URLs: `/users?id=123`.
|
|
802
|
+
|
|
803
|
+
### Revolutionary Benefits
|
|
804
|
+
1. **📍 Simple URLs**: `/product?id=123&category=electronics` (clear and readable)
|
|
805
|
+
2. **🎯 Consistent Access**: Always use `this.getParam('id')` - never mix path/query paradigms
|
|
806
|
+
3. **⚡ No Route Configuration**: No complex route definitions or parameter mappings needed
|
|
807
|
+
4. **🔍 SEO Friendly**: Descriptive parameter names make URLs self-documenting
|
|
808
|
+
5. **🌐 Universal Compatibility**: Query parameters work everywhere - no framework lock-in
|
|
809
|
+
|
|
810
|
+
### Simple Usage Example
|
|
1009
811
|
```javascript
|
|
1010
|
-
//
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
];
|
|
812
|
+
// Navigate - simple and intuitive
|
|
813
|
+
this.navigateTo('products', { id: 123, category: 'electronics' });
|
|
814
|
+
// → /products?id=123&category=electronics
|
|
1014
815
|
|
|
1015
|
-
//
|
|
816
|
+
// Access parameters - always the same way
|
|
1016
817
|
export default {
|
|
1017
818
|
mounted() {
|
|
1018
|
-
const
|
|
1019
|
-
const
|
|
1020
|
-
const
|
|
1021
|
-
// Complex logic needed...
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
|
|
1025
|
-
// After: Simple and flexible - no route definitions needed!
|
|
1026
|
-
export default {
|
|
1027
|
-
mounted() {
|
|
1028
|
-
// Clean global function access
|
|
1029
|
-
const year = this.getParam('year', new Date().getFullYear());
|
|
1030
|
-
const month = this.getParam('month', new Date().getMonth() + 1);
|
|
1031
|
-
const slug = this.getParam('slug');
|
|
1032
|
-
const utm_source = this.getParam('utm_source'); // Easy to add tracking params
|
|
1033
|
-
},
|
|
1034
|
-
methods: {
|
|
1035
|
-
navigateToPost() {
|
|
1036
|
-
this.navigateTo('blog-post', {
|
|
1037
|
-
year: 2024,
|
|
1038
|
-
month: 12,
|
|
1039
|
-
slug: 'my-article',
|
|
1040
|
-
utm_source: 'newsletter'
|
|
1041
|
-
});
|
|
1042
|
-
}
|
|
819
|
+
const id = this.getParam('id'); // Get parameter
|
|
820
|
+
const category = this.getParam('category', 'all'); // With default
|
|
821
|
+
const allParams = this.getParams(); // Get all parameters
|
|
1043
822
|
}
|
|
1044
|
-
}
|
|
823
|
+
};
|
|
1045
824
|
```
|
|
1046
825
|
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
## 🛡️ Error Handling
|
|
826
|
+
### Why Query-Based is Revolutionary
|
|
827
|
+
**Traditional Routers**: Complex path parameters (`/users/:id/posts/:postId`) require route configuration, parameter extraction logic, and mixed paradigms.
|
|
1050
828
|
|
|
1051
|
-
|
|
829
|
+
**ViewLogic Router**: Simple query parameters (`/users?id=123&postId=456`) work universally with consistent `getParam()` access.
|
|
1052
830
|
|
|
1053
|
-
```javascript
|
|
1054
|
-
// Global error handler
|
|
1055
|
-
router.errorHandler.log('error', 'Custom error message');
|
|
1056
831
|
|
|
1057
|
-
|
|
1058
|
-
router.errorHandler.handleRouteError('routeName', error);
|
|
832
|
+
## 🛡️ Error Handling
|
|
1059
833
|
|
|
1060
|
-
|
|
1061
|
-
```
|
|
834
|
+
Built-in comprehensive error handling with automatic 404 detection, graceful component loading failures, and parameter validation with fallbacks.
|
|
1062
835
|
|
|
1063
836
|
## 🚀 Production Deployment
|
|
1064
837
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
# This will:
|
|
1069
|
-
# - Combine view + logic + style files from src/
|
|
1070
|
-
# - Generate optimized route bundles in routes/ folder
|
|
1071
|
-
# - Minify and optimize each route
|
|
1072
|
-
# - Copy routes/ to root level for deployment
|
|
1073
|
-
```
|
|
838
|
+
1. **Build**: `npm run build` - Combines view + logic + style into optimized route bundles
|
|
839
|
+
2. **Deploy**: Set `environment: 'production'` and use CDN or local files
|
|
840
|
+
3. **Structure**: Deploy `routes/`, `css/`, `i18n/` folders (exclude `src/`)
|
|
1074
841
|
|
|
1075
|
-
|
|
842
|
+
**CDN Usage:**
|
|
1076
843
|
```html
|
|
1077
|
-
|
|
1078
|
-
<
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
<link rel="stylesheet" href="/css/base.css">
|
|
1082
|
-
</head>
|
|
1083
|
-
<body>
|
|
1084
|
-
<div id="app"></div>
|
|
1085
|
-
|
|
1086
|
-
<!-- Vue 3 Production -->
|
|
1087
|
-
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
|
|
1088
|
-
|
|
1089
|
-
<!-- ViewLogic Router from CDN -->
|
|
1090
|
-
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.umd.js"></script>
|
|
1091
|
-
|
|
1092
|
-
<script>
|
|
1093
|
-
ViewLogicRouter({
|
|
1094
|
-
environment: 'production',
|
|
1095
|
-
basePath: '/', // Root path
|
|
1096
|
-
routesPath: '/routes', // Routes folder at root level
|
|
1097
|
-
i18nPath: '/i18n', // i18n folder at root level
|
|
1098
|
-
cacheMode: 'session', // Enable session caching
|
|
1099
|
-
useComponents: true,
|
|
1100
|
-
useI18n: true
|
|
1101
|
-
});
|
|
1102
|
-
</script>
|
|
1103
|
-
</body>
|
|
1104
|
-
</html>
|
|
1105
|
-
```
|
|
1106
|
-
|
|
1107
|
-
### 3. Production deployment structure:
|
|
1108
|
-
```
|
|
1109
|
-
production/
|
|
1110
|
-
├── index.html
|
|
1111
|
-
├── i18n/ # Language files
|
|
1112
|
-
│ ├── ko.json
|
|
1113
|
-
│ └── en.json
|
|
1114
|
-
├── css/
|
|
1115
|
-
│ └── base.css # Global styles
|
|
1116
|
-
├── js/ # Optional (can use CDN instead)
|
|
1117
|
-
│ ├── viewlogic-router.umd.js
|
|
1118
|
-
│ └── viewlogic-router.min.js
|
|
1119
|
-
├── routes/ # Built route bundles
|
|
1120
|
-
│ ├── home.js # Bundled: view + logic + style
|
|
1121
|
-
│ ├── about.js
|
|
1122
|
-
│ └── products/
|
|
1123
|
-
│ ├── list.js
|
|
1124
|
-
│ └── detail.js
|
|
1125
|
-
└── assets/
|
|
1126
|
-
├── images/
|
|
1127
|
-
└── fonts/
|
|
1128
|
-
|
|
1129
|
-
# Note: src/ folder is NOT deployed to production
|
|
844
|
+
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.umd.js"></script>
|
|
845
|
+
<script>
|
|
846
|
+
ViewLogicRouter({ environment: 'production' }).mount('#app');
|
|
847
|
+
</script>
|
|
1130
848
|
```
|
|
1131
849
|
|
|
1132
850
|
## 🤝 Contributing
|