Skip to content

Commit 87e8572

Browse files
authored
Merge pull request #791 from Lemoncode/qwik-review
Qwik review
2 parents 484b991 + 38a4829 commit 87e8572

15 files changed

Lines changed: 131 additions & 39 deletions

File tree

04-frameworks/06-web-components/01-custom-element/readme.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,15 @@ If we inspect the developer tools we're able to see inside `search-bar`, the new
160160
background-color: #c7d0f8;
161161
}
162162
```
163+
164+
Update `index.html`
165+
166+
```diff
167+
<head>
168+
<meta charset="UTF-8">
169+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
170+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
171+
<title>Web Components</title>
172+
+ <link rel="stylesheet" href="style.css">
173+
</head>
174+
```

04-frameworks/06-web-components/03-custom-element-with-events/readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class SearchBar extends HTMLElement {
3737
container.appendChild(iconContainer);
3838
this.appendChild(container);
3939
/*diff*/
40-
this.dispacthMyEvent();
40+
this.dispatchMyEvent();
4141
/*diff*/
4242
}
4343

@@ -48,7 +48,7 @@ class SearchBar extends HTMLElement {
4848
return placeholder;
4949
}
5050
/*diff*/
51-
dispacthMyEvent() {
51+
dispatchMyEvent() {
5252
const myEvent = eventFact("myEvent", {
5353
bubbles: true, // [1]
5454
cancelable: false, // [2]

04-frameworks/06-web-components/05-shadow-root/readme.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Shadow Root
22

3-
An important aspect of custom elements is encapsulation, because a custom element, by definition, is a piece of reusable functionality: it might be dropped into any web page and be expected to work. So it's important that code running in the page should not be able to accidentally break a custom element by modifying its internal implementation. Shadow DOM enables you to attach a DOM tree to an element, and have the internals of this tree hidden from JavaScript and CSS running in the page.
3+
An important aspect of custom elements is encapsulation, because a custom element, by definition, is a piece of reusable functionality: it might be dropped into any web page and be expected to work. So it's important that code running in the page should not be able to accidentally break a custom element by modifying its internal implementation.
4+
5+
`Shadow DOM` enables you to attach a DOM tree to an element, and have the internals of this tree hidden from JavaScript and CSS running in the page.
46

57
## Step by step
68

04-frameworks/06-web-components/07-custom-element-extended/readme.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,23 @@ In order to make it work, we need to update `customElements.define` arguments:
2424
+customElements.define("search-bar", SearchBar, { extends: "div" });
2525
```
2626

27+
If we run our code now, we will notice that the error has gone. But the `search-bar` component, is not rendering. Well since we are exteding from `HTMLDivElement` we must refer as a `div` instead a custom element. For this purpose we can use the `is` attribute:
28+
29+
Update `index.html`
30+
31+
```diff
32+
<body style="font-family: Arial, Helvetica, sans-serif">
33+
<h1>Web Componentes</h1>
34+
<p>Custom Element</p>
35+
36+
<search-bar id="searchbar" ph="buscar..."></search-bar>
37+
+ <div is="search-bar"></div>
38+
<script type="module" src="searchbar.js"></script>
39+
<script type="module" src="main.js"></script>
40+
</body>
41+
```
42+
2743
## Reference
2844

29-
- https://dev.to/danieldekel/extending-native-elements-4h31
45+
- [Extending Native Elements](https://dev.to/danieldekel/extending-native-elements-4h31)
46+
- [Registering a custom element](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#registering_a_custom_element)

04-frameworks/06-web-components/08-life-cycle/readme.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ The DOM manipulation is something that we will align to `lifecycle callbacks`
66

77
## connectedCallback
88

9-
The connectedCallback method is run whenever your element gets attached to the document, either by the HTML parser or by any JavaScript that appends it to a parent element. This is where you probably want to put most of your actual setup code, but be aware that `connectedCallback` can be run multiple times if your element is moved around.
9+
The `connectedCallback` method is run whenever your element gets attached to the document, either by the HTML parser or by any JavaScript that appends it to a parent element. This is where you probably want to put most of your actual setup code, but be aware that `connectedCallback` can be run multiple times if your element is moved around.
1010

1111
Set up for HTML template and events.
1212

1313
## disconnectedCallback
1414

15-
As the name implies, this method gets called when your element is disconnected from the document. It's a good place to put any cleanup code: removing observers or event listeners that might have been added in `connectedCallback()`. Don't assume that this will be called once for each connectedCallback(), either before or after.
15+
As the name implies, this method gets called when your element is disconnected from the document. It's a good place to put any cleanup code: removing observers or event listeners that might have been added in `connectedCallback()`. Don't assume that this will be called once for each `connectedCallback()`, either before or after.
1616

1717
## attributeChangedCallback
1818

@@ -34,6 +34,20 @@ static get observedAttributes() {
3434

3535
### 1. Using `connectedCallback`
3636

37+
Update `index.html`
38+
39+
```diff
40+
<body style="font-family: Arial, Helvetica, sans-serif">
41+
<h1>Web Componentes</h1>
42+
<p>Custom Element</p>
43+
44+
<search-bar id="searchbar" ph="buscar..."></search-bar>
45+
- <div is="search-bar"></div>
46+
<script type="module" src="searchbar.js"></script>
47+
<script type="module" src="main.js"></script>
48+
</body>
49+
```
50+
3751
Update `searchbar.js`
3852

3953
```diff

04-frameworks/06-web-components/09-template-slot/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,4 @@ Update `index.html`
174174

175175
## References
176176

177-
- https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots
177+
- [Using Templates and Slots](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots)

04-frameworks/06-web-components/10-shadow-root-styling/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,4 @@ We can notice that is not taking any effect since is used **OUTSIDE** the Shadow
182182

183183
## References
184184

185-
- https://stackoverflow.com/questions/50999753/host-selector-not-working-for-custom-element-having-shadow-dom
185+
- [Host Selector not working Shadow DOM](https://stackoverflow.com/questions/50999753/host-selector-not-working-for-custom-element-having-shadow-dom)

04-frameworks/10-solid/3-LSP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Asumamos que nuestra clase base trabaja con una propiedad que es un int. Ahora,
141141

142142
- Postconditions can not be weakened in a subclass.
143143

144-
Asumamos el mismo escenario, pero en este caso la clase base garantiza que la propiedad sea positiva (no acepta números que no sean positivos en su setter). Y en este caso, la clase base sobreescribe el comportamiento del setter para que permita números negativos. Un código que use un getter de la propiedad asumiendo que siempre va a ser positivo (porque la clase base lo garantizaba) ahora estará roto debido a que se ha debilitado dicha restricción del getter.
144+
Asumamos el mismo escenario, pero en este caso la clase base garantiza que la propiedad sea positiva (no acepta números que no sean positivos en su setter). Y en este caso, la subclase sobreescribe el comportamiento del setter para que permita números negativos. Un código que use un getter de la propiedad asumiendo que siempre va a ser positivo (porque la clase base lo garantizaba) ahora estará roto debido a que se ha debilitado dicha restricción del getter.
145145

146146
## Ejemplo de precondiciones y postcondiciones
147147

04-frameworks/14-qwik/02-components/readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
Components are declared using [component$()](https://qwik.builder.io/docs/components/overview/#component) and at a minimum need to return a JSX Element.
66

7-
The trailing `$` allows the `Optimizer` to break the components into an application tree into a separate chunk so that each chunk can be loaded (or not loaded if it is not needed) independently.**Without the $ the component would be always loaded if the parent component needs to be loaded.**
7+
The trailing `$` allows the `Optimizer` to break the components into an application tree into a separate chunk so that each chunk can be loaded (or not loaded if it is not needed) independently. **Without the `$` the component would be always loaded if the parent component needs to be loaded.**
88

99
Update `qwik-app/src/routes/index.tsx`
1010

04-frameworks/14-qwik/03-events/readme.md

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Consider the following simplified HTML of the application below.
9191
- The `$` is a signal to the optimizer to extract the code for lazy-loading.
9292
- The `$` is a signal to you that lazy-loading "magic" happens at this point.
9393
- TypeScript rules ensure you don't skip any places where the `$` should appear.
94-
2. The optimizer looks for the $ and extracts the function wrapped by $ into a separate [lazy-loadable chunk](https://qwik.builder.io/docs/advanced/optimizer/).
94+
2. The optimizer looks for the `$` and extracts the function wrapped by `$` into a separate [lazy-loadable chunk](https://qwik.builder.io/docs/advanced/optimizer/).
9595
3. As the server renders the page, the JSX is executed and notices that there is a click listener. The click listener is serialized into the `<button>` element as `on:click` attribute. Qwik then knows how to hook this event back up on the client.
9696
4. Qwikloader scripts get inlined into HTML. The Qwikloader script sets up a global listener for all events in the browser. Qwikloader is about 1kb and executes in about 1ms.
9797
5. When a user clicks on the button, the Qwikloader intercepts the event and looks for an element with `on:click` attribute.
@@ -163,7 +163,13 @@ export default component$(() => {
163163
});
164164
```
165165

166-
We can see the confirmation dialog and immediately navigates to `GiTHub`. e wish to prevent this and call our callback instead. Add `preventdefault:click` to the `<a href>` to achieve this.
166+
Let's run the app:
167+
168+
```bash
169+
npm start
170+
```
171+
172+
We can see the confirmation dialog and immediately navigates to `GitHub`. We wish to prevent this and call our callback instead. Add `preventdefault:click` to the `<a href>` to achieve this.
167173

168174
Update `qwik-app/src/components/footer.component.tsx`
169175

@@ -208,7 +214,7 @@ export const Footer = component$(() => {
208214
event.preventDefault();
209215
window.open("https://github.com/lemoncode");
210216
};
211-
aHref.value!.addEventListener("click", handler);
217+
aHref.value?.addEventListener("click", handler);
212218
cleanup(() => aHref.value!.removeEventListener("click", handler));
213219
});
214220
return (
@@ -226,7 +232,45 @@ Qwik warns us what is going on:
226232

227233
![warning](./resources/02-warning.png)
228234

229-
Lets back to previous version just to remove the current warning:
235+
## `sync$()` Restriction (BETA)
236+
237+
Although it stills in BETA, it's the recommended way to handle code synchrounisly. The main issue with `$sync`, **can NOT close over anything**. What are the implications of this?
238+
239+
- access any state: The recommended way to get the state into function is to place on element attrbutes.
240+
- access any non-browser functions: No imports or closing over any variables or functions are allowed.
241+
- the function should be small as it will get inlined into the resulting HTML.
242+
243+
Because above reasons the recomendation is to breaking up event handlers into two parts:
244+
245+
1. **`sync$()`** The part which must be synchronous
246+
2. **`$()`** The part which can be asynchronous.
247+
248+
Update `qwik-app/src/components/footer.component.tsx`
249+
250+
```tsx
251+
import { component$, sync$, $ } from "@builder.io/qwik";
252+
253+
export const Footer = component$(() => {
254+
return (
255+
<a
256+
href="https://github.com/lemoncode"
257+
onClick$={[
258+
sync$((event: Event) => {
259+
event.preventDefault();
260+
}),
261+
$(() => {
262+
window.open("https://github.com/lemoncode");
263+
}),
264+
]}
265+
>
266+
Go To Lemonland
267+
</a>
268+
);
269+
});
270+
271+
```
272+
273+
Sadly, seems to not to be working... Lets back to first version just to remove the warning and make it work:
230274

231275
```tsx
232276
import { component$ } from "@builder.io/qwik";

0 commit comments

Comments
 (0)