Folien: http://bit.ly/wjax-2019-spa
https://twitter.com/_developit/status/1139252558369828865?s=19
const template = `
<input id="in">
<p><span id="log">, World
<input id="btn" type="button" value="Clear">`
class MyElement extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = template;
this.input = this.shadowRoot.querySelector("#in");
this.log = this.shadowRoot.querySelector("#log");
this.button = this.shadowRoot.querySelector("#btn");
}
connectedCallback() {
this.input.addEventListener("keyup", event => this.model = event.target.value);
this.button.addEventListener("click", event => this.model = "");
}
set model(value) {
this.log.textContent = value;
this.input.value = value;
}
}
customElements.define('my-element', MyElement);
// usage from html file
<script src="./my-element.js"></script>
<my-element></my-element>
https://lit-element.polymer-project.org/
@customElement('my-element')
class MyElement extends LitElement {
@property() greeting: string = 'Hello';
render() {
return html`
<input value="${this.greeting}"
@keyup="${(event: any) => this.greeting = event.target.value}">
<p>${this.greeting}, World</p>
<input type="button" value="Clear" @click="${this.handleClick}">`;
}
handleClick() {
this.greeting = '';
}
}
// using the web component (like before)
<script type="module" src="./my-element-pure.js"></script>
<my-element greeting="Hiho"></my-element>
// we can use properties or attributes for greeting
const greeter = document.querySelector('my-element')
greeter.greeting = 'Hi'
// Leaf Dumb Component
@Component({
selector: 'app-button',
template: ``
})
export class ButtonComponent {
@Input() private title = '';
@Output() send = new EventEmitter();
}
// Container Dumb Component
@Component({
selector: 'app-container',
template: `
`
})
export class Container {
@Output() send = new EventEmitter();
}
// Usage from Smart Component
// Dumb component
function Button(props) {
return <button onClick={props.onClick}>{props.label}</button>
}
function SearchField(props) {
const [search, setSearch] = React.useState("");
return <div>
<input value={search} onChange={e => setSearch(e.target.value)} />
<Button label="Search" onClick={() => props.onSearch(search);} />
<Button label="Clear" onClick={() =>setSearch("")/>
</div>
function SearchApp() {
const [result, setResult] = React.useState(null)
function doSearch(s) { /* do search, then */ setResult(searchResult); }
return <div className="Layout">
<SearchField onSearch={s => runSearch(s)} />
<SearchResult result={searchResult} />
</div>
}
// Button.vue (Dumb Component)
<template>
<button @click="$emit('on:click')">{{label}}</button>
</template>
<script>
export default {
name: "Button",
props: ["label"]
};
</script>
<style scoped>
button {
padding: 1rem;
}
</style>
// SearchField.vue
<template>
<div id="search-field">
<input v-model="searchString" />
<Button @on:click="search" label="Search" />
<Button @on:click="clear" label="Clear" />
</div>
</template>
<script>
export default {
name: "search-field",
components: { Button },
data() {
return { searchString: "" }
},
methods: {
search() { this.$emit("search", this.searchString); },
clear() { this.searchString = ""; }
}
};
</script>
<style scoped>
input, button {
padding: 1rem;
}
</style>