viewlogic 1.1.1 → 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 +154 -523
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
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
16
|
|
|
17
17
|
## 🆕 Latest Updates (v1.1.1)
|
|
18
18
|
|
|
@@ -24,37 +24,40 @@
|
|
|
24
24
|
|
|
25
25
|
## 🎯 Core Philosophy: Simplicity Through Design
|
|
26
26
|
|
|
27
|
-
ViewLogic Router revolutionizes Vue development with two core principles:
|
|
27
|
+
ViewLogic Router revolutionizes Vue development with two fundamental core principles:
|
|
28
28
|
|
|
29
29
|
### 🎭 View-Logic Separation
|
|
30
|
-
|
|
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.
|
|
31
31
|
|
|
32
|
-
###
|
|
33
|
-
**
|
|
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.
|
|
34
34
|
|
|
35
|
-
## ✨ Features
|
|
35
|
+
## ✨ Key Features
|
|
36
36
|
|
|
37
|
-
-
|
|
38
|
-
-
|
|
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
|
|
39
42
|
- ⚡ **Optimized Production** - Pre-built individual route bundles for lightning-fast production
|
|
40
43
|
- 📁 **Intuitive Structure** - Organized folder structure for views, logic, styles, layouts, and components
|
|
41
|
-
- 🔄 **Hot Development** - See changes instantly without compilation
|
|
42
|
-
- 📦 **Smart Production Build** - Each route becomes an optimized JavaScript bundle
|
|
43
|
-
- 🛠️ **Built-in Components** - Preloaded UI components including revolutionary DynamicInclude & HtmlInclude
|
|
44
|
-
- 🌐 **i18n Ready** - Built-in internationalization support
|
|
45
|
-
- 🔐 **Authentication** - Built-in auth management system
|
|
46
44
|
- 💾 **Smart Caching** - Intelligent route and component caching
|
|
47
|
-
-
|
|
48
|
-
-
|
|
45
|
+
- 🔐 **Authentication** - Built-in auth management system
|
|
46
|
+
- 🌐 **i18n Ready** - Built-in internationalization support
|
|
49
47
|
|
|
50
48
|
## 📦 Installation
|
|
51
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:
|
|
52
59
|
```bash
|
|
53
60
|
npm install viewlogic
|
|
54
|
-
# or
|
|
55
|
-
yarn add viewlogic
|
|
56
|
-
# or
|
|
57
|
-
pnpm add viewlogic
|
|
58
61
|
```
|
|
59
62
|
|
|
60
63
|
## 🚀 Quick Start
|
|
@@ -80,7 +83,7 @@ pnpm add viewlogic
|
|
|
80
83
|
// Development mode - loads files directly from src/
|
|
81
84
|
ViewLogicRouter({
|
|
82
85
|
environment: 'development',
|
|
83
|
-
})
|
|
86
|
+
});
|
|
84
87
|
</script>
|
|
85
88
|
</body>
|
|
86
89
|
</html>
|
|
@@ -109,7 +112,7 @@ pnpm add viewlogic
|
|
|
109
112
|
environment: 'production',
|
|
110
113
|
useI18n: true,
|
|
111
114
|
logLevel: 'error' // Only log errors
|
|
112
|
-
})
|
|
115
|
+
});
|
|
113
116
|
</script>
|
|
114
117
|
</body>
|
|
115
118
|
</html>
|
|
@@ -257,298 +260,105 @@ const config = {
|
|
|
257
260
|
};
|
|
258
261
|
```
|
|
259
262
|
|
|
260
|
-
## 📖 API
|
|
261
|
-
|
|
262
|
-
### Router Instance Methods
|
|
263
|
-
|
|
264
|
-
```javascript
|
|
265
|
-
// Navigation
|
|
266
|
-
router.navigateTo('routeName', { param: 'value' });
|
|
267
|
-
router.navigateTo({ route: 'products', params: { id: 123 } });
|
|
268
|
-
|
|
269
|
-
// Get current route
|
|
270
|
-
const currentRoute = router.getCurrentRoute();
|
|
263
|
+
## 📖 Complete API Documentation
|
|
271
264
|
|
|
272
|
-
|
|
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
|
+
For comprehensive API documentation including all methods, configuration options, and detailed examples, see:
|
|
277
266
|
|
|
278
|
-
|
|
279
|
-
router.authManager.login(token);
|
|
280
|
-
router.authManager.logout();
|
|
281
|
-
const isAuth = router.authManager.isAuthenticated();
|
|
267
|
+
**📚 [Complete API Reference →](./docs/index.md)**
|
|
282
268
|
|
|
283
|
-
|
|
284
|
-
router.i18nManager.setLanguage('en');
|
|
285
|
-
const t = router.i18nManager.translate('welcome.message');
|
|
286
|
-
|
|
287
|
-
// Cache management
|
|
288
|
-
router.cacheManager.clearAll();
|
|
289
|
-
|
|
290
|
-
// Cleanup
|
|
291
|
-
router.destroy();
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
### Global Functions Available in Route Components
|
|
295
|
-
|
|
296
|
-
Every route component automatically has access to these global functions:
|
|
269
|
+
### Quick API Overview
|
|
297
270
|
|
|
298
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:
|
|
299
278
|
export default {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
}
|
|
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
|
|
358
286
|
}
|
|
359
287
|
};
|
|
360
288
|
```
|
|
361
289
|
|
|
362
|
-
###
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
367
|
-
|
|
368
|
-
|
|
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:
|
|
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
|
|
395
297
|
|
|
298
|
+
### Auto-Injected Properties
|
|
396
299
|
```javascript
|
|
397
|
-
|
|
398
|
-
|
|
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
|
-
}
|
|
300
|
+
// Automatically available in every route component:
|
|
301
|
+
// currentRoute, $query, $lang, $dataLoading
|
|
409
302
|
```
|
|
410
303
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
After initialization, the router is available globally:
|
|
304
|
+
## 🎯 View-Logic Separation: Core Philosophy in Action
|
|
414
305
|
|
|
415
|
-
|
|
416
|
-
// UMD build automatically sets window.router
|
|
417
|
-
window.router.navigateTo('about');
|
|
418
|
-
|
|
419
|
-
// Also available as
|
|
420
|
-
window.createRouter(config);
|
|
421
|
-
window.ViewLogicRouter(config);
|
|
422
|
-
```
|
|
306
|
+
ViewLogic Router's fundamental philosophy of **View-Logic Separation** creates clear boundaries between concerns:
|
|
423
307
|
|
|
424
|
-
|
|
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
|
|
425
313
|
|
|
426
|
-
###
|
|
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
|
|
427
318
|
|
|
428
|
-
|
|
429
|
-
```html
|
|
430
|
-
<div class="products-page">
|
|
431
|
-
<h1>{{ title }}</h1>
|
|
432
|
-
<div class="product-grid">
|
|
433
|
-
<div v-for="product in products" :key="product.id" class="product-card">
|
|
434
|
-
<img :src="product.image" :alt="product.name">
|
|
435
|
-
<h3>{{ product.name }}</h3>
|
|
436
|
-
<p class="price">{{ formatPrice(product.price) }}</p>
|
|
437
|
-
<button @click="viewDetail(product.id)">View Detail</button>
|
|
438
|
-
</div>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
#### Logic File (src/logic/products/list.js)
|
|
319
|
+
### Example: Philosophy in Practice
|
|
444
320
|
```javascript
|
|
321
|
+
// src/logic/products.js - Pure business logic
|
|
445
322
|
export default {
|
|
446
323
|
name: 'ProductsList',
|
|
447
|
-
dataURL: '/api/products', //
|
|
324
|
+
dataURL: '/api/products', // Auto-fetch data
|
|
448
325
|
data() {
|
|
449
|
-
return {
|
|
450
|
-
title: 'Our Products'
|
|
451
|
-
// products: [] - No need! Auto-populated from dataURL
|
|
452
|
-
};
|
|
453
|
-
},
|
|
454
|
-
mounted() {
|
|
455
|
-
// Products already loaded from dataURL!
|
|
456
|
-
console.log('Products loaded:', this.products);
|
|
457
|
-
console.log('Loading state:', this.$dataLoading);
|
|
326
|
+
return { title: 'Our Products' };
|
|
458
327
|
},
|
|
459
328
|
methods: {
|
|
460
|
-
formatPrice(price) {
|
|
461
|
-
return new Intl.NumberFormat('ko-KR', {
|
|
462
|
-
style: 'currency',
|
|
463
|
-
currency: 'KRW'
|
|
464
|
-
}).format(price);
|
|
465
|
-
},
|
|
466
329
|
viewDetail(id) {
|
|
467
|
-
this.navigateTo('
|
|
468
|
-
},
|
|
469
|
-
async refreshProducts() {
|
|
470
|
-
// Manual refresh if needed
|
|
471
|
-
await this.$fetchData();
|
|
330
|
+
this.navigateTo('product-detail', { id });
|
|
472
331
|
}
|
|
473
332
|
}
|
|
474
333
|
};
|
|
475
334
|
```
|
|
476
335
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
.products-page {
|
|
480
|
-
padding: 20px;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
.product-grid {
|
|
484
|
-
display: grid;
|
|
485
|
-
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
|
486
|
-
gap: 20px;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.product-card {
|
|
490
|
-
border: 1px solid #e0e0e0;
|
|
491
|
-
border-radius: 8px;
|
|
492
|
-
padding: 15px;
|
|
493
|
-
transition: transform 0.2s;
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
.product-card:hover {
|
|
497
|
-
transform: translateY(-2px);
|
|
498
|
-
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
.price {
|
|
502
|
-
font-weight: bold;
|
|
503
|
-
color: #2196F3;
|
|
504
|
-
}
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
### Production Mode (Built Bundle)
|
|
508
|
-
|
|
509
|
-
After build, these files are automatically combined into a single optimized bundle:
|
|
510
|
-
|
|
511
|
-
```javascript
|
|
512
|
-
// routes/products/list.js (Auto-generated)
|
|
513
|
-
export default {
|
|
514
|
-
name: 'ProductsList',
|
|
515
|
-
template: `<div class="products-page">...`, // View injected
|
|
516
|
-
_style: `.products-page { ... }`, // Style injected
|
|
517
|
-
// ... logic code
|
|
518
|
-
}
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
## 🔄 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.
|
|
522
338
|
|
|
523
|
-
|
|
524
|
-
- **No Build Required**: Edit files and refresh browser to see changes
|
|
525
|
-
- **Clear Separation**: View, Logic, and Style in separate files for better organization
|
|
526
|
-
- **Easy Debugging**: Source maps and unminified code
|
|
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)
|
|
339
|
+
## 🔄 Zero Build Development vs Optimized Production
|
|
529
340
|
|
|
530
|
-
|
|
531
|
-
- **Optimized Bundles**: Each route is a single, minified JavaScript file
|
|
532
|
-
- **⚡ Superior Performance**: Single file request per route (all assets pre-bundled)
|
|
533
|
-
- **Faster Loading**: Pre-built bundles eliminate compilation overhead
|
|
534
|
-
- **Reduced Requests**: Combined view + logic + style in one file
|
|
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
|
|
341
|
+
ViewLogic Router's **Zero Build Development** (core philosophy) vs optimized production:
|
|
537
342
|
|
|
538
|
-
|
|
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** |
|
|
539
347
|
|
|
540
348
|
```javascript
|
|
541
|
-
// Development
|
|
542
|
-
ViewLogicRouter({
|
|
543
|
-
environment: 'development',
|
|
544
|
-
});
|
|
349
|
+
// Zero Build Development (Core Philosophy)
|
|
350
|
+
ViewLogicRouter({ environment: 'development' }); // Work directly with source files
|
|
545
351
|
|
|
546
|
-
// Production
|
|
547
|
-
ViewLogicRouter({
|
|
548
|
-
environment: 'production',
|
|
549
|
-
});
|
|
352
|
+
// Optimized Production
|
|
353
|
+
ViewLogicRouter({ environment: 'production' }); // Use pre-built bundles
|
|
550
354
|
```
|
|
551
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
|
+
|
|
552
362
|
## 🪶 Ultra-Lightweight Bundle
|
|
553
363
|
|
|
554
364
|
ViewLogic Router provides a complete routing solution in an incredibly small package:
|
|
@@ -771,117 +581,22 @@ export default {
|
|
|
771
581
|
|
|
772
582
|
### Why These Components Are Revolutionary
|
|
773
583
|
|
|
774
|
-
|
|
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
|
-
}
|
|
807
|
-
|
|
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
|
-
```
|
|
584
|
+
**Traditional Approach**: 30+ lines of loading states, error handling, and manual API calls.
|
|
826
585
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
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
|
-
}
|
|
844
|
-
```
|
|
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" />`
|
|
845
593
|
|
|
846
|
-
###
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
**
|
|
851
|
-
-
|
|
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.
|
|
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
|
|
885
600
|
|
|
886
601
|
## 📝 Automatic Form Handling with Variable Parameters
|
|
887
602
|
|
|
@@ -1000,194 +715,105 @@ export default {
|
|
|
1000
715
|
};
|
|
1001
716
|
```
|
|
1002
717
|
|
|
1003
|
-
### Event Handlers
|
|
1004
|
-
|
|
1005
|
-
Define success and error handlers using data attributes:
|
|
1006
|
-
|
|
718
|
+
### Event Handlers
|
|
1007
719
|
```html
|
|
1008
|
-
<form action="/api/
|
|
1009
|
-
data-success="subscriptionSuccess"
|
|
1010
|
-
data-error="subscriptionError"
|
|
1011
|
-
data-redirect="/thank-you">
|
|
720
|
+
<form action="/api/subscribe" method="POST"
|
|
721
|
+
data-success="subscriptionSuccess" data-error="subscriptionError">
|
|
1012
722
|
<input type="email" name="email" required>
|
|
1013
723
|
<button type="submit">Subscribe</button>
|
|
1014
724
|
</form>
|
|
1015
725
|
```
|
|
1016
|
-
|
|
1017
726
|
```javascript
|
|
1018
|
-
// src/logic/newsletter.js
|
|
1019
727
|
export default {
|
|
1020
|
-
name: 'NewsletterPage',
|
|
1021
728
|
methods: {
|
|
1022
|
-
subscriptionSuccess(response,
|
|
1023
|
-
|
|
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
|
-
}
|
|
729
|
+
subscriptionSuccess(response) { this.$toast('Success!', 'success'); },
|
|
730
|
+
subscriptionError(error) { this.$toast('Failed!', 'error'); }
|
|
1031
731
|
}
|
|
1032
732
|
};
|
|
1033
733
|
```
|
|
1034
734
|
|
|
1035
|
-
###
|
|
1036
|
-
|
|
735
|
+
### Form Options
|
|
1037
736
|
```html
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
data-success="
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
data-loading="Processing..." <!-- Loading message -->
|
|
1045
|
-
enctype="multipart/form-data"> <!-- File upload support -->
|
|
1046
|
-
|
|
1047
|
-
<input type="text" name="title" required>
|
|
1048
|
-
<input type="file" name="attachment" accept=".pdf,.doc">
|
|
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">
|
|
1049
743
|
<button type="submit">Submit</button>
|
|
1050
744
|
</form>
|
|
1051
745
|
```
|
|
1052
746
|
|
|
1053
747
|
### Authentication Integration
|
|
1054
|
-
|
|
1055
|
-
Forms automatically include authentication tokens when available:
|
|
1056
|
-
|
|
1057
748
|
```html
|
|
1058
|
-
<!--
|
|
749
|
+
<!-- Auth tokens automatically included for authenticated users -->
|
|
1059
750
|
<form action="/api/protected/resource" method="POST">
|
|
1060
|
-
<input
|
|
1061
|
-
<button type="submit">Save
|
|
751
|
+
<input name="data" required>
|
|
752
|
+
<button type="submit">Save</button>
|
|
1062
753
|
</form>
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
```javascript
|
|
1066
|
-
// Authentication token automatically included in headers:
|
|
1067
|
-
// Authorization: Bearer <user-token>
|
|
1068
|
-
// No additional code needed!
|
|
754
|
+
<!-- Authorization: Bearer <token> header added automatically -->
|
|
1069
755
|
```
|
|
1070
756
|
|
|
1071
757
|
### Form Validation
|
|
1072
|
-
|
|
1073
|
-
Built-in client-side validation with custom validation support:
|
|
1074
|
-
|
|
1075
758
|
```html
|
|
1076
|
-
<!-- HTML5
|
|
1077
|
-
<form action="/api/
|
|
1078
|
-
<input type="email" name="email" required
|
|
1079
|
-
|
|
1080
|
-
<input type="password" name="password" required minlength="8">
|
|
1081
|
-
<input type="password" name="confirmPassword" required>
|
|
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>
|
|
1082
763
|
<button type="submit">Register</button>
|
|
1083
764
|
</form>
|
|
1084
765
|
```
|
|
1085
766
|
|
|
1086
|
-
### Real-World Examples
|
|
1087
|
-
|
|
1088
|
-
#### User Profile Update
|
|
767
|
+
### Real-World Form Examples
|
|
1089
768
|
```html
|
|
1090
|
-
<!-- User profile with dynamic
|
|
1091
|
-
<form action="/api/users/{userId}" method="PUT"
|
|
1092
|
-
|
|
1093
|
-
|
|
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>
|
|
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>
|
|
1098
773
|
</form>
|
|
1099
|
-
```
|
|
1100
774
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
<!-- Order status update with order ID from route -->
|
|
1104
|
-
<form action="/api/orders/{orderId}/status" method="PUT"
|
|
1105
|
-
data-success="orderStatusUpdated">
|
|
775
|
+
<!-- Order management -->
|
|
776
|
+
<form action="/api/orders/{orderId}/status" method="PUT">
|
|
1106
777
|
<select name="status" required>
|
|
1107
778
|
<option value="pending">Pending</option>
|
|
1108
779
|
<option value="shipped">Shipped</option>
|
|
1109
|
-
<option value="delivered">Delivered</option>
|
|
1110
780
|
</select>
|
|
1111
|
-
<
|
|
1112
|
-
<button type="submit">Update Status</button>
|
|
781
|
+
<button type="submit">Update</button>
|
|
1113
782
|
</form>
|
|
1114
783
|
```
|
|
1115
784
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
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
|
-
```
|
|
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
|
|
1156
791
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
<button type="submit">Send</button>
|
|
1162
|
-
</form>
|
|
1163
|
-
```
|
|
1164
|
-
```javascript
|
|
1165
|
-
export default {
|
|
1166
|
-
methods: {
|
|
1167
|
-
handleSuccess(response) { /* success handling */ }
|
|
1168
|
-
}
|
|
1169
|
-
};
|
|
1170
|
-
```
|
|
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
|
|
1171
796
|
|
|
1172
|
-
|
|
797
|
+
## 🔗 Query-Based Parameter System: Revolutionary Simplicity
|
|
1173
798
|
|
|
1174
|
-
|
|
799
|
+
ViewLogic Router's **Query-Based Parameter System** is a key feature that eliminates routing complexity:
|
|
1175
800
|
|
|
1176
|
-
|
|
801
|
+
**Philosophy**: **Everything is query-based** - no complex path parameters like `/users/:id`. Just simple, clean URLs: `/users?id=123`.
|
|
1177
802
|
|
|
1178
|
-
###
|
|
1179
|
-
1.
|
|
1180
|
-
2.
|
|
1181
|
-
3.
|
|
1182
|
-
4.
|
|
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
|
|
1183
809
|
|
|
1184
|
-
### Usage Example
|
|
810
|
+
### Simple Usage Example
|
|
1185
811
|
```javascript
|
|
1186
|
-
// Navigate
|
|
812
|
+
// Navigate - simple and intuitive
|
|
1187
813
|
this.navigateTo('products', { id: 123, category: 'electronics' });
|
|
1188
814
|
// → /products?id=123&category=electronics
|
|
1189
815
|
|
|
1190
|
-
// Access
|
|
816
|
+
// Access parameters - always the same way
|
|
1191
817
|
export default {
|
|
1192
818
|
mounted() {
|
|
1193
819
|
const id = this.getParam('id'); // Get parameter
|
|
@@ -1197,6 +823,11 @@ export default {
|
|
|
1197
823
|
};
|
|
1198
824
|
```
|
|
1199
825
|
|
|
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.
|
|
828
|
+
|
|
829
|
+
**ViewLogic Router**: Simple query parameters (`/users?id=123&postId=456`) work universally with consistent `getParam()` access.
|
|
830
|
+
|
|
1200
831
|
|
|
1201
832
|
## 🛡️ Error Handling
|
|
1202
833
|
|
package/package.json
CHANGED