feat: remove attach-effect
This commit is contained in:
parent
d41affd709
commit
9ead44babe
12 changed files with 2135 additions and 681 deletions
13
README.md
13
README.md
|
@ -52,9 +52,9 @@ The result is a reactive UI on property changes.
|
|||
|
||||
## Project Status
|
||||
|
||||
It is ready for many cases we see people use custom elements for. If you have a cool project built on **WebComponent.io** we'd love to know! :)
|
||||
It is ready for many simple cases we see people use custom elements for. If you have a cool project built on **WebComponent.io** we'd love to know! :)
|
||||
|
||||
For building some advanced interactions, we have a few issues that are still open: [#24 smart diffing](https://github.com/ayoayco/web-component-base/issues/24) & [#4 attachEffect improvements](https://github.com/ayoayco/web-component-base/issues/4)
|
||||
For building advanced interactions, we have an in-progress work on smart diffing to prevent component children being wiped on interaction.
|
||||
|
||||
In the mean time, if you have some complex needs, we recommend using the `WebComponent` base class with a more mature rendering approach like `lit-html`... and here's a demo for that: [View on CodePen ↗](https://codepen.io/ayoayco-the-styleful/pen/ZEwNJBR?editors=1010).
|
||||
|
||||
|
@ -91,15 +91,13 @@ You can import everything separately, or in a single file each for the main expo
|
|||
```js
|
||||
// all in a single file
|
||||
|
||||
import { WebComponent, html, attachEffect } from 'web-component-base'
|
||||
import { WebComponent, html } from 'web-component-base'
|
||||
|
||||
// in separate files
|
||||
|
||||
import { WebComponent } from 'web-component-base/WebComponent.js'
|
||||
|
||||
import { html } from 'web-component-base/html.js'
|
||||
|
||||
import { attachEffect } from 'web-component-base/attach-effect.js'
|
||||
```
|
||||
|
||||
### Utilities
|
||||
|
@ -221,7 +219,6 @@ Some feature-specific demos:
|
|||
1. [Using dynamic style objects](https://codepen.io/ayoayco-the-styleful/pen/bGzXjwQ?editors=1010)
|
||||
1. [Using the Shadow DOM](https://codepen.io/ayoayco-the-styleful/pen/VwRYVPv?editors=1010)
|
||||
1. [Using tagged templates in your vanilla custom element](https://codepen.io/ayoayco-the-styleful/pen/bGzJQJg?editors=1010)
|
||||
1. [Using attachEffect (experimental)](https://codepen.io/ayoayco-the-styleful/pen/ExrdWPv?editors=1011)
|
||||
|
||||
## `template` vs `render()`
|
||||
|
||||
|
@ -448,9 +445,9 @@ class ClickableText extends WebComponent {
|
|||
|
||||
All the functions and the base class in the library are minimalist by design and only contains what is needed for their purpose.
|
||||
|
||||
As of v2.0.0, the main export (with `WebComponent` + `html` + `attachEffect`) is 1.7 kB (min + gzip) according to [bundlephobia.com](https://bundlephobia.com/package/web-component-base@2.0.0), and the `WebComponent` base class is just 1.1 kB (min + brotli) according to [size-limit](http://github.com/ai/size-limit).
|
||||
As of v3, the main export (with `WebComponent` + `html`) is 1.7 kB (min + gzip) according to [bundlephobia.com](https://bundlephobia.com/package/web-component-base@2.0.0), and the `WebComponent` base class is just 1.08 kB (min + brotli) according to [size-limit](http://github.com/ai/size-limit).
|
||||
|
||||
There is an increase in size compared to that of before this release, primarily because of advanced features (e.g., effects, html tagged templates, and props blueprints) in building complex applications.
|
||||
There is an increase in size compared to that of before this release, primarily because of advanced features (e.g., html tagged templates, and props blueprints) in building complex applications.
|
||||
|
||||
## Inspirations and thanks
|
||||
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
// @ts-check
|
||||
import { WebComponent, attachEffect, html } from '../../src/index.js'
|
||||
export class Counter extends WebComponent {
|
||||
static props = {
|
||||
count: 0,
|
||||
}
|
||||
|
||||
onInit() {
|
||||
attachEffect(this.props.count, (count) => console.log(count))
|
||||
}
|
||||
|
||||
afterViewInit() {
|
||||
attachEffect(this.props.count, (count) => console.log(count + 100))
|
||||
}
|
||||
|
||||
get template() {
|
||||
return html`<button onclick=${() => ++this.props.count} id="btn">
|
||||
${this.props.count}
|
||||
</button>`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('my-counter', Counter)
|
|
@ -1,24 +0,0 @@
|
|||
// @ts-check
|
||||
import { WebComponent, attachEffect, html } from '../../src/index.js'
|
||||
|
||||
export class Decrease extends WebComponent {
|
||||
static props = {
|
||||
count: 999,
|
||||
}
|
||||
|
||||
onInit() {
|
||||
attachEffect(this.props.count, (count) => console.log(count))
|
||||
}
|
||||
|
||||
afterViewInit() {
|
||||
attachEffect(this.props.count, (count) => console.log(count + 100))
|
||||
}
|
||||
|
||||
get template() {
|
||||
return html`<button onclick=${() => --this.props.count} id="btn">
|
||||
${this.props.count}
|
||||
</button>`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('my-decrement', Decrease)
|
|
@ -1,15 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>WC demo</title>
|
||||
<script type="module" src="./Counter.mjs"></script>
|
||||
<script type="module" src="./Decrease.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Attach Effect Test</h1>
|
||||
<my-counter></my-counter>
|
||||
<my-decrement></my-decrement>
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
@ -14,6 +15,7 @@
|
|||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>Counter: <my-counter></my-counter></div>
|
||||
<div>Toggle: <my-toggle></my-toggle></div>
|
||||
|
@ -23,14 +25,20 @@
|
|||
<p id="display-panel"></p>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { attachEffect } from '../../src/index.js'
|
||||
const myObjectEl = document.querySelector('my-object')
|
||||
const objectProp = myObjectEl.props.object
|
||||
const displayPanelEl = document.querySelector('#display-panel')
|
||||
displayPanelEl.textContent = JSON.stringify(objectProp)
|
||||
attachEffect(objectProp, (object) => {
|
||||
displayPanelEl.textContent = JSON.stringify(object)
|
||||
})
|
||||
/**
|
||||
* TODO: fix using custom events
|
||||
*/
|
||||
|
||||
// import { attachEffect } from '../../src/index.js'
|
||||
// const myObjectEl = document.querySelector('my-object')
|
||||
// const objectProp = myObjectEl.props.object
|
||||
// const displayPanelEl = document.querySelector('#display-panel')
|
||||
// displayPanelEl.textContent = JSON.stringify(objectProp)
|
||||
// attachEffect(objectProp, (object) => {
|
||||
// displayPanelEl.textContent = JSON.stringify(object)
|
||||
// })
|
||||
// console.log(JSON.stringify(object))
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -101,5 +101,8 @@
|
|||
"path": "./dist/utils/get-kebab-case.js",
|
||||
"limit": "0.5 KB"
|
||||
}
|
||||
]
|
||||
],
|
||||
"dependencies": {
|
||||
"release-it": "^18.1.2"
|
||||
}
|
||||
}
|
||||
|
|
2375
pnpm-lock.yaml
2375
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -25,13 +25,6 @@ class FeatureSet extends WebComponent {
|
|||
'Use the built-in JSX-like syntax or bring your own custom templating',
|
||||
url: 'https://codepen.io/ayoayco-the-styleful/pen/ZEwNJBR?editors=1010',
|
||||
},
|
||||
{
|
||||
icon: '️🛜',
|
||||
title: 'Powerful.',
|
||||
description:
|
||||
"Attach 'side effects' that gets triggered on property value changes",
|
||||
url: '',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
symbols: '️✅';
|
||||
suffix: ' ';
|
||||
}
|
||||
|
||||
main {
|
||||
font-size: large;
|
||||
|
||||
|
@ -42,12 +43,14 @@
|
|||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
& code-block {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</my-head>
|
||||
|
||||
<body>
|
||||
<awesome-header>
|
||||
<span>{{ project.name }}</span>
|
||||
|
@ -78,10 +81,6 @@
|
|||
Use the built-in JSX-like syntax or bring your own custom
|
||||
templating
|
||||
</li>
|
||||
<li>
|
||||
Attach 'side effects' that gets triggered on property value
|
||||
changes
|
||||
</li>
|
||||
</ul>
|
||||
</feature-set>
|
||||
</div>
|
||||
|
@ -90,11 +89,8 @@
|
|||
<h2>Why use this base class?</h2>
|
||||
<p>
|
||||
Often times, when simple websites need a quick
|
||||
<a
|
||||
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Components/Using_custom_elements"
|
||||
target="_blank"
|
||||
>custom element</a
|
||||
>, the best way is still to create one extending from
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Components/Using_custom_elements"
|
||||
target="_blank">custom element</a>, the best way is still to create one extending from
|
||||
<code-block inline>HTMLElement</code-block>. However, it can quickly
|
||||
reach a point where writing the code from scratch can seem confusing
|
||||
and hard to maintain especially when compared to other projects with
|
||||
|
@ -136,20 +132,18 @@ export class Counter extends WebComponent {
|
|||
}
|
||||
}
|
||||
|
||||
customElements.define("my-counter", Counter);</pre
|
||||
>
|
||||
customElements.define("my-counter", Counter);</pre>
|
||||
</code-block>
|
||||
</section>
|
||||
</main>
|
||||
<my-footer>
|
||||
<small>
|
||||
<a href="https://ayco.io/sh/wcb/tree/main/site"
|
||||
>Website</a
|
||||
>
|
||||
<a href="https://ayco.io/sh/wcb/tree/main/site">Website</a>
|
||||
built with <a href="https://mcfly.js.org">McFly</a>.<br />
|
||||
Copyright © {{author.year}}
|
||||
<a href="{{ author.url }}">{{ author.name }}</a>.
|
||||
</small>
|
||||
</my-footer>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -20,7 +20,6 @@ export class WebComponent extends HTMLElement {
|
|||
#prevDOM
|
||||
#props
|
||||
#typeMap = {}
|
||||
#effectsMap = {}
|
||||
|
||||
/**
|
||||
* Array of strings that tells the browsers which attributes will cause a render
|
||||
|
@ -130,7 +129,6 @@ export class WebComponent extends HTMLElement {
|
|||
}
|
||||
|
||||
#handler(setter, meta) {
|
||||
const effectsMap = meta.#effectsMap
|
||||
const typeMap = meta.#typeMap
|
||||
|
||||
return {
|
||||
|
@ -141,12 +139,7 @@ export class WebComponent extends HTMLElement {
|
|||
typeMap[prop] = typeof value
|
||||
}
|
||||
|
||||
if (value.attach === 'effect') {
|
||||
if (!effectsMap[prop]) {
|
||||
effectsMap[prop] = []
|
||||
}
|
||||
effectsMap[prop].push(value.callback)
|
||||
} else if (typeMap[prop] !== typeof value) {
|
||||
if (typeMap[prop] !== typeof value) {
|
||||
throw TypeError(
|
||||
`Cannot assign ${typeof value} to ${
|
||||
typeMap[prop]
|
||||
|
@ -154,7 +147,6 @@ export class WebComponent extends HTMLElement {
|
|||
)
|
||||
} else if (oldValue !== value) {
|
||||
obj[prop] = value
|
||||
effectsMap[prop]?.forEach((f) => f(value))
|
||||
const kebab = getKebabCase(prop)
|
||||
setter(kebab, serialize(value))
|
||||
}
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/**
|
||||
* Attach a "side effect" function that gets triggered on property value changes
|
||||
* @param {Object} obj
|
||||
* @param {(newValue: any) => void} callback
|
||||
*/
|
||||
export function attachEffect(obj, callback) {
|
||||
const { proxy, prop } = Object.getPrototypeOf(obj)
|
||||
|
||||
proxy[prop] = {
|
||||
attach: 'effect',
|
||||
callback,
|
||||
}
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
export { attachEffect } from './attach-effect.js'
|
||||
export { WebComponent } from './WebComponent.js'
|
||||
export { html } from './html.js'
|
||||
|
|
Loading…
Reference in a new issue