lego-dom 0.0.7 → 0.0.9
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/.github/workflows/deploy-docs.yml +56 -0
- package/LICENSE +21 -0
- package/README.md +52 -314
- package/docs/.vitepress/config.js +107 -0
- package/docs/.vitepress/dist/404.html +22 -0
- package/docs/.vitepress/dist/api/define.html +35 -0
- package/docs/.vitepress/dist/api/directives.html +32 -0
- package/docs/.vitepress/dist/api/globals.html +27 -0
- package/docs/.vitepress/dist/api/index.html +25 -0
- package/docs/.vitepress/dist/api/lifecycle.html +38 -0
- package/docs/.vitepress/dist/api/route.html +34 -0
- package/docs/.vitepress/dist/api/vite-plugin.html +37 -0
- package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.js +11 -0
- package/docs/.vitepress/dist/assets/api_define.md.UA-ygUnQ.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.js +8 -0
- package/docs/.vitepress/dist/assets/api_directives.md.BV-D251p.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_globals.md.CEznyRAY.js +3 -0
- package/docs/.vitepress/dist/assets/api_globals.md.CEznyRAY.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_index.md.IEYUxUIr.js +1 -0
- package/docs/.vitepress/dist/assets/api_index.md.IEYUxUIr.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.js +14 -0
- package/docs/.vitepress/dist/assets/api_lifecycle.md.Ccm5xw6-.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.js +10 -0
- package/docs/.vitepress/dist/assets/api_route.md.CAHf_KNp.lean.js +1 -0
- package/docs/.vitepress/dist/assets/api_vite-plugin.md.DC8Li09k.js +13 -0
- package/docs/.vitepress/dist/assets/api_vite-plugin.md.DC8Li09k.lean.js +1 -0
- package/docs/.vitepress/dist/assets/app.BfblNDJy.js +1 -0
- package/docs/.vitepress/dist/assets/chunks/@localSearchIndexroot.Crdp7-Zp.js +1 -0
- package/docs/.vitepress/dist/assets/chunks/VPLocalSearchBox.C18E44rY.js +9 -0
- package/docs/.vitepress/dist/assets/chunks/framework.B7OFBR9X.js +19 -0
- package/docs/.vitepress/dist/assets/chunks/theme.VX3itTW6.js +2 -0
- package/docs/.vitepress/dist/assets/examples_form.md.DQoAgbLR.js +34 -0
- package/docs/.vitepress/dist/assets/examples_form.md.DQoAgbLR.lean.js +1 -0
- package/docs/.vitepress/dist/assets/examples_index.md.CVJJjXXE.js +28 -0
- package/docs/.vitepress/dist/assets/examples_index.md.CVJJjXXE.lean.js +1 -0
- package/docs/.vitepress/dist/assets/examples_routing.md.sRnA5RXw.js +338 -0
- package/docs/.vitepress/dist/assets/examples_routing.md.sRnA5RXw.lean.js +1 -0
- package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DPf9Wm99.js +13 -0
- package/docs/.vitepress/dist/assets/examples_sfc-showcase.md.DPf9Wm99.lean.js +1 -0
- package/docs/.vitepress/dist/assets/examples_todo-app.md.CqF4JaWn.js +297 -0
- package/docs/.vitepress/dist/assets/examples_todo-app.md.CqF4JaWn.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CjIjusre.js +182 -0
- package/docs/.vitepress/dist/assets/guide_cdn-usage.md.CjIjusre.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_components.md.CMU3iM6R.js +174 -0
- package/docs/.vitepress/dist/assets/guide_components.md.CMU3iM6R.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_contributing.md.Crrv3T_0.js +1 -0
- package/docs/.vitepress/dist/assets/guide_contributing.md.Crrv3T_0.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_directives.md.DFwqvqOv.js +140 -0
- package/docs/.vitepress/dist/assets/guide_directives.md.DFwqvqOv.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_getting-started.md.DtaJPe0i.js +107 -0
- package/docs/.vitepress/dist/assets/guide_getting-started.md.DtaJPe0i.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_index.md.DtJVpLI9.js +2 -0
- package/docs/.vitepress/dist/assets/guide_index.md.DtJVpLI9.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_lifecycle.md.CfY3jlU1.js +304 -0
- package/docs/.vitepress/dist/assets/guide_lifecycle.md.CfY3jlU1.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_quick-start.md.CwdNNA21.js +33 -0
- package/docs/.vitepress/dist/assets/guide_quick-start.md.CwdNNA21.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_reactivity.md.DgTH0MTn.js +135 -0
- package/docs/.vitepress/dist/assets/guide_reactivity.md.DgTH0MTn.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_routing.md.nMB0QOBR.js +193 -0
- package/docs/.vitepress/dist/assets/guide_routing.md.nMB0QOBR.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_sfc.md.BUkWma1z.js +187 -0
- package/docs/.vitepress/dist/assets/guide_sfc.md.BUkWma1z.lean.js +1 -0
- package/docs/.vitepress/dist/assets/guide_templating.md.XI3uUlYI.js +119 -0
- package/docs/.vitepress/dist/assets/guide_templating.md.XI3uUlYI.lean.js +1 -0
- package/docs/.vitepress/dist/assets/index.md.M4_o26kF.js +23 -0
- package/docs/.vitepress/dist/assets/index.md.M4_o26kF.lean.js +1 -0
- package/docs/.vitepress/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/docs/.vitepress/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/docs/.vitepress/dist/assets/style.eycE2Jhw.css +1 -0
- package/docs/.vitepress/dist/examples/form.html +58 -0
- package/docs/.vitepress/dist/examples/index.html +52 -0
- package/docs/.vitepress/dist/examples/routing.html +362 -0
- package/docs/.vitepress/dist/examples/sfc-showcase.html +37 -0
- package/docs/.vitepress/dist/examples/todo-app.html +321 -0
- package/docs/.vitepress/dist/guide/cdn-usage.html +206 -0
- package/docs/.vitepress/dist/guide/components.html +198 -0
- package/docs/.vitepress/dist/guide/contributing.html +25 -0
- package/docs/.vitepress/dist/guide/directives.html +164 -0
- package/docs/.vitepress/dist/guide/getting-started.html +131 -0
- package/docs/.vitepress/dist/guide/index.html +26 -0
- package/docs/.vitepress/dist/guide/lifecycle.html +328 -0
- package/docs/.vitepress/dist/guide/quick-start.html +57 -0
- package/docs/.vitepress/dist/guide/reactivity.html +159 -0
- package/docs/.vitepress/dist/guide/routing.html +217 -0
- package/docs/.vitepress/dist/guide/sfc.html +211 -0
- package/docs/.vitepress/dist/guide/templating.html +143 -0
- package/docs/.vitepress/dist/hashmap.json +1 -0
- package/docs/.vitepress/dist/index.html +47 -0
- package/docs/.vitepress/dist/logo.svg +38 -0
- package/docs/.vitepress/dist/vp-icons.css +1 -0
- package/docs/api/define.md +31 -0
- package/docs/api/directives.md +42 -0
- package/docs/api/globals.md +29 -0
- package/docs/api/index.md +29 -0
- package/docs/api/lifecycle.md +40 -0
- package/docs/api/route.md +37 -0
- package/docs/api/vite-plugin.md +58 -0
- package/docs/examples/form.md +42 -0
- package/docs/examples/index.md +104 -0
- package/docs/examples/routing.md +409 -0
- package/docs/examples/sfc-showcase.md +34 -0
- package/docs/examples/todo-app.md +383 -0
- package/docs/guide/cdn-usage.md +320 -0
- package/docs/guide/components.md +394 -0
- package/docs/guide/contributing.md +32 -0
- package/docs/guide/directives.md +430 -0
- package/docs/guide/getting-started.md +233 -0
- package/docs/guide/index.md +88 -0
- package/docs/guide/lifecycle.md +493 -0
- package/docs/guide/quick-start.md +46 -0
- package/docs/guide/reactivity.md +394 -0
- package/docs/guide/routing.md +373 -0
- package/docs/guide/sfc.md +381 -0
- package/docs/guide/templating.md +383 -0
- package/docs/index.md +126 -0
- package/docs/public/logo.svg +17 -0
- package/examples/vite-app/README.md +71 -0
- package/examples/vite-app/index.html +49 -0
- package/examples/vite-app/package.json +16 -0
- package/examples/vite-app/src/components/greeting-card.lego +41 -0
- package/examples/vite-app/src/components/sample-component.lego +75 -0
- package/examples/vite-app/src/components/todo-list.lego +242 -0
- package/examples/vite-app/src/main.js +11 -0
- package/examples/vite-app/vite.config.js +17 -0
- package/examples.js +99 -0
- package/go.html +117 -0
- package/lego.js +2 -0
- package/main.js +41 -35
- package/package.json +39 -6
- package/parse-lego.js +119 -0
- package/parse-lego.test.js +107 -0
- package/vite-plugin.js +133 -0
- package/.ignore/auto.html +0 -135
- package/.ignore/test.html +0 -73
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# Components
|
|
2
|
+
|
|
3
|
+
Learn how to create and use components in Lego.
|
|
4
|
+
|
|
5
|
+
## What is a Component?
|
|
6
|
+
|
|
7
|
+
A component is a reusable, self-contained piece of UI with its own template, styles, and logic.
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<template b-id="user-badge">
|
|
11
|
+
<style>
|
|
12
|
+
self {
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: 0.5rem;
|
|
16
|
+
padding: 0.5rem 1rem;
|
|
17
|
+
background: #f0f0f0;
|
|
18
|
+
border-radius: 20px;
|
|
19
|
+
}
|
|
20
|
+
.avatar {
|
|
21
|
+
width: 32px;
|
|
22
|
+
height: 32px;
|
|
23
|
+
border-radius: 50%;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
26
|
+
|
|
27
|
+
<img class="avatar" src="{{ avatarUrl }}" alt="{{ name }}">
|
|
28
|
+
<span>{{ name }}</span>
|
|
29
|
+
</template>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Creating Components
|
|
33
|
+
|
|
34
|
+
### Method 1: HTML Templates
|
|
35
|
+
|
|
36
|
+
Define components directly in your HTML with `<template b-id>`:
|
|
37
|
+
|
|
38
|
+
```html
|
|
39
|
+
<template b-id="hello-world">
|
|
40
|
+
<h1>Hello {{ name }}!</h1>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<hello-world b-data="{ name: 'Alice' }"></hello-world>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Method 2: JavaScript
|
|
47
|
+
|
|
48
|
+
Use `Lego.define()` for programmatic component creation:
|
|
49
|
+
|
|
50
|
+
```js
|
|
51
|
+
Lego.define('hello-world', `
|
|
52
|
+
<h1>Hello {{ name }}!</h1>
|
|
53
|
+
`, {
|
|
54
|
+
name: 'Alice'
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Method 3: Single File Components (.lego)
|
|
59
|
+
|
|
60
|
+
With Vite, use `.lego` files:
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- hello-world.lego -->
|
|
64
|
+
<template>
|
|
65
|
+
<h1>Hello {{ name }}!</h1>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<script>
|
|
69
|
+
export default {
|
|
70
|
+
name: 'Alice'
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Component State
|
|
76
|
+
|
|
77
|
+
State is defined in the component's logic object:
|
|
78
|
+
|
|
79
|
+
```js
|
|
80
|
+
{
|
|
81
|
+
// Data properties
|
|
82
|
+
count: 0,
|
|
83
|
+
username: 'Alice',
|
|
84
|
+
items: ['apple', 'banana'],
|
|
85
|
+
|
|
86
|
+
// Methods
|
|
87
|
+
increment() {
|
|
88
|
+
this.count++;
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
addItem(item) {
|
|
92
|
+
this.items.push(item);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Access state in templates using `{{ }}`:
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<p>Count: {{ count }}</p>
|
|
101
|
+
<button @click="increment()">+1</button>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Passing Data
|
|
105
|
+
|
|
106
|
+
### Via b-data Attribute
|
|
107
|
+
|
|
108
|
+
```html
|
|
109
|
+
<user-card b-data="{
|
|
110
|
+
name: 'Bob',
|
|
111
|
+
email: 'bob@example.com',
|
|
112
|
+
role: 'admin'
|
|
113
|
+
}"></user-card>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Merging with Defaults
|
|
117
|
+
|
|
118
|
+
Component defaults are merged with `b-data`:
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
Lego.define('user-card', `...`, {
|
|
122
|
+
name: 'Guest', // Default
|
|
123
|
+
email: '', // Default
|
|
124
|
+
role: 'user' // Default
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```html
|
|
129
|
+
<!-- Only name is overridden -->
|
|
130
|
+
<user-card b-data="{ name: 'Alice' }"></user-card>
|
|
131
|
+
<!-- email and role use defaults -->
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Component Communication
|
|
135
|
+
|
|
136
|
+
### Parent → Child (Props)
|
|
137
|
+
|
|
138
|
+
Pass data via `b-data`:
|
|
139
|
+
|
|
140
|
+
```html
|
|
141
|
+
<child-component b-data="{ title: parentData.title }"></child-component>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Child → Parent (Events)
|
|
145
|
+
|
|
146
|
+
Use `$emit()` to dispatch custom events:
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<!-- Child component -->
|
|
150
|
+
<button @click="$emit('save', { id: 123 })">Save</button>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
// Parent listens
|
|
155
|
+
document.querySelector('child-component')
|
|
156
|
+
.addEventListener('save', (e) => {
|
|
157
|
+
console.log('Saved:', e.detail); // { id: 123 }
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Accessing Ancestors
|
|
162
|
+
|
|
163
|
+
Use `$ancestors()` to read parent component state:
|
|
164
|
+
|
|
165
|
+
```html
|
|
166
|
+
<!-- In nested component -->
|
|
167
|
+
<p>App title: {{ $ancestors('app-root').title }}</p>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
::: warning Read-Only
|
|
171
|
+
`$ancestors()` is for reading parent state, not mutating it.
|
|
172
|
+
:::
|
|
173
|
+
|
|
174
|
+
## Component Composition
|
|
175
|
+
|
|
176
|
+
### Nesting Components
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
<template b-id="app-layout">
|
|
180
|
+
<header>
|
|
181
|
+
<app-header></app-header>
|
|
182
|
+
</header>
|
|
183
|
+
<main>
|
|
184
|
+
<app-sidebar></app-sidebar>
|
|
185
|
+
<app-content></app-content>
|
|
186
|
+
</main>
|
|
187
|
+
</template>
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Using Slots
|
|
191
|
+
|
|
192
|
+
Standard Web Components slots work:
|
|
193
|
+
|
|
194
|
+
```html
|
|
195
|
+
<template b-id="card-container">
|
|
196
|
+
<div class="card">
|
|
197
|
+
<slot name="header"></slot>
|
|
198
|
+
<slot></slot>
|
|
199
|
+
<slot name="footer"></slot>
|
|
200
|
+
</div>
|
|
201
|
+
</template>
|
|
202
|
+
|
|
203
|
+
<!-- Usage -->
|
|
204
|
+
<card-container>
|
|
205
|
+
<h2 slot="header">Title</h2>
|
|
206
|
+
<p>Main content</p>
|
|
207
|
+
<button slot="footer">Action</button>
|
|
208
|
+
</card-container>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Shadow DOM
|
|
212
|
+
|
|
213
|
+
All components use Shadow DOM for style encapsulation.
|
|
214
|
+
|
|
215
|
+
### Benefits
|
|
216
|
+
|
|
217
|
+
✅ **Scoped Styles** - CSS doesn't leak in or out
|
|
218
|
+
✅ **No Naming Conflicts** - ID/class names are isolated
|
|
219
|
+
✅ **Composability** - Components work without side effects
|
|
220
|
+
|
|
221
|
+
### Styling the Host
|
|
222
|
+
|
|
223
|
+
Use `self` keyword (converts to `:host`):
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<style>
|
|
227
|
+
self {
|
|
228
|
+
display: block;
|
|
229
|
+
padding: 1rem;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
self:hover {
|
|
233
|
+
background: #f5f5f5;
|
|
234
|
+
}
|
|
235
|
+
</style>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Lifecycle
|
|
239
|
+
|
|
240
|
+
Components have three lifecycle hooks:
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
{
|
|
244
|
+
mounted() {
|
|
245
|
+
// Component added to DOM
|
|
246
|
+
this.fetchData();
|
|
247
|
+
},
|
|
248
|
+
|
|
249
|
+
updated() {
|
|
250
|
+
// State changed and re-rendered
|
|
251
|
+
console.log('New count:', this.count);
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
unmounted() {
|
|
255
|
+
// Component removed from DOM
|
|
256
|
+
clearInterval(this.timer);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
See [Lifecycle Hooks](/guide/lifecycle) for details.
|
|
262
|
+
|
|
263
|
+
## Best Practices
|
|
264
|
+
|
|
265
|
+
### 1. Keep Components Small
|
|
266
|
+
|
|
267
|
+
Each component should have a single responsibility.
|
|
268
|
+
|
|
269
|
+
✅ Good: `user-avatar`, `user-name`, `user-bio`
|
|
270
|
+
❌ Bad: `entire-user-profile-page`
|
|
271
|
+
|
|
272
|
+
### 2. Use Semantic Names
|
|
273
|
+
|
|
274
|
+
Name components after what they represent:
|
|
275
|
+
|
|
276
|
+
✅ Good: `product-card`, `search-bar`
|
|
277
|
+
❌ Bad: `blue-box`, `flex-container`
|
|
278
|
+
|
|
279
|
+
### 3. Avoid Deep Nesting
|
|
280
|
+
|
|
281
|
+
Keep component trees shallow (3-4 levels max):
|
|
282
|
+
|
|
283
|
+
```html
|
|
284
|
+
app-root
|
|
285
|
+
├── app-header
|
|
286
|
+
│ └── nav-menu
|
|
287
|
+
├── app-main
|
|
288
|
+
│ └── content-area
|
|
289
|
+
└── app-footer
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 4. Initialize State in mounted()
|
|
293
|
+
|
|
294
|
+
Fetch data or set up timers in `mounted()`:
|
|
295
|
+
|
|
296
|
+
```js
|
|
297
|
+
{
|
|
298
|
+
data: null,
|
|
299
|
+
mounted() {
|
|
300
|
+
this.fetchData();
|
|
301
|
+
},
|
|
302
|
+
async fetchData() {
|
|
303
|
+
this.data = await fetch('/api/data').then(r => r.json());
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### 5. Clean Up in unmounted()
|
|
309
|
+
|
|
310
|
+
Clear timers, remove listeners:
|
|
311
|
+
|
|
312
|
+
```js
|
|
313
|
+
{
|
|
314
|
+
timer: null,
|
|
315
|
+
mounted() {
|
|
316
|
+
this.timer = setInterval(() => this.tick(), 1000);
|
|
317
|
+
},
|
|
318
|
+
unmounted() {
|
|
319
|
+
clearInterval(this.timer);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Common Patterns
|
|
325
|
+
|
|
326
|
+
### Loading States
|
|
327
|
+
|
|
328
|
+
```html
|
|
329
|
+
<div b-if="loading">Loading...</div>
|
|
330
|
+
<div b-if="!loading && data">
|
|
331
|
+
<h2>{{ data.title }}</h2>
|
|
332
|
+
<p>{{ data.content }}</p>
|
|
333
|
+
</div>
|
|
334
|
+
<div b-if="!loading && error">
|
|
335
|
+
Error: {{ error }}
|
|
336
|
+
</div>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Form Components
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
{
|
|
343
|
+
form: {
|
|
344
|
+
username: '',
|
|
345
|
+
email: '',
|
|
346
|
+
password: ''
|
|
347
|
+
},
|
|
348
|
+
errors: {},
|
|
349
|
+
|
|
350
|
+
validate() {
|
|
351
|
+
this.errors = {};
|
|
352
|
+
if (!this.form.username) {
|
|
353
|
+
this.errors.username = 'Required';
|
|
354
|
+
}
|
|
355
|
+
if (!this.form.email.includes('@')) {
|
|
356
|
+
this.errors.email = 'Invalid email';
|
|
357
|
+
}
|
|
358
|
+
return Object.keys(this.errors).length === 0;
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
submit() {
|
|
362
|
+
if (this.validate()) {
|
|
363
|
+
// Submit form
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Computed Values
|
|
370
|
+
|
|
371
|
+
Use methods for computed values:
|
|
372
|
+
|
|
373
|
+
```js
|
|
374
|
+
{
|
|
375
|
+
items: [
|
|
376
|
+
{ name: 'Apple', price: 1.20 },
|
|
377
|
+
{ name: 'Banana', price: 0.80 }
|
|
378
|
+
],
|
|
379
|
+
|
|
380
|
+
total() {
|
|
381
|
+
return this.items.reduce((sum, item) => sum + item.price, 0);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
```html
|
|
387
|
+
<p>Total: ${{ total().toFixed(2) }}</p>
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Next Steps
|
|
391
|
+
|
|
392
|
+
- Learn about [Reactivity](/guide/reactivity) in depth
|
|
393
|
+
- Explore [Templating](/guide/templating) features
|
|
394
|
+
- See [complete examples](/examples/)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Lego!
|
|
4
|
+
|
|
5
|
+
## Development Setup
|
|
6
|
+
|
|
7
|
+
1. Clone the repository:
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/rayattack/Lego.git
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Install dependencies:
|
|
13
|
+
```bash
|
|
14
|
+
yarn install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
3. Run the dev server for docs:
|
|
18
|
+
```bash
|
|
19
|
+
yarn docs:dev
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Pull Requests
|
|
23
|
+
|
|
24
|
+
1. Fork the repo and create your branch from `main`.
|
|
25
|
+
2. If you've added code that should be tested, add tests.
|
|
26
|
+
3. If you've changed APIs, update the documentation.
|
|
27
|
+
4. Ensure the test suite passes.
|
|
28
|
+
5. Make sure your code lints.
|
|
29
|
+
|
|
30
|
+
## License
|
|
31
|
+
|
|
32
|
+
By contributing, you agree that your contributions will be licensed under its MIT License.
|