viewlogic 1.0.4 → 1.1.1
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
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,11 +12,25 @@
|
|
|
12
12
|
</a>
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
> A revolutionary Vue 3 routing system with
|
|
15
|
+
> A revolutionary Vue 3 routing system with automatic data fetching, form handling, and zero build development
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 🆕 Latest Updates (v1.1.1)
|
|
18
18
|
|
|
19
|
-
|
|
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
|
|
24
|
+
|
|
25
|
+
## 🎯 Core Philosophy: Simplicity Through Design
|
|
26
|
+
|
|
27
|
+
ViewLogic Router revolutionizes Vue development with two core principles:
|
|
28
|
+
|
|
29
|
+
### 🎭 View-Logic Separation
|
|
30
|
+
Clear separation between **View** (presentation) and **Logic** (business logic), making your code more maintainable, testable, and scalable.
|
|
31
|
+
|
|
32
|
+
### 🔗 Query-Only Parameters
|
|
33
|
+
**All parameters are passed via query strings only** - no complex path parameters (`/users/:id`), just simple, clean URLs (`/users?id=123`). This revolutionary approach simplifies routing and makes URLs more predictable and SEO-friendly.
|
|
20
34
|
|
|
21
35
|
## ✨ Features
|
|
22
36
|
|
|
@@ -26,10 +40,12 @@ ViewLogic Router revolutionizes Vue development by clearly separating **View** (
|
|
|
26
40
|
- 📁 **Intuitive Structure** - Organized folder structure for views, logic, styles, layouts, and components
|
|
27
41
|
- 🔄 **Hot Development** - See changes instantly without compilation
|
|
28
42
|
- 📦 **Smart Production Build** - Each route becomes an optimized JavaScript bundle
|
|
29
|
-
- 🛠️ **Built-in Components** - Preloaded UI components
|
|
43
|
+
- 🛠️ **Built-in Components** - Preloaded UI components including revolutionary DynamicInclude & HtmlInclude
|
|
30
44
|
- 🌐 **i18n Ready** - Built-in internationalization support
|
|
31
45
|
- 🔐 **Authentication** - Built-in auth management system
|
|
32
46
|
- 💾 **Smart Caching** - Intelligent route and component caching
|
|
47
|
+
- 📝 **Automatic Form Handling** - Revolutionary form submission with variable parameters
|
|
48
|
+
- 🚀 **Ultra-Lightweight** - Complete routing system in just 13KB gzipped (48KB minified)
|
|
33
49
|
|
|
34
50
|
## 📦 Installation
|
|
35
51
|
|
|
@@ -57,17 +73,14 @@ pnpm add viewlogic
|
|
|
57
73
|
<div id="app"></div>
|
|
58
74
|
|
|
59
75
|
<!-- Vue 3 (development version) -->
|
|
60
|
-
<script src="https://
|
|
76
|
+
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
|
|
61
77
|
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.umd.js"></script>
|
|
62
78
|
|
|
63
79
|
<script>
|
|
64
80
|
// Development mode - loads files directly from src/
|
|
65
81
|
ViewLogicRouter({
|
|
66
82
|
environment: 'development',
|
|
67
|
-
}).
|
|
68
|
-
console.log('Development router ready!');
|
|
69
|
-
// Router automatically combines view + logic + style on the fly
|
|
70
|
-
});
|
|
83
|
+
}).mount('#app');
|
|
71
84
|
</script>
|
|
72
85
|
</body>
|
|
73
86
|
</html>
|
|
@@ -87,8 +100,8 @@ pnpm add viewlogic
|
|
|
87
100
|
<div id="app"></div>
|
|
88
101
|
|
|
89
102
|
<!-- Vue 3 (production version) -->
|
|
90
|
-
<script src="https://
|
|
91
|
-
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.
|
|
103
|
+
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
|
|
104
|
+
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.umd.js"></script>
|
|
92
105
|
|
|
93
106
|
<script>
|
|
94
107
|
// Production mode - loads pre-built bundles from routes/
|
|
@@ -96,9 +109,7 @@ pnpm add viewlogic
|
|
|
96
109
|
environment: 'production',
|
|
97
110
|
useI18n: true,
|
|
98
111
|
logLevel: 'error' // Only log errors
|
|
99
|
-
}).
|
|
100
|
-
console.log('Production router ready!');
|
|
101
|
-
});
|
|
112
|
+
}).mount('#app');
|
|
102
113
|
</script>
|
|
103
114
|
</body>
|
|
104
115
|
</html>
|
|
@@ -258,10 +269,11 @@ router.navigateTo({ route: 'products', params: { id: 123 } });
|
|
|
258
269
|
// Get current route
|
|
259
270
|
const currentRoute = router.getCurrentRoute();
|
|
260
271
|
|
|
261
|
-
//
|
|
262
|
-
router.queryManager.setQueryParams({
|
|
263
|
-
const params = router.queryManager.
|
|
264
|
-
router.queryManager.
|
|
272
|
+
// Unified parameter system - all parameters are query-based
|
|
273
|
+
router.queryManager.setQueryParams({ id: 123, category: 'electronics' });
|
|
274
|
+
const params = router.queryManager.getParams(); // Gets all parameters
|
|
275
|
+
const userId = router.queryManager.getParam('id', 1); // Get specific parameter with default
|
|
276
|
+
router.queryManager.removeQueryParams(['category']);
|
|
265
277
|
|
|
266
278
|
// Authentication (if enabled)
|
|
267
279
|
router.authManager.login(token);
|
|
@@ -279,6 +291,123 @@ router.cacheManager.clearAll();
|
|
|
279
291
|
router.destroy();
|
|
280
292
|
```
|
|
281
293
|
|
|
294
|
+
### Global Functions Available in Route Components
|
|
295
|
+
|
|
296
|
+
Every route component automatically has access to these global functions:
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
export default {
|
|
300
|
+
name: 'MyComponent',
|
|
301
|
+
data() {
|
|
302
|
+
return {
|
|
303
|
+
products: []
|
|
304
|
+
};
|
|
305
|
+
},
|
|
306
|
+
async mounted() {
|
|
307
|
+
// Get all parameters (both route and query parameters)
|
|
308
|
+
const allParams = this.getParams();
|
|
309
|
+
|
|
310
|
+
// Get specific parameter with default value
|
|
311
|
+
const categoryId = this.getParam('categoryId', 1);
|
|
312
|
+
const sortBy = this.getParam('sort', 'name');
|
|
313
|
+
|
|
314
|
+
// Navigation
|
|
315
|
+
this.navigateTo('product-detail', { id: 123 });
|
|
316
|
+
|
|
317
|
+
// Check authentication
|
|
318
|
+
if (this.$isAuthenticated()) {
|
|
319
|
+
// User is logged in
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Internationalization
|
|
323
|
+
const title = this.$t('product.title');
|
|
324
|
+
|
|
325
|
+
// Data automatically fetched if dataURL is defined in component
|
|
326
|
+
// Single API: this.products available
|
|
327
|
+
// Multiple APIs: this.products, this.categories, this.stats, etc. available
|
|
328
|
+
console.log('Auto-loaded data:', this.products); // From dataURL
|
|
329
|
+
},
|
|
330
|
+
methods: {
|
|
331
|
+
handleProductClick(productId) {
|
|
332
|
+
// Navigate with parameters
|
|
333
|
+
this.navigateTo('product-detail', {
|
|
334
|
+
id: productId,
|
|
335
|
+
category: this.getParam('category')
|
|
336
|
+
});
|
|
337
|
+
},
|
|
338
|
+
|
|
339
|
+
handleLogout() {
|
|
340
|
+
this.$logout(); // Will navigate to login page
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
async loadUserData() {
|
|
344
|
+
// Get authentication token
|
|
345
|
+
const token = this.$getToken();
|
|
346
|
+
if (token) {
|
|
347
|
+
// Make authenticated API call
|
|
348
|
+
const response = await fetch('/api/user', {
|
|
349
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
|
|
354
|
+
changeLanguage() {
|
|
355
|
+
// Change language and get translated text
|
|
356
|
+
const greeting = this.$t('common.greeting');
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Complete Global Functions List
|
|
363
|
+
|
|
364
|
+
#### Navigation Functions
|
|
365
|
+
- `navigateTo(route, params)` - Navigate to a route with parameters
|
|
366
|
+
- `getCurrentRoute()` - Get current route name
|
|
367
|
+
|
|
368
|
+
#### Parameter Management
|
|
369
|
+
- `getParams()` - Get all parameters (route + query)
|
|
370
|
+
- `getParam(key, defaultValue)` - Get specific parameter with default
|
|
371
|
+
|
|
372
|
+
#### Authentication Functions
|
|
373
|
+
- `$isAuthenticated()` - Check if user is authenticated
|
|
374
|
+
- `$logout()` - Logout and navigate to login page
|
|
375
|
+
- `$loginSuccess(target)` - Handle successful login navigation
|
|
376
|
+
- `$checkAuth(route)` - Check authentication for a route
|
|
377
|
+
- `$getToken()` - Get access token
|
|
378
|
+
- `$setToken(token, options)` - Set access token
|
|
379
|
+
- `$removeToken(storage)` - Remove access token
|
|
380
|
+
- `$getAuthCookie()` - Get authentication cookie
|
|
381
|
+
- `$getCookie(name)` - Get specific cookie value
|
|
382
|
+
|
|
383
|
+
#### Internationalization Functions
|
|
384
|
+
- `$t(key, params)` - Translate text with optional parameters
|
|
385
|
+
|
|
386
|
+
#### Data Management Functions
|
|
387
|
+
- `$fetchData()` - Fetch data from single dataURL or all multiple dataURLs
|
|
388
|
+
- `$fetchData('apiName')` - Fetch data from specific named API (multiple dataURL mode)
|
|
389
|
+
- `$fetchAllData()` - Explicitly fetch all APIs (works for both single and multiple dataURL)
|
|
390
|
+
- `$fetchMultipleData()` - Internal method for multiple API handling
|
|
391
|
+
|
|
392
|
+
### Component Data Properties
|
|
393
|
+
|
|
394
|
+
Every route component also has access to these reactive data properties:
|
|
395
|
+
|
|
396
|
+
```javascript
|
|
397
|
+
data() {
|
|
398
|
+
return {
|
|
399
|
+
// Your custom data
|
|
400
|
+
products: [],
|
|
401
|
+
|
|
402
|
+
// Automatically available properties
|
|
403
|
+
currentRoute: 'home', // Current route name
|
|
404
|
+
$query: {}, // Current query parameters
|
|
405
|
+
$lang: 'ko', // Current language
|
|
406
|
+
$dataLoading: false // Data loading state
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
282
411
|
### Global Access
|
|
283
412
|
|
|
284
413
|
After initialization, the router is available globally:
|
|
@@ -315,20 +444,19 @@ window.ViewLogicRouter(config);
|
|
|
315
444
|
```javascript
|
|
316
445
|
export default {
|
|
317
446
|
name: 'ProductsList',
|
|
447
|
+
dataURL: '/api/products', // ✨ Auto-fetch magic!
|
|
318
448
|
data() {
|
|
319
449
|
return {
|
|
320
|
-
title: 'Our Products'
|
|
321
|
-
products: []
|
|
450
|
+
title: 'Our Products'
|
|
451
|
+
// products: [] - No need! Auto-populated from dataURL
|
|
322
452
|
};
|
|
323
453
|
},
|
|
324
|
-
|
|
325
|
-
|
|
454
|
+
mounted() {
|
|
455
|
+
// Products already loaded from dataURL!
|
|
456
|
+
console.log('Products loaded:', this.products);
|
|
457
|
+
console.log('Loading state:', this.$dataLoading);
|
|
326
458
|
},
|
|
327
459
|
methods: {
|
|
328
|
-
async loadProducts() {
|
|
329
|
-
const response = await fetch('/api/products');
|
|
330
|
-
return response.json();
|
|
331
|
-
},
|
|
332
460
|
formatPrice(price) {
|
|
333
461
|
return new Intl.NumberFormat('ko-KR', {
|
|
334
462
|
style: 'currency',
|
|
@@ -336,7 +464,11 @@ export default {
|
|
|
336
464
|
}).format(price);
|
|
337
465
|
},
|
|
338
466
|
viewDetail(id) {
|
|
339
|
-
this
|
|
467
|
+
this.navigateTo('products/detail', { id });
|
|
468
|
+
},
|
|
469
|
+
async refreshProducts() {
|
|
470
|
+
// Manual refresh if needed
|
|
471
|
+
await this.$fetchData();
|
|
340
472
|
}
|
|
341
473
|
}
|
|
342
474
|
};
|
|
@@ -393,12 +525,15 @@ export default {
|
|
|
393
525
|
- **Clear Separation**: View, Logic, and Style in separate files for better organization
|
|
394
526
|
- **Easy Debugging**: Source maps and unminified code
|
|
395
527
|
- **Real-time Updates**: Changes reflect immediately without compilation
|
|
528
|
+
- **⚠️ Performance Trade-off**: Multiple file requests per route (view.html + logic.js + style.css + layout.html)
|
|
396
529
|
|
|
397
530
|
### Production Mode Benefits
|
|
398
531
|
- **Optimized Bundles**: Each route is a single, minified JavaScript file
|
|
532
|
+
- **⚡ Superior Performance**: Single file request per route (all assets pre-bundled)
|
|
399
533
|
- **Faster Loading**: Pre-built bundles eliminate compilation overhead
|
|
400
534
|
- **Reduced Requests**: Combined view + logic + style in one file
|
|
401
535
|
- **CDN Ready**: Individual route files can be cached and served from CDN
|
|
536
|
+
- **Minimal Bundle Size**: Each route file contains only what's needed for that specific route
|
|
402
537
|
|
|
403
538
|
### Automatic Environment Detection
|
|
404
539
|
|
|
@@ -414,87 +549,671 @@ ViewLogicRouter({
|
|
|
414
549
|
});
|
|
415
550
|
```
|
|
416
551
|
|
|
417
|
-
##
|
|
552
|
+
## 🪶 Ultra-Lightweight Bundle
|
|
553
|
+
|
|
554
|
+
ViewLogic Router provides a complete routing solution in an incredibly small package:
|
|
555
|
+
|
|
556
|
+
### Size Comparison
|
|
557
|
+
- **ViewLogic Router**: 13KB gzipped (48KB minified)
|
|
558
|
+
- **Vue Router + Auth + i18n + Cache**: 50KB+ gzipped
|
|
559
|
+
|
|
560
|
+
### What's Included in 13KB
|
|
561
|
+
- ✅ Complete Vue 3 routing system
|
|
562
|
+
- ✅ Authentication & authorization
|
|
563
|
+
- ✅ Internationalization (i18n)
|
|
564
|
+
- ✅ Smart caching system
|
|
565
|
+
- ✅ Query parameter management
|
|
566
|
+
- ✅ Component lazy loading
|
|
567
|
+
- ✅ Layout system
|
|
568
|
+
- ✅ Error handling
|
|
569
|
+
- ✅ Development/production modes
|
|
570
|
+
- ✅ **Automatic data fetching with dataURL**
|
|
571
|
+
- ✅ **Revolutionary DynamicInclude & HtmlInclude components**
|
|
572
|
+
- ✅ **Automatic form handling with variable parameters**
|
|
573
|
+
- ✅ **10+ Built-in UI components (Button, Modal, Card, etc.)**
|
|
574
|
+
|
|
575
|
+
### Why So Small?
|
|
576
|
+
- **Zero Dependencies** - No external libraries required (except Vue 3)
|
|
577
|
+
- **Tree-Shakable** - Only includes what you use
|
|
578
|
+
- **Optimized Code** - Hand-crafted for minimal bundle size
|
|
579
|
+
- **Smart Bundling** - Efficient code organization and minification
|
|
580
|
+
|
|
581
|
+
### Performance Benefits
|
|
582
|
+
- **Faster Load Times** - 70% smaller than typical Vue router setups
|
|
583
|
+
- **Better UX** - Instant page loads with minimal JavaScript overhead
|
|
584
|
+
- **Mobile Optimized** - Perfect for mobile-first applications
|
|
585
|
+
- **CDN Friendly** - Small size ideal for CDN distribution
|
|
586
|
+
|
|
587
|
+
## 🏆 Performance Comparison
|
|
588
|
+
|
|
589
|
+
### Bundle Size Comparison
|
|
590
|
+
| Router System | Bundle Size (Gzipped) | Features Included |
|
|
591
|
+
|---------------|----------------------|------------------|
|
|
592
|
+
| **ViewLogic Router** | **13KB** | Routing + Auth + i18n + Cache + Query + Components |
|
|
593
|
+
| Vue Router | 12KB | Routing only |
|
|
594
|
+
| Vue Router + Pinia | 18KB | Routing + State |
|
|
595
|
+
| React Router | 15KB | Routing only |
|
|
596
|
+
| Next.js Router | 25KB+ | Routing + SSR |
|
|
597
|
+
| Nuxt Router | 30KB+ | Routing + SSR + Meta |
|
|
598
|
+
|
|
599
|
+
### Runtime Performance Comparison
|
|
600
|
+
|
|
601
|
+
#### Traditional SPA Routing
|
|
602
|
+
```
|
|
603
|
+
Route Change Process:
|
|
604
|
+
├── 1️⃣ Parse route
|
|
605
|
+
├── 2️⃣ Load component bundle
|
|
606
|
+
├── 3️⃣ Execute component code
|
|
607
|
+
├── 4️⃣ Load template (if separate)
|
|
608
|
+
├── 5️⃣ Load styles (if separate)
|
|
609
|
+
├── 6️⃣ Apply i18n translations
|
|
610
|
+
├── 7️⃣ Check authentication
|
|
611
|
+
└── 8️⃣ Render component
|
|
612
|
+
|
|
613
|
+
Total: Multiple operations + Bundle parsing
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
#### ViewLogic Router (Production)
|
|
617
|
+
```
|
|
618
|
+
Route Change Process:
|
|
619
|
+
├── 1️⃣ Load pre-built route bundle (all-in-one)
|
|
620
|
+
└── 2️⃣ Render component
|
|
621
|
+
|
|
622
|
+
Total: Single optimized operation
|
|
623
|
+
```
|
|
418
624
|
|
|
419
|
-
|
|
625
|
+
### Performance Advantages
|
|
626
|
+
- **🚀 75% Faster Loading** - Pre-bundled routes vs on-demand compilation
|
|
627
|
+
- **📦 Smaller Footprint** - 13KB includes everything others need 30KB+ for
|
|
628
|
+
- **⚡ Instant Navigation** - No build-time compilation in production
|
|
629
|
+
- **🎯 Route-Level Optimization** - Each route is independently optimized
|
|
630
|
+
- **💾 Superior Caching** - Route-level caching vs component-level caching
|
|
631
|
+
- **🔄 Zero Hydration** - No server-side rendering complexity
|
|
420
632
|
|
|
633
|
+
### Why ViewLogic Router Wins
|
|
634
|
+
1. **Pre-compilation**: Routes are pre-built, not compiled at runtime
|
|
635
|
+
2. **All-in-One Bundles**: View + Logic + Style in single optimized file
|
|
636
|
+
3. **Zero Dependencies**: No additional libraries needed for full functionality
|
|
637
|
+
4. **Smart Caching**: Route-level caching with intelligent invalidation
|
|
638
|
+
5. **Optimized Architecture**: Purpose-built for maximum performance
|
|
639
|
+
6. **Revolutionary Components**: DynamicInclude & HtmlInclude for dynamic content loading
|
|
640
|
+
|
|
641
|
+
## 🚀 Revolutionary Built-in Components
|
|
642
|
+
|
|
643
|
+
ViewLogic Router includes groundbreaking components that revolutionize how you handle dynamic content:
|
|
644
|
+
|
|
645
|
+
### DynamicInclude Component
|
|
646
|
+
```html
|
|
647
|
+
<!-- Dynamically load content from any URL -->
|
|
648
|
+
<DynamicInclude
|
|
649
|
+
page="login"
|
|
650
|
+
:use-cache="false"
|
|
651
|
+
loading-text="로그인 페이지 로딩 중..."
|
|
652
|
+
wrapper-class="test-dynamic-include"
|
|
653
|
+
:params="{
|
|
654
|
+
returnUrl: '/dashboard',
|
|
655
|
+
showWelcome: true,
|
|
656
|
+
theme: 'compact',
|
|
657
|
+
testMode: true
|
|
658
|
+
}"
|
|
659
|
+
/>
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
**Features:**
|
|
663
|
+
- **Dynamic URL Loading** - Load content from any REST API or URL
|
|
664
|
+
- **Parameter Injection** - Pass dynamic parameters to the URL
|
|
665
|
+
- **Event Handling** - React to loading states and errors
|
|
666
|
+
- **Slot Support** - Custom loading and error templates
|
|
667
|
+
- **Cache Integration** - Automatic caching with TTL support
|
|
668
|
+
|
|
669
|
+
### HtmlInclude Component
|
|
670
|
+
```html
|
|
671
|
+
<!-- Include raw HTML content with Vue reactivity -->
|
|
672
|
+
<HtmlInclude
|
|
673
|
+
src="/src/views/404.html"
|
|
674
|
+
:sanitize="true"
|
|
675
|
+
:use-cache="false"
|
|
676
|
+
loading-text="위젯 로딩 중..."
|
|
677
|
+
wrapper-class="test-html-include"
|
|
678
|
+
/>
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
**Features:**
|
|
682
|
+
- **Raw HTML Rendering** - Safely render dynamic HTML content
|
|
683
|
+
- **XSS Protection** - Built-in HTML sanitization
|
|
684
|
+
- **Vue Integration** - HTML content works with Vue reactivity
|
|
685
|
+
- **Fallback Support** - Default content when HTML is unavailable
|
|
686
|
+
- **Script Execution** - Optional JavaScript execution in HTML content
|
|
687
|
+
|
|
688
|
+
### Automatic Data Fetching with dataURL
|
|
689
|
+
|
|
690
|
+
ViewLogic Router includes revolutionary automatic data fetching that eliminates manual API calls in component lifecycle hooks.
|
|
691
|
+
|
|
692
|
+
#### Single API (Simple Usage)
|
|
421
693
|
```javascript
|
|
422
|
-
//
|
|
423
|
-
|
|
694
|
+
// src/logic/products/list.js
|
|
695
|
+
export default {
|
|
696
|
+
name: 'ProductsList',
|
|
697
|
+
dataURL: '/api/products', // ✨ Magic happens here!
|
|
698
|
+
data() {
|
|
699
|
+
return {
|
|
700
|
+
title: 'Our Products'
|
|
701
|
+
// products: [] - No need to declare, auto-populated from API
|
|
702
|
+
};
|
|
703
|
+
},
|
|
704
|
+
mounted() {
|
|
705
|
+
// Data is already fetched and available!
|
|
706
|
+
console.log('Products loaded:', this.products);
|
|
707
|
+
console.log('Loading state:', this.$dataLoading);
|
|
708
|
+
},
|
|
709
|
+
methods: {
|
|
710
|
+
async refreshData() {
|
|
711
|
+
// Manual refresh if needed
|
|
712
|
+
await this.$fetchData();
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
#### Multiple APIs (Advanced Usage) - 🆕 Revolutionary!
|
|
719
|
+
```javascript
|
|
720
|
+
// src/logic/dashboard/main.js
|
|
721
|
+
export default {
|
|
722
|
+
name: 'DashboardMain',
|
|
723
|
+
dataURL: {
|
|
724
|
+
products: '/api/products',
|
|
725
|
+
categories: '/api/categories',
|
|
726
|
+
stats: '/api/dashboard/stats',
|
|
727
|
+
user: '/api/user/profile'
|
|
728
|
+
}, // ✨ Multiple APIs with named data!
|
|
729
|
+
data() {
|
|
730
|
+
return {
|
|
731
|
+
title: 'Dashboard'
|
|
732
|
+
// products: [], categories: [], stats: {}, user: {}
|
|
733
|
+
// All auto-populated from respective APIs!
|
|
734
|
+
};
|
|
735
|
+
},
|
|
736
|
+
mounted() {
|
|
737
|
+
// All APIs called in parallel, data available by name!
|
|
738
|
+
console.log('Products:', this.products);
|
|
739
|
+
console.log('Categories:', this.categories);
|
|
740
|
+
console.log('Stats:', this.stats);
|
|
741
|
+
console.log('User:', this.user);
|
|
742
|
+
console.log('Loading state:', this.$dataLoading);
|
|
743
|
+
},
|
|
744
|
+
methods: {
|
|
745
|
+
async refreshProducts() {
|
|
746
|
+
// Refresh specific API only
|
|
747
|
+
await this.$fetchData('products');
|
|
748
|
+
},
|
|
749
|
+
async refreshStats() {
|
|
750
|
+
// Refresh specific API only
|
|
751
|
+
await this.$fetchData('stats');
|
|
752
|
+
},
|
|
753
|
+
async refreshAllData() {
|
|
754
|
+
// Refresh all APIs
|
|
755
|
+
await this.$fetchAllData();
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
**Features:**
|
|
762
|
+
- **Zero-Config API Calls** - Just define `dataURL` and data is automatically fetched
|
|
763
|
+
- **🆕 Multiple API Support** - Define multiple APIs with custom names
|
|
764
|
+
- **🚀 Parallel Processing** - Multiple APIs called simultaneously for best performance
|
|
765
|
+
- **🎯 Selective Refresh** - Refresh specific APIs independently
|
|
766
|
+
- **Query Parameter Integration** - Current route parameters are automatically sent to all APIs
|
|
767
|
+
- **Loading State Management** - `$dataLoading` property automatically managed
|
|
768
|
+
- **Advanced Error Handling** - Per-API error handling with detailed events
|
|
769
|
+
- **Named Data Storage** - Each API result stored with its defined name
|
|
770
|
+
- **Event Support** - `@data-loaded` and `@data-error` events with detailed info
|
|
771
|
+
|
|
772
|
+
### Why These Components Are Revolutionary
|
|
773
|
+
|
|
774
|
+
#### Traditional Approach Problems
|
|
775
|
+
```javascript
|
|
776
|
+
// Traditional Vue way - complex and verbose for API calls
|
|
777
|
+
export default {
|
|
778
|
+
data() {
|
|
779
|
+
return {
|
|
780
|
+
products: [],
|
|
781
|
+
loading: false,
|
|
782
|
+
error: null
|
|
783
|
+
};
|
|
784
|
+
},
|
|
785
|
+
async mounted() {
|
|
786
|
+
await this.loadProducts();
|
|
787
|
+
},
|
|
788
|
+
methods: {
|
|
789
|
+
async loadProducts() {
|
|
790
|
+
this.loading = true;
|
|
791
|
+
this.error = null;
|
|
792
|
+
try {
|
|
793
|
+
const response = await fetch('/api/products');
|
|
794
|
+
if (!response.ok) throw new Error('Failed to fetch');
|
|
795
|
+
const data = await response.json();
|
|
796
|
+
this.products = data.products || data;
|
|
797
|
+
// Manual error handling, loading states, etc.
|
|
798
|
+
} catch (error) {
|
|
799
|
+
this.error = error.message;
|
|
800
|
+
console.error('Failed to load products:', error);
|
|
801
|
+
} finally {
|
|
802
|
+
this.loading = false;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
424
807
|
|
|
425
|
-
//
|
|
426
|
-
|
|
808
|
+
// For dynamic content loading - even more complex
|
|
809
|
+
async loadDynamicContent() {
|
|
810
|
+
this.loading = true;
|
|
811
|
+
try {
|
|
812
|
+
const response = await fetch(`/api/content/${this.contentId}`);
|
|
813
|
+
const data = await response.json();
|
|
814
|
+
this.content = data.html;
|
|
815
|
+
this.$nextTick(() => {
|
|
816
|
+
// Manual DOM manipulation needed
|
|
817
|
+
this.bindEvents();
|
|
818
|
+
});
|
|
819
|
+
} catch (error) {
|
|
820
|
+
this.error = error;
|
|
821
|
+
} finally {
|
|
822
|
+
this.loading = false;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
```
|
|
427
826
|
|
|
428
|
-
|
|
827
|
+
#### ViewLogic Router Way - Revolutionary Simplicity
|
|
828
|
+
```javascript
|
|
829
|
+
// Automatic API fetching - just define dataURL!
|
|
830
|
+
export default {
|
|
831
|
+
dataURL: '/api/products', // ✨ That's it!
|
|
832
|
+
data() {
|
|
833
|
+
return {
|
|
834
|
+
title: 'Our Products'
|
|
835
|
+
// No need for products:[], loading:false, error:null
|
|
836
|
+
};
|
|
837
|
+
},
|
|
838
|
+
mounted() {
|
|
839
|
+
// Data already fetched and available
|
|
840
|
+
console.log('Products:', this.products);
|
|
841
|
+
console.log('Loading:', this.$dataLoading);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
429
844
|
```
|
|
430
845
|
|
|
431
|
-
|
|
846
|
+
### Use Cases
|
|
432
847
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
848
|
+
#### Automatic Data Fetching (dataURL)
|
|
849
|
+
|
|
850
|
+
**Single API Usage:**
|
|
851
|
+
- **🛒 Product Listings** - `dataURL: '/api/products'` automatically loads and populates product data
|
|
852
|
+
- **👤 User Profiles** - `dataURL: '/api/user'` fetches user information with authentication
|
|
853
|
+
- **📊 Dashboard Data** - `dataURL: '/api/dashboard/stats'` loads analytics data
|
|
854
|
+
- **📰 Article Content** - `dataURL: '/api/articles'` populates blog posts or news
|
|
855
|
+
- **🔍 Search Results** - Query parameters automatically sent to search API
|
|
856
|
+
|
|
857
|
+
**🆕 Multiple API Usage (Revolutionary!):**
|
|
858
|
+
- **📊 Dashboard Pages** - `dataURL: { stats: '/api/stats', users: '/api/users', orders: '/api/orders' }`
|
|
859
|
+
- **🛒 E-commerce Pages** - `dataURL: { products: '/api/products', cart: '/api/cart', wishlist: '/api/wishlist' }`
|
|
860
|
+
- **👥 Social Media** - `dataURL: { posts: '/api/posts', friends: '/api/friends', notifications: '/api/notifications' }`
|
|
861
|
+
- **📱 Admin Panels** - `dataURL: { analytics: '/api/analytics', logs: '/api/logs', settings: '/api/settings' }`
|
|
862
|
+
- **🎯 Landing Pages** - `dataURL: { hero: '/api/hero-content', testimonials: '/api/testimonials', features: '/api/features' }`
|
|
863
|
+
|
|
864
|
+
#### Dynamic Components
|
|
865
|
+
- **📰 Dynamic Content Management** - Load blog posts, news articles dynamically
|
|
866
|
+
- **🛒 Product Details** - Fetch product information on-demand
|
|
867
|
+
- **📊 Dashboard Widgets** - Load dashboard components from APIs
|
|
868
|
+
- **📝 Form Builders** - Dynamic form generation from configuration
|
|
869
|
+
- **🎨 Template Systems** - CMS-driven content rendering
|
|
870
|
+
- **📱 Micro-frontends** - Load remote components seamlessly
|
|
871
|
+
|
|
872
|
+
### Advantages Over Other Solutions
|
|
873
|
+
| Feature | ViewLogic Router | React Suspense | Vue Async Components |
|
|
874
|
+
|---------|------------------|----------------|----------------------|
|
|
875
|
+
| **Auto Data Fetching** | ✅ `dataURL` property | ❌ Manual fetch logic | ❌ Manual fetch logic |
|
|
876
|
+
| **Query Parameter Integration** | ✅ Automatic API params | ❌ Manual URL building | ❌ Manual URL building |
|
|
877
|
+
| **Dynamic URLs** | ✅ Built-in | ❌ Manual implementation | ❌ Manual implementation |
|
|
878
|
+
| **Parameter Injection** | ✅ Automatic | ❌ Manual | ❌ Manual |
|
|
879
|
+
| **Loading State Management** | ✅ `$dataLoading` auto-managed | ✅ Suspense | ❌ Manual state |
|
|
880
|
+
| **Error Boundaries** | ✅ Built-in slots + events | ✅ ErrorBoundary | ❌ Manual |
|
|
881
|
+
| **HTML Sanitization** | ✅ Built-in | ❌ External library | ❌ External library |
|
|
882
|
+
| **Cache Integration** | ✅ Automatic | ❌ Manual | ❌ Manual |
|
|
883
|
+
|
|
884
|
+
These components eliminate the need for complex state management and manual DOM manipulation, making dynamic content loading as simple as using a regular component.
|
|
885
|
+
|
|
886
|
+
## 📝 Automatic Form Handling with Variable Parameters
|
|
887
|
+
|
|
888
|
+
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!
|
|
889
|
+
|
|
890
|
+
### Basic Form Handling
|
|
891
|
+
|
|
892
|
+
```html
|
|
893
|
+
<!-- src/views/contact.html -->
|
|
894
|
+
<div class="contact-page">
|
|
895
|
+
<h1>Contact Us</h1>
|
|
896
|
+
<form action="/api/contact" method="POST">
|
|
897
|
+
<input type="text" name="name" required placeholder="Your Name">
|
|
898
|
+
<input type="email" name="email" required placeholder="Your Email">
|
|
899
|
+
<textarea name="message" required placeholder="Your Message"></textarea>
|
|
900
|
+
<button type="submit">Send Message</button>
|
|
901
|
+
</form>
|
|
902
|
+
</div>
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
```javascript
|
|
906
|
+
// src/logic/contact.js
|
|
907
|
+
export default {
|
|
908
|
+
name: 'ContactPage',
|
|
909
|
+
mounted() {
|
|
910
|
+
// Forms are automatically bound - no additional code needed!
|
|
911
|
+
// Form submission will automatically POST to /api/contact
|
|
912
|
+
console.log('Form handling is automatic!');
|
|
913
|
+
}
|
|
914
|
+
};
|
|
441
915
|
```
|
|
442
916
|
|
|
443
|
-
###
|
|
917
|
+
### Variable Parameter Forms - 🆕 Revolutionary!
|
|
918
|
+
|
|
919
|
+
The most powerful feature is **variable parameter support** in action URLs. You can use simple template syntax to inject dynamic values:
|
|
920
|
+
|
|
444
921
|
```html
|
|
445
|
-
|
|
446
|
-
<
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
<
|
|
450
|
-
|
|
451
|
-
<
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
<
|
|
922
|
+
<!-- Dynamic form actions with variable parameters -->
|
|
923
|
+
<form action="/api/users/{userId}/posts" method="POST"
|
|
924
|
+
data-success="handlePostSuccess"
|
|
925
|
+
data-error="handlePostError">
|
|
926
|
+
<input type="text" name="title" required placeholder="Post Title">
|
|
927
|
+
<textarea name="content" required placeholder="Post Content"></textarea>
|
|
928
|
+
<button type="submit">Create Post</button>
|
|
929
|
+
</form>
|
|
930
|
+
|
|
931
|
+
<!-- Order update with dynamic order ID -->
|
|
932
|
+
<form action="/api/orders/{orderId}/update" method="PUT"
|
|
933
|
+
data-success="orderUpdated"
|
|
934
|
+
data-redirect="/orders">
|
|
935
|
+
<input type="number" name="quantity" required>
|
|
936
|
+
<select name="status">
|
|
937
|
+
<option value="pending">Pending</option>
|
|
938
|
+
<option value="processing">Processing</option>
|
|
939
|
+
<option value="completed">Completed</option>
|
|
940
|
+
</select>
|
|
941
|
+
<button type="submit">Update Order</button>
|
|
942
|
+
</form>
|
|
943
|
+
|
|
944
|
+
<!-- File upload support -->
|
|
945
|
+
<form action="/api/profile/{userId}/avatar" method="POST" enctype="multipart/form-data"
|
|
946
|
+
data-success="avatarUploaded">
|
|
947
|
+
<input type="file" name="avatar" accept="image/*" required>
|
|
948
|
+
<button type="submit">Upload Avatar</button>
|
|
949
|
+
</form>
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
```javascript
|
|
953
|
+
// Component logic - parameters are resolved automatically
|
|
954
|
+
export default {
|
|
955
|
+
name: 'UserProfile',
|
|
956
|
+
data() {
|
|
957
|
+
return {
|
|
958
|
+
userId: 123, // {userId} will be replaced with this value
|
|
959
|
+
orderId: 456 // {orderId} will be replaced with this value
|
|
960
|
+
};
|
|
961
|
+
},
|
|
962
|
+
methods: {
|
|
963
|
+
handlePostSuccess(response) {
|
|
964
|
+
console.log('Post created successfully!', response);
|
|
965
|
+
},
|
|
966
|
+
orderUpdated(response) {
|
|
967
|
+
console.log('Order updated!', response);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
};
|
|
971
|
+
```
|
|
972
|
+
|
|
973
|
+
### How Parameter Resolution Works
|
|
974
|
+
|
|
975
|
+
Parameters are resolved automatically from multiple sources in this order:
|
|
976
|
+
|
|
977
|
+
1. **Route Parameters**: `this.getParam('paramName')` - from URL query parameters
|
|
978
|
+
2. **Component Data**: `this.paramName` - from component's data properties
|
|
979
|
+
3. **Computed Properties**: `this.paramName` - from component's computed properties
|
|
980
|
+
|
|
981
|
+
```javascript
|
|
982
|
+
// Component example
|
|
983
|
+
export default {
|
|
984
|
+
name: 'UserProfile',
|
|
985
|
+
data() {
|
|
986
|
+
return {
|
|
987
|
+
userId: 123, // Available as {userId} in action URLs
|
|
988
|
+
productId: 456 // Available as {productId} in action URLs
|
|
989
|
+
};
|
|
990
|
+
},
|
|
991
|
+
computed: {
|
|
992
|
+
currentOrderId() { // Available as {currentOrderId} in action URLs
|
|
993
|
+
return this.getParam('orderId') || this.defaultOrderId;
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
mounted() {
|
|
997
|
+
// Route parameters also work: /user-profile?userId=789
|
|
998
|
+
// {userId} will use 789 from URL, or fall back to data() value of 123
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
### Event Handlers and Callbacks
|
|
1004
|
+
|
|
1005
|
+
Define success and error handlers using data attributes:
|
|
1006
|
+
|
|
1007
|
+
```html
|
|
1008
|
+
<form action="/api/newsletter/subscribe" method="POST"
|
|
1009
|
+
data-success="subscriptionSuccess"
|
|
1010
|
+
data-error="subscriptionError"
|
|
1011
|
+
data-redirect="/thank-you">
|
|
1012
|
+
<input type="email" name="email" required>
|
|
1013
|
+
<button type="submit">Subscribe</button>
|
|
1014
|
+
</form>
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
```javascript
|
|
1018
|
+
// src/logic/newsletter.js
|
|
1019
|
+
export default {
|
|
1020
|
+
name: 'NewsletterPage',
|
|
1021
|
+
methods: {
|
|
1022
|
+
subscriptionSuccess(response, formData) {
|
|
1023
|
+
console.log('Subscription successful!', response);
|
|
1024
|
+
this.$toast('Thank you for subscribing!', 'success');
|
|
1025
|
+
// Form will automatically redirect to /thank-you
|
|
1026
|
+
},
|
|
1027
|
+
subscriptionError(error, formData) {
|
|
1028
|
+
console.error('Subscription failed:', error);
|
|
1029
|
+
this.$toast('Subscription failed. Please try again.', 'error');
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
```
|
|
1034
|
+
|
|
1035
|
+
### Complete Form Options
|
|
1036
|
+
|
|
1037
|
+
```html
|
|
1038
|
+
<!-- All available data attributes -->
|
|
1039
|
+
<form action="/api/complex/{{getParam('id')}}" method="POST"
|
|
1040
|
+
data-success="handleSuccess" <!-- Success callback method -->
|
|
1041
|
+
data-error="handleError" <!-- Error callback method -->
|
|
1042
|
+
data-redirect="/success" <!-- Auto-redirect on success -->
|
|
1043
|
+
data-confirm="Are you sure?" <!-- Confirmation dialog -->
|
|
1044
|
+
data-loading="Processing..." <!-- Loading message -->
|
|
1045
|
+
enctype="multipart/form-data"> <!-- File upload support -->
|
|
459
1046
|
|
|
460
|
-
<
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
routesPath: '/routes', // Routes folder at root level
|
|
465
|
-
i18nPath: '/i18n', // i18n folder at root level
|
|
466
|
-
cacheMode: 'session', // Enable session caching
|
|
467
|
-
useComponents: true,
|
|
468
|
-
useI18n: true
|
|
469
|
-
});
|
|
470
|
-
</script>
|
|
471
|
-
</body>
|
|
472
|
-
</html>
|
|
1047
|
+
<input type="text" name="title" required>
|
|
1048
|
+
<input type="file" name="attachment" accept=".pdf,.doc">
|
|
1049
|
+
<button type="submit">Submit</button>
|
|
1050
|
+
</form>
|
|
473
1051
|
```
|
|
474
1052
|
|
|
475
|
-
###
|
|
1053
|
+
### Authentication Integration
|
|
1054
|
+
|
|
1055
|
+
Forms automatically include authentication tokens when available:
|
|
1056
|
+
|
|
1057
|
+
```html
|
|
1058
|
+
<!-- Authentication token automatically added for authenticated users -->
|
|
1059
|
+
<form action="/api/protected/resource" method="POST">
|
|
1060
|
+
<input type="text" name="data" required>
|
|
1061
|
+
<button type="submit">Save Protected Data</button>
|
|
1062
|
+
</form>
|
|
476
1063
|
```
|
|
477
|
-
production/
|
|
478
|
-
├── index.html
|
|
479
|
-
├── i18n/ # Language files
|
|
480
|
-
│ ├── ko.json
|
|
481
|
-
│ └── en.json
|
|
482
|
-
├── css/
|
|
483
|
-
│ └── base.css # Global styles
|
|
484
|
-
├── js/ # Optional (can use CDN instead)
|
|
485
|
-
│ ├── viewlogic-router.umd.js
|
|
486
|
-
│ └── viewlogic-router.min.js
|
|
487
|
-
├── routes/ # Built route bundles
|
|
488
|
-
│ ├── home.js # Bundled: view + logic + style
|
|
489
|
-
│ ├── about.js
|
|
490
|
-
│ └── products/
|
|
491
|
-
│ ├── list.js
|
|
492
|
-
│ └── detail.js
|
|
493
|
-
└── assets/
|
|
494
|
-
├── images/
|
|
495
|
-
└── fonts/
|
|
496
1064
|
|
|
497
|
-
|
|
1065
|
+
```javascript
|
|
1066
|
+
// Authentication token automatically included in headers:
|
|
1067
|
+
// Authorization: Bearer <user-token>
|
|
1068
|
+
// No additional code needed!
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
### Form Validation
|
|
1072
|
+
|
|
1073
|
+
Built-in client-side validation with custom validation support:
|
|
1074
|
+
|
|
1075
|
+
```html
|
|
1076
|
+
<!-- HTML5 validation attributes work automatically -->
|
|
1077
|
+
<form action="/api/user/register" method="POST" data-success="registrationSuccess">
|
|
1078
|
+
<input type="email" name="email" required
|
|
1079
|
+
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$">
|
|
1080
|
+
<input type="password" name="password" required minlength="8">
|
|
1081
|
+
<input type="password" name="confirmPassword" required>
|
|
1082
|
+
<button type="submit">Register</button>
|
|
1083
|
+
</form>
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
### Real-World Examples
|
|
1087
|
+
|
|
1088
|
+
#### User Profile Update
|
|
1089
|
+
```html
|
|
1090
|
+
<!-- User profile with dynamic user ID -->
|
|
1091
|
+
<form action="/api/users/{userId}" method="PUT"
|
|
1092
|
+
data-success="profileUpdated"
|
|
1093
|
+
data-redirect="/profile?updated=true">
|
|
1094
|
+
<input type="text" name="firstName" :value="user.firstName">
|
|
1095
|
+
<input type="text" name="lastName" :value="user.lastName">
|
|
1096
|
+
<input type="email" name="email" :value="user.email">
|
|
1097
|
+
<button type="submit">Update Profile</button>
|
|
1098
|
+
</form>
|
|
1099
|
+
```
|
|
1100
|
+
|
|
1101
|
+
#### E-commerce Order Management
|
|
1102
|
+
```html
|
|
1103
|
+
<!-- Order status update with order ID from route -->
|
|
1104
|
+
<form action="/api/orders/{orderId}/status" method="PUT"
|
|
1105
|
+
data-success="orderStatusUpdated">
|
|
1106
|
+
<select name="status" required>
|
|
1107
|
+
<option value="pending">Pending</option>
|
|
1108
|
+
<option value="shipped">Shipped</option>
|
|
1109
|
+
<option value="delivered">Delivered</option>
|
|
1110
|
+
</select>
|
|
1111
|
+
<textarea name="notes" placeholder="Optional notes"></textarea>
|
|
1112
|
+
<button type="submit">Update Status</button>
|
|
1113
|
+
</form>
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
#### Blog Post Creation
|
|
1117
|
+
```html
|
|
1118
|
+
<!-- Create post for specific category -->
|
|
1119
|
+
<form action="/api/categories/{categoryId}/posts" method="POST"
|
|
1120
|
+
data-success="postCreated"
|
|
1121
|
+
data-redirect="/posts">
|
|
1122
|
+
<input type="text" name="title" required>
|
|
1123
|
+
<textarea name="content" required></textarea>
|
|
1124
|
+
<input type="file" name="featured_image" accept="image/*">
|
|
1125
|
+
<button type="submit">Create Post</button>
|
|
1126
|
+
</form>
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
### Advantages Over Traditional Form Handling
|
|
1130
|
+
|
|
1131
|
+
| Feature | Traditional Vue/React | ViewLogic Router |
|
|
1132
|
+
|---------|----------------------|------------------|
|
|
1133
|
+
| **Setup Required** | Manual event handlers + API calls | ✅ Zero setup - just add `action` |
|
|
1134
|
+
| **Variable Parameters** | Manual string interpolation | ✅ Template syntax with function evaluation |
|
|
1135
|
+
| **Authentication** | Manual token handling | ✅ Automatic token injection |
|
|
1136
|
+
| **File Uploads** | Complex FormData handling | ✅ Automatic multipart support |
|
|
1137
|
+
| **Loading States** | Manual loading management | ✅ Automatic loading indicators |
|
|
1138
|
+
| **Error Handling** | Custom error logic | ✅ Built-in error callbacks |
|
|
1139
|
+
| **Validation** | External validation libraries | ✅ HTML5 + custom validation |
|
|
1140
|
+
| **Redirect Logic** | Manual navigation code | ✅ `data-redirect` attribute |
|
|
1141
|
+
|
|
1142
|
+
### Code Comparison: Traditional vs ViewLogic
|
|
1143
|
+
|
|
1144
|
+
**Traditional Approach** (30+ lines):
|
|
1145
|
+
```javascript
|
|
1146
|
+
// Lots of boilerplate for simple form
|
|
1147
|
+
export default {
|
|
1148
|
+
data() { return { form: {}, loading: false, error: null }; },
|
|
1149
|
+
methods: {
|
|
1150
|
+
async submitForm() {
|
|
1151
|
+
// 20+ lines of fetch, error handling, tokens, etc.
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
```
|
|
1156
|
+
|
|
1157
|
+
**ViewLogic Approach** (5 lines):
|
|
1158
|
+
```html
|
|
1159
|
+
<form action="/api/contact" data-success="handleSuccess">
|
|
1160
|
+
<input name="name" required>
|
|
1161
|
+
<button type="submit">Send</button>
|
|
1162
|
+
</form>
|
|
1163
|
+
```
|
|
1164
|
+
```javascript
|
|
1165
|
+
export default {
|
|
1166
|
+
methods: {
|
|
1167
|
+
handleSuccess(response) { /* success handling */ }
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
**Result**: 80% less code with more features (auto-auth, validation, error handling).
|
|
1173
|
+
|
|
1174
|
+
## 🔗 Query-Only Parameter System
|
|
1175
|
+
|
|
1176
|
+
ViewLogic Router uses **only query parameters** - no complex path parameters like `/users/:id`. Everything is simple query-based: `/users?id=123`.
|
|
1177
|
+
|
|
1178
|
+
### Key Benefits
|
|
1179
|
+
1. **Simple URLs**: `/product?id=123&category=electronics` (clear and readable)
|
|
1180
|
+
2. **Consistent Access**: Always use `this.getParam('id')` - never mix path/query
|
|
1181
|
+
3. **No Route Config**: No complex route definitions needed
|
|
1182
|
+
4. **SEO Friendly**: Descriptive parameter names in URLs
|
|
1183
|
+
|
|
1184
|
+
### Usage Example
|
|
1185
|
+
```javascript
|
|
1186
|
+
// Navigate
|
|
1187
|
+
this.navigateTo('products', { id: 123, category: 'electronics' });
|
|
1188
|
+
// → /products?id=123&category=electronics
|
|
1189
|
+
|
|
1190
|
+
// Access in component
|
|
1191
|
+
export default {
|
|
1192
|
+
mounted() {
|
|
1193
|
+
const id = this.getParam('id'); // Get parameter
|
|
1194
|
+
const category = this.getParam('category', 'all'); // With default
|
|
1195
|
+
const allParams = this.getParams(); // Get all parameters
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
## 🛡️ Error Handling
|
|
1202
|
+
|
|
1203
|
+
Built-in comprehensive error handling with automatic 404 detection, graceful component loading failures, and parameter validation with fallbacks.
|
|
1204
|
+
|
|
1205
|
+
## 🚀 Production Deployment
|
|
1206
|
+
|
|
1207
|
+
1. **Build**: `npm run build` - Combines view + logic + style into optimized route bundles
|
|
1208
|
+
2. **Deploy**: Set `environment: 'production'` and use CDN or local files
|
|
1209
|
+
3. **Structure**: Deploy `routes/`, `css/`, `i18n/` folders (exclude `src/`)
|
|
1210
|
+
|
|
1211
|
+
**CDN Usage:**
|
|
1212
|
+
```html
|
|
1213
|
+
<script src="https://cdn.jsdelivr.net/npm/viewlogic/dist/viewlogic-router.umd.js"></script>
|
|
1214
|
+
<script>
|
|
1215
|
+
ViewLogicRouter({ environment: 'production' }).mount('#app');
|
|
1216
|
+
</script>
|
|
498
1217
|
```
|
|
499
1218
|
|
|
500
1219
|
## 🤝 Contributing
|