Experiments in Vue 3 Reactivity to build Custom Elements
Andrew Beng
github.com/andrewbeng89
andrewbeng89.me
andrew@factorial.io
Reactivity
Custom Elements
Experiment
Vue 3.x Reactivity TL;DR
- The "magic" behind Vue
- 2.x Vue.observable() now 3.x reactive()
- Uses ES6 Proxy (easy effects + optional read-only), no IE support
- Standalone package
import { reactive, effect } from
"https://unpkg.com/@vue/reactivity?module";
const state = reactive({
count: 0
});
effect(() => {
console.log(state.count);
// 0
// 1
});
const add = () => state.count++;
add();
... published as a package that can be used standalone
Reactivity
Custom Elements
Experiment
Custom Elements
Custom Elements - TL;DR
- Core Web Components feature
- Create new HTML tags
- Extend existing (built-in or custom) tags
- Creating reusable components with vanilla JS/HTML/CSS
Custom Elements
- in the Wild
- GitHub's Web Components collection
- Google Web Components
- PolymerElements
Custom Elements - Pros
- Standards based
- Interoperability
Custom Elements - Cons
- "Boilerplate" code (vanilla)
- MANY libraries/frameworks
- "Web Components are not Vue / React / <insert any framework> components"
Custom Elements
- Best Practices
- Create a shadow root to encapsulate styles
- Aim to keep primitive data attributes and properties in sync, reflecting from property to attribute, and vice versa.
- ... and many others
Reactivity
Custom Elements
Experiment
Evan You's vue-lit
Experiment goals
- Based on vue-lit (props + lifecycle hooks)
- Props validation
- Add a <slot> interface
- Testable
export default ({ name, setup, props }) => {
customElements.define(
name,
class extends HTMLElement {
static get observedAttributes() {
// Return a list of observed attribute names
}
constructor() {
// 1. Scaffold reactive props
// 2. Scaffold slots as reactive object
// 3. Apply effect to render the template + run hooks
}
connectedCallback() {
// 1. Run beforeMount hook
// 2. Render template + invoke setup()
// 3. Run mounted hook
// 4. Bind template slots to reactive object
// 5. Validate props
}
disconnectedCallback() {
// Run unmounted hook
}
attributeChangedCallback() {
// Parse, validate and update reactive props
}
}
);
}
import { defineComponent, reactive, html }
from "https://unpkg.com/vue-uhtml?module";
defineComponent({
name: "my-component",
setup: () => {
const state = reactive({
text: "hello"
});
const onInput = (e) => {
state.text = e.target.value;
};
return () => html`
<p>
<input value=${state.text} oninput=${onInput} />
<span>${state.text}</span>
</p>
`;
},
});
<my-component></my-component>
Testing
- Test defined Custom Elements
- @web/test-runner
- events, properties, lifecycle hooks
- Gotha: closed vs open shadowRoot
Take-aways
- Standalone reactivity is awesome
- Custom Elements aren't scary
- Get out there and experiment!
Experiments in Vue 3 Reactivity to build Custom Elements
By Andrew Beng
Experiments in Vue 3 Reactivity to build Custom Elements
Experiments in Vue 3 Reactivity to build Custom Elements
- 1,154