viewlogic 1.1.1 → 1.1.3
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 +212 -512
- package/dist/viewlogic-router.js +159 -40
- package/dist/viewlogic-router.js.map +3 -3
- package/dist/viewlogic-router.min.js +3 -3
- package/dist/viewlogic-router.min.js.map +3 -3
- package/package.json +2 -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,174 @@ const config = {
|
|
|
257
260
|
};
|
|
258
261
|
```
|
|
259
262
|
|
|
260
|
-
|
|
263
|
+
### 🏗️ Subfolder Deployment Support
|
|
261
264
|
|
|
262
|
-
|
|
265
|
+
ViewLogic Router supports deployment in subfolders with smart path resolution:
|
|
263
266
|
|
|
264
267
|
```javascript
|
|
265
|
-
//
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
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']);
|
|
277
|
-
|
|
278
|
-
// Authentication (if enabled)
|
|
279
|
-
router.authManager.login(token);
|
|
280
|
-
router.authManager.logout();
|
|
281
|
-
const isAuth = router.authManager.isAuthenticated();
|
|
282
|
-
|
|
283
|
-
// Internationalization (if enabled)
|
|
284
|
-
router.i18nManager.setLanguage('en');
|
|
285
|
-
const t = router.i18nManager.translate('welcome.message');
|
|
268
|
+
// Root deployment: https://example.com/
|
|
269
|
+
ViewLogicRouter({
|
|
270
|
+
basePath: '/src', // → https://example.com/src
|
|
271
|
+
routesPath: '/routes', // → https://example.com/routes
|
|
272
|
+
i18nPath: '/i18n' // → https://example.com/i18n
|
|
273
|
+
});
|
|
286
274
|
|
|
287
|
-
//
|
|
288
|
-
|
|
275
|
+
// Subfolder deployment: https://example.com/myapp/
|
|
276
|
+
ViewLogicRouter({
|
|
277
|
+
basePath: 'src', // → https://example.com/myapp/src (relative)
|
|
278
|
+
routesPath: 'routes', // → https://example.com/myapp/routes (relative)
|
|
279
|
+
i18nPath: 'i18n', // → https://example.com/myapp/i18n (relative)
|
|
280
|
+
});
|
|
289
281
|
|
|
290
|
-
//
|
|
291
|
-
|
|
282
|
+
// Mixed paths: https://example.com/projects/myapp/
|
|
283
|
+
ViewLogicRouter({
|
|
284
|
+
basePath: './src', // → https://example.com/projects/myapp/src
|
|
285
|
+
routesPath: '../shared/routes', // → https://example.com/projects/shared/routes
|
|
286
|
+
i18nPath: '/global/i18n' // → https://example.com/global/i18n (absolute)
|
|
287
|
+
});
|
|
292
288
|
```
|
|
293
289
|
|
|
294
|
-
|
|
290
|
+
**Path Resolution Rules:**
|
|
291
|
+
- **Absolute paths** (`/path`) → `https://domain.com/path`
|
|
292
|
+
- **Relative paths** (`path`, `./path`) → Resolved from current page location
|
|
293
|
+
- **Parent paths** (`../path`) → Navigate up directory levels
|
|
294
|
+
- **HTTP URLs** → Used as-is (no processing)
|
|
295
295
|
|
|
296
|
-
|
|
296
|
+
### 🔄 Hash vs History Mode in Subfolders
|
|
297
297
|
|
|
298
|
-
|
|
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
|
-
```
|
|
298
|
+
Both routing modes work seamlessly in subfolder deployments:
|
|
361
299
|
|
|
362
|
-
|
|
300
|
+
```javascript
|
|
301
|
+
// Hash Mode (recommended for subfolders)
|
|
302
|
+
// URL: https://example.com/myapp/#/products?id=123
|
|
303
|
+
ViewLogicRouter({
|
|
304
|
+
mode: 'hash' // Works anywhere, no server config needed
|
|
305
|
+
});
|
|
363
306
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
307
|
+
// History Mode (requires server configuration)
|
|
308
|
+
// URL: https://example.com/myapp/products?id=123
|
|
309
|
+
ViewLogicRouter({
|
|
310
|
+
mode: 'history' // Cleaner URLs, needs server setup
|
|
311
|
+
});
|
|
312
|
+
```
|
|
367
313
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
314
|
+
**History Mode Server Configuration:**
|
|
315
|
+
```nginx
|
|
316
|
+
# Nginx - redirect all subfolder requests to index.html
|
|
317
|
+
location /myapp/ {
|
|
318
|
+
try_files $uri $uri/ /myapp/index.html;
|
|
319
|
+
}
|
|
320
|
+
```
|
|
371
321
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
- `$getCookie(name)` - Get specific cookie value
|
|
322
|
+
```apache
|
|
323
|
+
# Apache .htaccess in /myapp/ folder
|
|
324
|
+
RewriteEngine On
|
|
325
|
+
RewriteBase /myapp/
|
|
326
|
+
RewriteRule ^index\.html$ - [L]
|
|
327
|
+
RewriteCond %{REQUEST_FILENAME} !-f
|
|
328
|
+
RewriteCond %{REQUEST_FILENAME} !-d
|
|
329
|
+
RewriteRule . /myapp/index.html [L]
|
|
330
|
+
```
|
|
382
331
|
|
|
383
|
-
|
|
384
|
-
- `$t(key, params)` - Translate text with optional parameters
|
|
332
|
+
## 📖 Complete API Documentation
|
|
385
333
|
|
|
386
|
-
|
|
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
|
|
334
|
+
For comprehensive API documentation including all methods, configuration options, and detailed examples, see:
|
|
391
335
|
|
|
392
|
-
|
|
336
|
+
**📚 [Complete API Reference →](./docs/index.md)**
|
|
393
337
|
|
|
394
|
-
|
|
338
|
+
### Quick API Overview
|
|
395
339
|
|
|
396
340
|
```javascript
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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
|
-
```
|
|
341
|
+
// Basic router usage
|
|
342
|
+
const router = new ViewLogicRouter({ environment: 'development' });
|
|
343
|
+
router.navigateTo('products', { id: 123, category: 'electronics' });
|
|
344
|
+
const current = router.getCurrentRoute();
|
|
410
345
|
|
|
411
|
-
|
|
346
|
+
// In route components - global methods automatically available:
|
|
347
|
+
export default {
|
|
348
|
+
dataURL: '/api/products', // Auto-fetch data
|
|
349
|
+
mounted() {
|
|
350
|
+
const id = this.getParam('id'); // Get parameter
|
|
351
|
+
this.navigateTo('detail', { id }); // Navigate
|
|
352
|
+
console.log('Data loaded:', this.products); // From dataURL
|
|
353
|
+
if (this.$isAuthenticated()) { /* auth check */ }
|
|
354
|
+
const text = this.$t('welcome.message'); // i18n
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
```
|
|
412
358
|
|
|
413
|
-
|
|
359
|
+
### Key Global Methods (Auto-available in all route components)
|
|
360
|
+
- **Navigation**: `navigateTo()`, `getCurrentRoute()`
|
|
361
|
+
- **Parameters**: `getParams()`, `getParam(key, defaultValue)`
|
|
362
|
+
- **Data Fetching**: `$fetchData()`, `$fetchAllData()` (with dataURL)
|
|
363
|
+
- **Authentication**: `$isAuthenticated()`, `$getToken()`, `$logout()`
|
|
364
|
+
- **Forms**: Auto-binding with `action` attribute and `{param}` templates
|
|
365
|
+
- **i18n**: `$t(key, params)` for translations
|
|
414
366
|
|
|
367
|
+
### Auto-Injected Properties
|
|
415
368
|
```javascript
|
|
416
|
-
//
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
// Also available as
|
|
420
|
-
window.createRouter(config);
|
|
421
|
-
window.ViewLogicRouter(config);
|
|
369
|
+
// Automatically available in every route component:
|
|
370
|
+
// currentRoute, $query, $lang, $dataLoading
|
|
422
371
|
```
|
|
423
372
|
|
|
424
|
-
## 🎯 View-Logic Separation
|
|
373
|
+
## 🎯 View-Logic Separation: Core Philosophy in Action
|
|
425
374
|
|
|
426
|
-
|
|
375
|
+
ViewLogic Router's fundamental philosophy of **View-Logic Separation** creates clear boundaries between concerns:
|
|
427
376
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
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
|
-
```
|
|
377
|
+
### Philosophy Benefits
|
|
378
|
+
- **🎨 Pure Presentation**: Views contain only HTML - no mixed logic or scripts
|
|
379
|
+
- **🧠 Pure Logic**: JavaScript components focus solely on business logic
|
|
380
|
+
- **⚡ Zero Build Required**: Work directly with separate files in development
|
|
381
|
+
- **🔄 Hot Reload**: Instant changes without compilation or bundling
|
|
442
382
|
|
|
443
|
-
|
|
383
|
+
### File Structure (Core Philosophy)
|
|
384
|
+
- **View**: `src/views/products.html` - Pure HTML template
|
|
385
|
+
- **Logic**: `src/logic/products.js` - Pure Vue component logic
|
|
386
|
+
- **Style**: `src/styles/products.css` - Pure CSS styles
|
|
387
|
+
|
|
388
|
+
### Example: Philosophy in Practice
|
|
444
389
|
```javascript
|
|
390
|
+
// src/logic/products.js - Pure business logic
|
|
445
391
|
export default {
|
|
446
392
|
name: 'ProductsList',
|
|
447
|
-
dataURL: '/api/products', //
|
|
393
|
+
dataURL: '/api/products', // Auto-fetch data
|
|
448
394
|
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);
|
|
395
|
+
return { title: 'Our Products' };
|
|
458
396
|
},
|
|
459
397
|
methods: {
|
|
460
|
-
formatPrice(price) {
|
|
461
|
-
return new Intl.NumberFormat('ko-KR', {
|
|
462
|
-
style: 'currency',
|
|
463
|
-
currency: 'KRW'
|
|
464
|
-
}).format(price);
|
|
465
|
-
},
|
|
466
398
|
viewDetail(id) {
|
|
467
|
-
this.navigateTo('
|
|
468
|
-
},
|
|
469
|
-
async refreshProducts() {
|
|
470
|
-
// Manual refresh if needed
|
|
471
|
-
await this.$fetchData();
|
|
399
|
+
this.navigateTo('product-detail', { id });
|
|
472
400
|
}
|
|
473
401
|
}
|
|
474
402
|
};
|
|
475
403
|
```
|
|
476
404
|
|
|
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
|
-
}
|
|
405
|
+
### Production: Automatic Optimization
|
|
406
|
+
All separate files automatically combine into optimized bundles in `routes/` folder - maintaining the development philosophy while optimizing for production.
|
|
500
407
|
|
|
501
|
-
|
|
502
|
-
font-weight: bold;
|
|
503
|
-
color: #2196F3;
|
|
504
|
-
}
|
|
505
|
-
```
|
|
408
|
+
## 🔄 Zero Build Development vs Optimized Production
|
|
506
409
|
|
|
507
|
-
|
|
410
|
+
ViewLogic Router's **Zero Build Development** (core philosophy) vs optimized production:
|
|
508
411
|
|
|
509
|
-
|
|
412
|
+
| Mode | Philosophy | Files | Requests | Experience |
|
|
413
|
+
|------|------------|-------|----------|------------|
|
|
414
|
+
| **Development** | **Zero Build Required** | Separate files | 4 per route | **Real-time, instant changes** |
|
|
415
|
+
| **Production** | **Optimized Performance** | Single bundle | 1 per route | **Lightning-fast loading** |
|
|
510
416
|
|
|
511
417
|
```javascript
|
|
512
|
-
//
|
|
513
|
-
|
|
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
|
|
522
|
-
|
|
523
|
-
### Development Mode Benefits
|
|
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)
|
|
418
|
+
// Zero Build Development (Core Philosophy)
|
|
419
|
+
ViewLogicRouter({ environment: 'development' }); // Work directly with source files
|
|
529
420
|
|
|
530
|
-
|
|
531
|
-
|
|
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
|
|
537
|
-
|
|
538
|
-
### Automatic Environment Detection
|
|
539
|
-
|
|
540
|
-
```javascript
|
|
541
|
-
// Development Mode (loads from src/)
|
|
542
|
-
ViewLogicRouter({
|
|
543
|
-
environment: 'development',
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// Production Mode (loads from dist/routes/)
|
|
547
|
-
ViewLogicRouter({
|
|
548
|
-
environment: 'production',
|
|
549
|
-
});
|
|
421
|
+
// Optimized Production
|
|
422
|
+
ViewLogicRouter({ environment: 'production' }); // Use pre-built bundles
|
|
550
423
|
```
|
|
551
424
|
|
|
425
|
+
### Zero Build Development Benefits
|
|
426
|
+
- ⚡ **Instant Changes** - Edit HTML/JS/CSS and see changes immediately
|
|
427
|
+
- 🚀 **Zero Setup** - No webpack, vite, or build tools required
|
|
428
|
+
- 🎯 **True Hot Reload** - Files load directly from src/ folder
|
|
429
|
+
- 🛠️ **Pure Development** - Focus on code, not build configuration
|
|
430
|
+
|
|
552
431
|
## 🪶 Ultra-Lightweight Bundle
|
|
553
432
|
|
|
554
433
|
ViewLogic Router provides a complete routing solution in an incredibly small package:
|
|
@@ -771,117 +650,22 @@ export default {
|
|
|
771
650
|
|
|
772
651
|
### Why These Components Are Revolutionary
|
|
773
652
|
|
|
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
|
-
}
|
|
653
|
+
**Traditional Approach**: 30+ lines of loading states, error handling, and manual API calls.
|
|
807
654
|
|
|
808
|
-
|
|
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
|
-
```
|
|
655
|
+
**ViewLogic Approach**: `dataURL: '/api/products'` - That's it! Data automatically fetched and available as `this.products`.
|
|
826
656
|
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
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
|
-
}
|
|
844
|
-
```
|
|
657
|
+
### Common Use Cases
|
|
658
|
+
- **Single API**: `dataURL: '/api/products'` - Product listings, user profiles, articles
|
|
659
|
+
- **Multiple APIs**: `dataURL: { stats: '/api/stats', users: '/api/users' }` - Dashboards, admin panels
|
|
660
|
+
- **Dynamic Content**: `<DynamicInclude page="login" :params="{ theme: 'compact' }" />`
|
|
661
|
+
- **HTML Includes**: `<HtmlInclude src="/widgets/weather.html" :sanitize="true" />`
|
|
845
662
|
|
|
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.
|
|
663
|
+
### Advantages
|
|
664
|
+
- ✅ **Auto Data Fetching** with `dataURL` property (others: manual logic)
|
|
665
|
+
- ✅ **Parameter Integration** - Query params sent automatically
|
|
666
|
+
- ✅ **Loading States** - `$dataLoading` auto-managed
|
|
667
|
+
- ✅ **Built-in Security** - HTML sanitization included
|
|
668
|
+
- ✅ **Zero Setup** - Works immediately without configuration
|
|
885
669
|
|
|
886
670
|
## 📝 Automatic Form Handling with Variable Parameters
|
|
887
671
|
|
|
@@ -1000,194 +784,105 @@ export default {
|
|
|
1000
784
|
};
|
|
1001
785
|
```
|
|
1002
786
|
|
|
1003
|
-
### Event Handlers
|
|
1004
|
-
|
|
1005
|
-
Define success and error handlers using data attributes:
|
|
1006
|
-
|
|
787
|
+
### Event Handlers
|
|
1007
788
|
```html
|
|
1008
|
-
<form action="/api/
|
|
1009
|
-
data-success="subscriptionSuccess"
|
|
1010
|
-
data-error="subscriptionError"
|
|
1011
|
-
data-redirect="/thank-you">
|
|
789
|
+
<form action="/api/subscribe" method="POST"
|
|
790
|
+
data-success="subscriptionSuccess" data-error="subscriptionError">
|
|
1012
791
|
<input type="email" name="email" required>
|
|
1013
792
|
<button type="submit">Subscribe</button>
|
|
1014
793
|
</form>
|
|
1015
794
|
```
|
|
1016
|
-
|
|
1017
795
|
```javascript
|
|
1018
|
-
// src/logic/newsletter.js
|
|
1019
796
|
export default {
|
|
1020
|
-
name: 'NewsletterPage',
|
|
1021
797
|
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
|
-
}
|
|
798
|
+
subscriptionSuccess(response) { this.$toast('Success!', 'success'); },
|
|
799
|
+
subscriptionError(error) { this.$toast('Failed!', 'error'); }
|
|
1031
800
|
}
|
|
1032
801
|
};
|
|
1033
802
|
```
|
|
1034
803
|
|
|
1035
|
-
###
|
|
1036
|
-
|
|
804
|
+
### Form Options
|
|
1037
805
|
```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">
|
|
806
|
+
<form action="/api/resource/{id}" method="POST"
|
|
807
|
+
data-success="handleSuccess" data-error="handleError"
|
|
808
|
+
data-redirect="/success" data-confirm="Sure?"
|
|
809
|
+
enctype="multipart/form-data">
|
|
810
|
+
<input name="title" required>
|
|
811
|
+
<input type="file" name="file" accept=".pdf">
|
|
1049
812
|
<button type="submit">Submit</button>
|
|
1050
813
|
</form>
|
|
1051
814
|
```
|
|
1052
815
|
|
|
1053
816
|
### Authentication Integration
|
|
1054
|
-
|
|
1055
|
-
Forms automatically include authentication tokens when available:
|
|
1056
|
-
|
|
1057
817
|
```html
|
|
1058
|
-
<!--
|
|
818
|
+
<!-- Auth tokens automatically included for authenticated users -->
|
|
1059
819
|
<form action="/api/protected/resource" method="POST">
|
|
1060
|
-
<input
|
|
1061
|
-
<button type="submit">Save
|
|
820
|
+
<input name="data" required>
|
|
821
|
+
<button type="submit">Save</button>
|
|
1062
822
|
</form>
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
```javascript
|
|
1066
|
-
// Authentication token automatically included in headers:
|
|
1067
|
-
// Authorization: Bearer <user-token>
|
|
1068
|
-
// No additional code needed!
|
|
823
|
+
<!-- Authorization: Bearer <token> header added automatically -->
|
|
1069
824
|
```
|
|
1070
825
|
|
|
1071
826
|
### Form Validation
|
|
1072
|
-
|
|
1073
|
-
Built-in client-side validation with custom validation support:
|
|
1074
|
-
|
|
1075
827
|
```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>
|
|
828
|
+
<!-- HTML5 + custom validation -->
|
|
829
|
+
<form action="/api/register" method="POST">
|
|
830
|
+
<input type="email" name="email" required pattern="...">
|
|
831
|
+
<input type="password" name="password" minlength="8" required>
|
|
1082
832
|
<button type="submit">Register</button>
|
|
1083
833
|
</form>
|
|
1084
834
|
```
|
|
1085
835
|
|
|
1086
|
-
### Real-World Examples
|
|
1087
|
-
|
|
1088
|
-
#### User Profile Update
|
|
836
|
+
### Real-World Form Examples
|
|
1089
837
|
```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>
|
|
838
|
+
<!-- User profile with dynamic parameters -->
|
|
839
|
+
<form action="/api/users/{userId}" method="PUT" data-success="profileUpdated">
|
|
840
|
+
<input name="firstName" required>
|
|
841
|
+
<button type="submit">Update</button>
|
|
1098
842
|
</form>
|
|
1099
|
-
```
|
|
1100
843
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
<!-- Order status update with order ID from route -->
|
|
1104
|
-
<form action="/api/orders/{orderId}/status" method="PUT"
|
|
1105
|
-
data-success="orderStatusUpdated">
|
|
844
|
+
<!-- Order management -->
|
|
845
|
+
<form action="/api/orders/{orderId}/status" method="PUT">
|
|
1106
846
|
<select name="status" required>
|
|
1107
847
|
<option value="pending">Pending</option>
|
|
1108
848
|
<option value="shipped">Shipped</option>
|
|
1109
|
-
<option value="delivered">Delivered</option>
|
|
1110
849
|
</select>
|
|
1111
|
-
<
|
|
1112
|
-
<button type="submit">Update Status</button>
|
|
850
|
+
<button type="submit">Update</button>
|
|
1113
851
|
</form>
|
|
1114
852
|
```
|
|
1115
853
|
|
|
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
|
-
```
|
|
854
|
+
### Form Handling Advantages
|
|
855
|
+
- ✅ **Zero Setup** - Just add `action` attribute vs manual event handlers
|
|
856
|
+
- ✅ **Variable Parameters** - `{userId}` template syntax vs manual interpolation
|
|
857
|
+
- ✅ **Auto Authentication** - Tokens injected automatically
|
|
858
|
+
- ✅ **File Uploads** - Automatic multipart support
|
|
859
|
+
- ✅ **Built-in Validation** - HTML5 + custom functions
|
|
1128
860
|
|
|
1129
|
-
###
|
|
861
|
+
### Code Comparison
|
|
862
|
+
**Traditional**: 30+ lines of boilerplate for forms, API calls, loading states
|
|
863
|
+
**ViewLogic**: 5 lines with `action` attribute + callback method
|
|
864
|
+
**Result**: 80% less code, more features included
|
|
1130
865
|
|
|
1131
|
-
|
|
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 |
|
|
866
|
+
## 🔗 Query-Based Parameter System: Revolutionary Simplicity
|
|
1141
867
|
|
|
1142
|
-
|
|
868
|
+
ViewLogic Router's **Query-Based Parameter System** is a key feature that eliminates routing complexity:
|
|
1143
869
|
|
|
1144
|
-
**
|
|
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
|
-
```
|
|
870
|
+
**Philosophy**: **Everything is query-based** - no complex path parameters like `/users/:id`. Just simple, clean URLs: `/users?id=123`.
|
|
1171
871
|
|
|
1172
|
-
|
|
872
|
+
### Revolutionary Benefits
|
|
873
|
+
1. **📍 Simple URLs**: `/product?id=123&category=electronics` (clear and readable)
|
|
874
|
+
2. **🎯 Consistent Access**: Always use `this.getParam('id')` - never mix path/query paradigms
|
|
875
|
+
3. **⚡ No Route Configuration**: No complex route definitions or parameter mappings needed
|
|
876
|
+
4. **🔍 SEO Friendly**: Descriptive parameter names make URLs self-documenting
|
|
877
|
+
5. **🌐 Universal Compatibility**: Query parameters work everywhere - no framework lock-in
|
|
1173
878
|
|
|
1174
|
-
|
|
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
|
|
879
|
+
### Simple Usage Example
|
|
1185
880
|
```javascript
|
|
1186
|
-
// Navigate
|
|
881
|
+
// Navigate - simple and intuitive
|
|
1187
882
|
this.navigateTo('products', { id: 123, category: 'electronics' });
|
|
1188
883
|
// → /products?id=123&category=electronics
|
|
1189
884
|
|
|
1190
|
-
// Access
|
|
885
|
+
// Access parameters - always the same way
|
|
1191
886
|
export default {
|
|
1192
887
|
mounted() {
|
|
1193
888
|
const id = this.getParam('id'); // Get parameter
|
|
@@ -1197,6 +892,11 @@ export default {
|
|
|
1197
892
|
};
|
|
1198
893
|
```
|
|
1199
894
|
|
|
895
|
+
### Why Query-Based is Revolutionary
|
|
896
|
+
**Traditional Routers**: Complex path parameters (`/users/:id/posts/:postId`) require route configuration, parameter extraction logic, and mixed paradigms.
|
|
897
|
+
|
|
898
|
+
**ViewLogic Router**: Simple query parameters (`/users?id=123&postId=456`) work universally with consistent `getParam()` access.
|
|
899
|
+
|
|
1200
900
|
|
|
1201
901
|
## 🛡️ Error Handling
|
|
1202
902
|
|