Mit welchem Framework soll ich meine Single-Page-App bauen?

WJAX, München, November 2019

Nils Hartmann / @nilshartmann
Oliver Zeigermann / @DJCordhose / embarc GmbH

Folien: http://bit.ly/wjax-2019-spa

Alle guten Dinge sind drei...?

https://twitter.com/_developit/status/1139252558369828865?s=19

Web Components


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>
### Sind Web Components immer prozedural und low-level?

lit-element, Nachfolger Polymer

https://lit-element.polymer-project.org/

Web Components mit lit-element


@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'
  

Code Sample


// 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          

            

Code Sample


          // 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>
                  }        
                  

Code Sample


// 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>            
          

Code Sample


// 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>        
    

Vielen Dank!

Mit welchem Framework soll ich meine Single-Page-App bauen? WJAX 2019

Nils Hartmann / @nilshartmann
Oliver Zeigermann / @DJCordhose / embarc GmbH

http://bit.ly/wjax-2019-spa

https://reactbuch.de