lego-dom 1.0.0 → 1.3.4
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/.legodom +87 -0
- package/CHANGELOG.md +87 -3
- package/cdn.html +10 -5
- package/docs/.vitepress/config.js +23 -7
- package/docs/api/config.md +95 -0
- package/docs/api/define.md +29 -2
- package/docs/api/directives.md +10 -2
- package/docs/api/index.md +1 -0
- package/docs/contributing/01-welcome.md +2 -0
- package/docs/contributing/02-registry.md +37 -3
- package/docs/contributing/06-init.md +13 -2
- package/docs/contributing/07-observer.md +3 -0
- package/docs/contributing/08-snap.md +15 -1
- package/docs/contributing/10-studs.md +3 -1
- package/docs/contributing/11-scanner.md +13 -0
- package/docs/contributing/12-render.md +32 -10
- package/docs/contributing/13-directives.md +19 -1
- package/docs/contributing/14-events.md +1 -1
- package/docs/contributing/15-router.md +49 -1
- package/docs/contributing/16-state.md +9 -10
- package/docs/contributing/17-legodom.md +1 -8
- package/docs/contributing/index.md +23 -4
- package/docs/examples/form.md +1 -1
- package/docs/examples/index.md +3 -3
- package/docs/examples/routing.md +10 -10
- package/docs/examples/sfc-showcase.md +1 -1
- package/docs/examples/todo-app.md +7 -7
- package/docs/guide/cdn-usage.md +44 -18
- package/docs/guide/components.md +18 -12
- package/docs/guide/directives.md +131 -22
- package/docs/guide/directory-structure.md +248 -0
- package/docs/guide/faq.md +210 -0
- package/docs/guide/getting-started.md +14 -10
- package/docs/guide/index.md +1 -1
- package/docs/guide/lifecycle.md +32 -0
- package/docs/guide/quick-start.md +4 -4
- package/docs/guide/reactivity.md +2 -2
- package/docs/guide/routing.md +69 -8
- package/docs/guide/server-side.md +134 -0
- package/docs/guide/sfc.md +96 -13
- package/docs/guide/templating.md +62 -57
- package/docs/index.md +9 -9
- package/docs/router/basic-routing.md +8 -8
- package/docs/router/cold-entry.md +2 -2
- package/docs/router/history.md +7 -7
- package/docs/router/index.md +1 -1
- package/docs/router/resolver.md +5 -5
- package/docs/router/surgical-swaps.md +5 -5
- package/docs/tutorial/01-project-setup.md +152 -0
- package/docs/tutorial/02-your-first-component.md +226 -0
- package/docs/tutorial/03-adding-routes.md +279 -0
- package/docs/tutorial/04-multi-page-app.md +329 -0
- package/docs/tutorial/05-state-and-globals.md +285 -0
- package/docs/tutorial/index.md +40 -0
- package/examples/vite-app/index.html +1 -0
- package/examples/vite-app/src/app.js +2 -2
- package/examples/vite-app/src/components/side-menu.lego +46 -0
- package/examples/vite-app/vite.config.js +2 -1
- package/main.js +261 -72
- package/main.min.js +7 -0
- package/monitoring-plugin.js +111 -0
- package/package.json +4 -2
- package/parse-lego.js +49 -22
- package/tests/error.test.js +74 -0
- package/tests/main.test.js +2 -2
- package/tests/memory.test.js +68 -0
- package/tests/monitoring.test.js +74 -0
- package/tests/naming.test.js +74 -0
- package/tests/parse-lego.test.js +2 -2
- package/tests/security.test.js +67 -0
- package/tests/server.test.js +114 -0
- package/tests/syntax.test.js +67 -0
- package/vite-plugin.js +3 -2
- package/docs/guide/contributing.md +0 -32
package/docs/router/resolver.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
# 06. Target Resolver: Scoping and Logic
|
|
3
3
|
|
|
4
|
-
In the previous chapters, we used `b-target` to send content to different parts of the page. But how does
|
|
4
|
+
In the previous chapters, we used `b-target` to send content to different parts of the page. But how does LegoDOM actually find those "holes" in a complex, nested DOM? This is where the **Target Resolver** comes in.
|
|
5
5
|
|
|
6
6
|
The Target Resolver is a prioritized logic engine that ensures your links always find the correct destination, even in massive applications with thousands of components.
|
|
7
7
|
|
|
@@ -16,11 +16,11 @@ In traditional JavaScript, if you use `document.querySelector('#detail-view')`,
|
|
|
16
16
|
|
|
17
17
|
## The Resolver Hierarchy
|
|
18
18
|
|
|
19
|
-
When you click a `b-link` with a `b-target`,
|
|
19
|
+
When you click a `b-link` with a `b-target`, LegoDOM follows a strict search order to resolve the target:
|
|
20
20
|
|
|
21
21
|
### 1. Local Component Scope (The Primary Search)
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
LegoDOM first looks for the target **inside the component that contains the link**.
|
|
24
24
|
|
|
25
25
|
If you use `b-target="email-view"`, Lego looks for an `<email-view>` tag _within the current parent shell_. This allows you to have multiple instances of the same layout on one screen without them interfering with each other.
|
|
26
26
|
|
|
@@ -58,7 +58,7 @@ For highly dynamic UIs, `b-target` can even be a function or a dynamic expressio
|
|
|
58
58
|
|
|
59
59
|
```
|
|
60
60
|
<!-- Logic decides the target based on screen size -->
|
|
61
|
-
<a href="/settings" b-link b-target="
|
|
61
|
+
<a href="/settings" b-link b-target="[[ isMobile ? '#main' : 'settings-pane' ]]">
|
|
62
62
|
Settings
|
|
63
63
|
</a>
|
|
64
64
|
|
|
@@ -66,7 +66,7 @@ For highly dynamic UIs, `b-target` can even be a function or a dynamic expressio
|
|
|
66
66
|
|
|
67
67
|
## Why This Matters
|
|
68
68
|
|
|
69
|
-
By prioritizing local tags over global IDs,
|
|
69
|
+
By prioritizing local tags over global IDs, LegoDOM encourages **Encapsulation**. Your components become "Black Boxes" that manage their own internal routing targets. This means you can take a complex "Messaging Shell" and drop it into a "Dashboard Shell" without changing a single line of routing code—the targets will still resolve correctly because they are scoped to their parents.
|
|
70
70
|
|
|
71
71
|
## Summary
|
|
72
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Surgical Swaps: Mastering b-target
|
|
2
2
|
|
|
3
|
-
The true power of
|
|
3
|
+
The true power of LegoDOM lies in its ability to perform **Surgical Swaps**. In a traditional application, clicking a link often causes the entire page to re-render, destroying the state of your sidebar, header, or scroll position.
|
|
4
4
|
|
|
5
5
|
With `b-target` (and optionally `b-link`), we can choose to update only a specific "fragment" of the page.
|
|
6
6
|
|
|
@@ -80,8 +80,8 @@ You can tell Lego to find a specific element by its ID and replace its contents.
|
|
|
80
80
|
<aside class="sidebar">
|
|
81
81
|
<div b-for="chat in threads">
|
|
82
82
|
<!-- Parent component (this shell) binds data to these links -->
|
|
83
|
-
<a href="/messaging/
|
|
84
|
-
|
|
83
|
+
<a href="/messaging/[[chat.id]]" b-target="#chat-window">
|
|
84
|
+
[[chat.userName]]
|
|
85
85
|
</a>
|
|
86
86
|
</div>
|
|
87
87
|
</aside>
|
|
@@ -110,7 +110,7 @@ Because Lego is built on Custom Elements, you can target a component tag directl
|
|
|
110
110
|
|
|
111
111
|
## How the Target Resolver Works
|
|
112
112
|
|
|
113
|
-
When you click a link with a `b-target`, the
|
|
113
|
+
When you click a link with a `b-target`, the LegoDOM **Target Resolver** follows a specific hierarchy:
|
|
114
114
|
|
|
115
115
|
1. **Local Scope**: It looks for the target inside the current component first. This prevents "ID collisions" if you have multiple instances of a layout.
|
|
116
116
|
|
|
@@ -123,7 +123,7 @@ When you click a link with a `b-target`, the LegoJS **Target Resolver** follows
|
|
|
123
123
|
|
|
124
124
|
## Smart History
|
|
125
125
|
|
|
126
|
-
Even though we are only swapping a small part of the DOM,
|
|
126
|
+
Even though we are only swapping a small part of the DOM, LegoDOM is smart enough to update the browser's address bar.
|
|
127
127
|
|
|
128
128
|
When a surgical swap happens, Lego saves the "target" information into the browser's history state (`history.state.legoTargets`). This means that when a user hits the **Back Button**, Lego knows exactly which fragment needs to be swapped back to its previous state.
|
|
129
129
|
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Step 1: Project Setup
|
|
2
|
+
|
|
3
|
+
Let's create a new LegoDOM project from scratch. By the end of this page, you'll have a fully configured development environment ready to build components.
|
|
4
|
+
|
|
5
|
+
## Create a New Project
|
|
6
|
+
|
|
7
|
+
Open your terminal and run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Create a new Vite project
|
|
11
|
+
npm create vite@latest my-lego-app -- --template vanilla
|
|
12
|
+
|
|
13
|
+
# Enter the project
|
|
14
|
+
cd my-lego-app
|
|
15
|
+
|
|
16
|
+
# Install LegoDOM
|
|
17
|
+
npm install lego-dom
|
|
18
|
+
|
|
19
|
+
# Install dependencies
|
|
20
|
+
npm install
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Configure Vite
|
|
24
|
+
|
|
25
|
+
Create or replace `vite.config.js` in your project root:
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
import { defineConfig } from 'vite';
|
|
29
|
+
import legoPlugin from 'lego-dom/vite-plugin';
|
|
30
|
+
|
|
31
|
+
export default defineConfig({
|
|
32
|
+
plugins: [
|
|
33
|
+
legoPlugin({
|
|
34
|
+
componentsDir: './src/components', // Where your .lego files live
|
|
35
|
+
include: ['**/*.lego'] // File pattern to match
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Project Structure
|
|
42
|
+
|
|
43
|
+
Create this folder structure:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
my-lego-app/
|
|
47
|
+
├── index.html ← Your app's entry HTML
|
|
48
|
+
├── src/
|
|
49
|
+
│ ├── app.js ← Your app's entry JavaScript ⭐
|
|
50
|
+
│ └── components/ ← Your .lego files go here
|
|
51
|
+
│ └── (empty for now)
|
|
52
|
+
├── vite.config.js ← Vite configuration
|
|
53
|
+
└── package.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
::: warning The Magic File: `app.js`
|
|
57
|
+
This is where **everything comes together**. Your routes, global state, and initialization all happen here. We'll build it in the next section.
|
|
58
|
+
:::
|
|
59
|
+
|
|
60
|
+
## Set Up Your Entry Point
|
|
61
|
+
|
|
62
|
+
Replace the contents of `src/app.js` (create it if it doesn't exist):
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// 1. Import the Lego core
|
|
66
|
+
import { Lego } from 'lego-dom';
|
|
67
|
+
|
|
68
|
+
// 2. Import the virtual module that auto-discovers .lego files
|
|
69
|
+
import registerComponents from 'virtual:lego-components';
|
|
70
|
+
|
|
71
|
+
// 3. Register all discovered components
|
|
72
|
+
registerComponents();
|
|
73
|
+
|
|
74
|
+
// 4. Define your routes (we'll add these soon!)
|
|
75
|
+
// Lego.route('/', 'home-page');
|
|
76
|
+
// Lego.route('/login', 'login-page');
|
|
77
|
+
|
|
78
|
+
// 5. Initialize the engine
|
|
79
|
+
await Lego.init();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> **What's happening here?**
|
|
83
|
+
> - Lines 1-3: Import LegoDOM and auto-register every `.lego` file in your `components/` folder
|
|
84
|
+
> - Line 4: Routes map URLs to components (commented out until we create them)
|
|
85
|
+
> - Line 5: `Lego.init()` starts the reactivity engine, routing, and DOM observation
|
|
86
|
+
|
|
87
|
+
## Set Up Your HTML
|
|
88
|
+
|
|
89
|
+
Replace `index.html`:
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<!DOCTYPE html>
|
|
93
|
+
<html lang="en">
|
|
94
|
+
<head>
|
|
95
|
+
<meta charset="UTF-8">
|
|
96
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
97
|
+
<title>My Lego App</title>
|
|
98
|
+
<style>
|
|
99
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
100
|
+
body {
|
|
101
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
102
|
+
background: #f5f5f5;
|
|
103
|
+
min-height: 100vh;
|
|
104
|
+
}
|
|
105
|
+
</style>
|
|
106
|
+
</head>
|
|
107
|
+
<body>
|
|
108
|
+
<!-- The router renders your page components here -->
|
|
109
|
+
<lego-router></lego-router>
|
|
110
|
+
|
|
111
|
+
<!-- Load your app -->
|
|
112
|
+
<script type="module" src="/src/app.js"></script>
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Run It
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm run dev
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Open `http://localhost:5173` in your browser. You'll see a blank page—that's expected! We haven't created any components yet.
|
|
124
|
+
|
|
125
|
+
## What You've Done
|
|
126
|
+
|
|
127
|
+
✅ Created a Vite project
|
|
128
|
+
✅ Installed LegoDOM
|
|
129
|
+
✅ Configured the Vite plugin
|
|
130
|
+
✅ Set up `app.js` with the Lego initialization pattern
|
|
131
|
+
✅ Added `<lego-router>` to your HTML
|
|
132
|
+
|
|
133
|
+
## The Key Insight
|
|
134
|
+
|
|
135
|
+
::: tip Where Config Goes: The Golden Rule
|
|
136
|
+
**Everything related to your app's setup goes in `app.js`:**
|
|
137
|
+
- Component registration → `registerComponents()`
|
|
138
|
+
- Route definitions → `Lego.route(...)`
|
|
139
|
+
- Global state → `Lego.globals.user = ...`
|
|
140
|
+
- Initialization → `Lego.init()`
|
|
141
|
+
|
|
142
|
+
Your `index.html` just needs `<lego-router>` and a script tag. That's it.
|
|
143
|
+
:::
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
<div style="display: flex; justify-content: space-between; margin-top: 3rem;">
|
|
148
|
+
<span></span>
|
|
149
|
+
<a href="./02-your-first-component" style="display: inline-block; background: #4CAF50; color: white; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: 600;">
|
|
150
|
+
Next: Your First Component →
|
|
151
|
+
</a>
|
|
152
|
+
</div>
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Step 2: Your First Component
|
|
2
|
+
|
|
3
|
+
Now let's create a component! By the end of this page, you'll understand the `.lego` file format and have a working home page.
|
|
4
|
+
|
|
5
|
+
## Create Your First `.lego` File
|
|
6
|
+
|
|
7
|
+
Create `src/components/home-page.lego`:
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<template>
|
|
11
|
+
<div class="hero">
|
|
12
|
+
<h1>[[ title ]]</h1>
|
|
13
|
+
<p>[[ subtitle ]]</p>
|
|
14
|
+
<button @click="handleClick()">[[ buttonText ]]</button>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<div class="features">
|
|
18
|
+
<div class="feature" b-for="feature in features">
|
|
19
|
+
<span class="icon">[[ feature.icon ]]</span>
|
|
20
|
+
<h3>[[ feature.title ]]</h3>
|
|
21
|
+
<p>[[ feature.description ]]</p>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<style>
|
|
27
|
+
self {
|
|
28
|
+
display: block;
|
|
29
|
+
min-height: 100vh;
|
|
30
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
31
|
+
color: white;
|
|
32
|
+
padding: 4rem 2rem;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.hero {
|
|
36
|
+
text-align: center;
|
|
37
|
+
max-width: 600px;
|
|
38
|
+
margin: 0 auto 4rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.hero h1 {
|
|
42
|
+
font-size: 3rem;
|
|
43
|
+
margin-bottom: 1rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.hero p {
|
|
47
|
+
font-size: 1.25rem;
|
|
48
|
+
opacity: 0.9;
|
|
49
|
+
margin-bottom: 2rem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.hero button {
|
|
53
|
+
background: white;
|
|
54
|
+
color: #667eea;
|
|
55
|
+
border: none;
|
|
56
|
+
padding: 1rem 2.5rem;
|
|
57
|
+
font-size: 1.1rem;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
border-radius: 50px;
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.hero button:hover {
|
|
65
|
+
transform: translateY(-2px);
|
|
66
|
+
box-shadow: 0 10px 20px rgba(0,0,0,0.2);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.features {
|
|
70
|
+
display: grid;
|
|
71
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
72
|
+
gap: 2rem;
|
|
73
|
+
max-width: 900px;
|
|
74
|
+
margin: 0 auto;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.feature {
|
|
78
|
+
background: rgba(255,255,255,0.1);
|
|
79
|
+
padding: 2rem;
|
|
80
|
+
border-radius: 16px;
|
|
81
|
+
text-align: center;
|
|
82
|
+
backdrop-filter: blur(10px);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.feature .icon {
|
|
86
|
+
font-size: 3rem;
|
|
87
|
+
display: block;
|
|
88
|
+
margin-bottom: 1rem;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.feature h3 {
|
|
92
|
+
margin-bottom: 0.5rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.feature p {
|
|
96
|
+
opacity: 0.8;
|
|
97
|
+
font-size: 0.9rem;
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
100
|
+
|
|
101
|
+
<script>
|
|
102
|
+
export default {
|
|
103
|
+
title: 'Welcome to My App',
|
|
104
|
+
subtitle: 'Built with LegoDOM – the tiny framework that loves developers',
|
|
105
|
+
buttonText: 'Get Started',
|
|
106
|
+
|
|
107
|
+
features: [
|
|
108
|
+
{ icon: '⚡', title: 'Lightning Fast', description: 'No virtual DOM overhead' },
|
|
109
|
+
{ icon: '🧩', title: 'Component-Based', description: 'Reusable building blocks' },
|
|
110
|
+
{ icon: '🎨', title: 'Scoped Styles', description: 'CSS that never leaks' }
|
|
111
|
+
],
|
|
112
|
+
|
|
113
|
+
handleClick() {
|
|
114
|
+
// We'll wire this up to navigation soon!
|
|
115
|
+
alert('Clicked! Next: we\'ll navigate to /login');
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
mounted() {
|
|
119
|
+
console.log('Home page mounted!');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
</script>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Understanding the Structure
|
|
126
|
+
|
|
127
|
+
Every `.lego` file has three sections:
|
|
128
|
+
|
|
129
|
+
### 1. `<template>` – Your HTML
|
|
130
|
+
|
|
131
|
+
```html
|
|
132
|
+
<template>
|
|
133
|
+
<h1>[[ title ]]</h1> <!-- Reactive text -->
|
|
134
|
+
<button @click="doSomething()"> <!-- Event binding -->
|
|
135
|
+
<div b-for="item in items"> <!-- Loop directive -->
|
|
136
|
+
</template>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 2. `<style>` – Scoped CSS
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<style>
|
|
143
|
+
self {
|
|
144
|
+
/* 'self' targets the component root (like :host) */
|
|
145
|
+
display: block;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
button {
|
|
149
|
+
/* These styles ONLY affect this component */
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 3. `<script>` – Logic & State
|
|
155
|
+
|
|
156
|
+
```html
|
|
157
|
+
<script>
|
|
158
|
+
export default {
|
|
159
|
+
// Reactive properties
|
|
160
|
+
title: 'Hello',
|
|
161
|
+
count: 0,
|
|
162
|
+
items: [],
|
|
163
|
+
|
|
164
|
+
// Methods
|
|
165
|
+
doSomething() {
|
|
166
|
+
this.count++; // Mutation triggers re-render!
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
// Lifecycle
|
|
170
|
+
mounted() {
|
|
171
|
+
console.log('Component is ready');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
</script>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Register the Route
|
|
178
|
+
|
|
179
|
+
Now update `src/app.js` to show your component:
|
|
180
|
+
|
|
181
|
+
```javascript{7-8}
|
|
182
|
+
import { Lego } from 'lego-dom';
|
|
183
|
+
import registerComponents from 'virtual:lego-components';
|
|
184
|
+
|
|
185
|
+
registerComponents();
|
|
186
|
+
|
|
187
|
+
// Add this line:
|
|
188
|
+
Lego.route('/', 'home-page');
|
|
189
|
+
|
|
190
|
+
await Lego.init();
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## See It Live
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
npm run dev
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Open `http://localhost:5173` and you'll see your beautiful home page!
|
|
200
|
+
|
|
201
|
+
## What You've Learned
|
|
202
|
+
|
|
203
|
+
✅ The three-section `.lego` file structure
|
|
204
|
+
✅ Template syntax: `[[ ]]` for data, `@click` for events, `b-for` for loops
|
|
205
|
+
✅ The `self` keyword for component root styling
|
|
206
|
+
✅ How to export state and methods from `<script>`
|
|
207
|
+
✅ Connecting a component to a route
|
|
208
|
+
|
|
209
|
+
## Key Pattern: Component → Route → Display
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
home-page.lego → Lego.route('/', 'home-page') → <lego-router> shows it
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The filename (minus `.lego`) becomes the component name. Routes map URLs to component names. The router displays the matched component.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
<div style="display: flex; justify-content: space-between; margin-top: 3rem;">
|
|
220
|
+
<a href="./01-project-setup" style="display: inline-block; background: #eee; color: #333; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: 600;">
|
|
221
|
+
← Previous: Project Setup
|
|
222
|
+
</a>
|
|
223
|
+
<a href="./03-adding-routes" style="display: inline-block; background: #4CAF50; color: white; padding: 0.75rem 1.5rem; border-radius: 6px; text-decoration: none; font-weight: 600;">
|
|
224
|
+
Next: Adding Routes →
|
|
225
|
+
</a>
|
|
226
|
+
</div>
|