Vue intermediate

Vue router

client-seitiges Routing

client-seitiges Routing: Navigieren zwischen Ansichten, ohne die Anwendung zu verlassen

Client side routing

Möglichkeiten:

hash-basiertes Client-seitiges Routing, z.B.:

  • example.com/#/home
  • example.com/#/shop/cart

Client-seitiges Routing basierend auf dem History API, z.B.:

  • example.com/home
  • example.com/shop/cart

Für die zweite Option muss der Server zusätzlich konfiguriert werden

Routen-Konfiguration

// router/index.js

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
  {
    path: '/about',
    name: 'About',
    component: About,
  },
];

Grundlegende Komponenten

<router-link to="/">Home</router-link>
<router-view />

Ãœbergeben von Daten

Wir können Daten an die Route übergebn:

<router-view :todos="todos" />

Routenparameter

const routes = [
  {
    path: '/todos/:todoId',
    component: TodoDetailView,
  },
];

Zugriff auf die Parameter:

Details of todo: {{ $route.params.todoId }}

Navigation aus dem Code heraus

this.$router.push('/');

Styling von Links

aktive Links erhalten die Klasse router-link-active

Two-way Binding in eigenen Komponenten

Two-way Binding in eigenen Komponenten

(dies gilt für Vue 3)

Two-way Binding in eigenen Komponenten

two-way binding für inputs:

<input v-model="newTitle" />

Two-way Binding in eigenen Komponenten:

<star-rating v-model="productRating" />
<todo-item
  v-model:title="todo.title"
  v-model:completed="todo.completed"
/>

Two-way Binding in eigenen Komponenten

Implementierung von star-rating:

  • prop: modelValue
  • event: update:modelValue

Two-way Binding in eigenen Komponenten

Implementierung von todo-item:

  • props: title, completed
  • events: update:title, update:completed
<li>
  {{ completed ? "DONE: " : "TODO: " }}
  <input
    :value="title"
    @input="$emit('update:title', $event.target.value)"
    :style="{ border: 'none' }"
  />
  <button @click="$emit('update:completed', !completed)">
    toggle
  </button>
</li>

Prop-Types und Prop-Validierung

Prop-Types und Prop-Validierung

minimale Prop-Definition einer Komponente:

export default {
  props: ['title', 'completed'],
};

Prop-Types und Prop-Validierung

export default {
  props: {
    title: String,
    completed: Boolean,
  },
};

Prop-Types und Prop-Validierung

export default {
  props: {
    title: {
      type: String,
      required: true,
    },
    completed: {
      type: Boolean,
      default: false,
    },
  },
};

Vue und TypeScript

Vue und TypeScript

Einrichtung eines Vue-TypeScript-Projekts:

während der Projekterstellung mit Vue-CLI, wähle "Manually select features"

Vue und TypeScript

<script lang="ts">
  // ...
</script>

Vue und TypeScript

in Komponentendefnitionen:

export default {
  name: 'TodoApp',
  // ...
};

wird zu:

import { defineComponent } from 'vue';

export default defineComponent({
  name: 'TodoApp',
  // ...
});

Vue und TypeScript

Konfiguration von Vetur in VS Code:

Aktiviere die Option: Vetur > Experimental: Template Interpolation Service

Vue und TypeScript

Deklarieren der Struktur von Komponenten-State:

type ComponentState = {
  todos: Array<Todo>;
};
export default defineComponent({
  data(): ComponentState {
    // ...
  },
});

Vue und TypeScript

Definieren von Props mit TypeScript-Annotationen:

import { defineComponent, PropType } from 'vue';

// define interface / type "Todo" here

export default defineComponent({
  props: {
    type: [] as PropType<Array<Todo>>,
    required: true,
  },
});

Vue und TypeScript

nur Vue 3:

Definieren von Events und Event-Payloads (in Validierungsfunktionen):

export default defineComponent({
  emits: {
    /* eslint-disable @typescript-eslint/no-unused-vars */
    delete(id: number) {
      return true;
    },
    toggle(id: number) {
      return true;
    },
    /* eslint-enable @typescript-eslint/no-unused-vars */
  },
});

State Management mit VueX

State Management

In komplexeren Anwendungen oder Komponenten macht es Sinn, den Anwendungszustand (model) von der Ansicht (view) zu trennen.

Oft wird der gesamte Anwendungszustand durch ein Datenmodell repräsentiert. Jede Änderung am Anwendungszustand läuft über das Datenmodell.

State Management mit Mutationen

eine Mutation beschreibt ein bestimmtes Ereignis in einer Anwendung (in anderen Tools: Action)

Eine Mutation hat einen type, und eventuell eine payload-Property

State Management mit Mutationen

Beispiele für Mutationen, wie sie in den Devtools erscheinen:

{
  "type": "addTodo",
  "payload": {
    "title": "learn Vue"
  }
}
{
  "type": "deleteCompletedTodos"
}

Beispiel: Todos State Management

Manuelle Verwendung eines Vuex-Stores:

const store = new Vuex.Store({
  // set up store here
});

store.commit('addTodo', { title: 'foo' });
store.commit('addTodo', { title: 'bar' });
store.commit('setTodoCompleted', {
  id: 1,
  completed: true,
});
store.commit('deleteTodo', { id: 2 });

console.log(JSON.stringify(store.state));

State Management mit Vuex

Konfiguration von Vuex:

  • initialer State
  • Getters (ähnlich zu computed)
  • Muttionen (definieren State-Änderungen)
  • Actions (asynchrone Trigger von Mutationen)

State Management mit Vuex

const store = new Vuex.Store({
  state: { todos: [] },
  getters: {
    numIncomplete(state) {
      return state.todos.filter((t) => !t.completed).length;
    },
  },
  mutations: {
    addTodo(state, payload) {
      // ...
    },
    deleteTodo(state, payload) {
      // ...
    },
  },
  actions: {
    async loadFromApi(context) {
      // ...
    },
  },
});

Vuex und Vue

Verwenden eines Vuex-Stores in einer Vue-Anwendung:

new Vue({
  // ...
  store: store,
});

Der Store ist innerhalb von Komponenten als $store verfügbar

Vuex und Vue

Zugriff auf den Vuex-State aus Komponenten:

<todo-item v-for="todo in $store.state.todos" ... />
<p>Incomplete todos: {{ $store.getters.numIncomplete }}</p>

Vuex und Vue

Auslösen von Mutationen aus Vue:

<todo-item
  :todo="todo"
  @toggle="$store.commit('toggleTodo', { id: todo.id })"
  @delete="$store.commit('deleteTodo', { id: todo.id })"
/>

Vuex und Vue

Auslösen einer Action aus Vue:

export default {
  async created() {
    this.$store.dispatch('loadFromApi');
  },
};

Transitions

Transitions

Animation von Eingangs- oder Ausgangs- Transitions:

<transition name="fade">
  <button>delete</button>
</transition>

Name der Transition: fade

Transitions

Definition der fade-Transition:

während der Animation:

.fade-enter-active {
  transition: opacity 5s;
}
.fade-leave-active {
  transition: opacity 5s;
}

Styles für Anfang / Ende:

.fade-enter {
  opacity: 0;
}
.fade-leave-to {
  opacity 0;
}

Transition Groups

Transitions für Gruppen von Elementen, bei denen einzelne Elemente erscheinen oder verschwinden können

<transition-group name="list-fade" tag="ul">
  <li v-for="todo in todos" :key="todo.id">
    {{ todo.title }}
  </li>
</transition-group>

Transition Groups

.list-fade-enter-active,
.list-fade-leave-active {
  transition: opacity 0.5s;
}
.list-fade-enter,
.list-fade-leave-to {
  opacity: 0;
}

Transitions

Dokumentation: https://v3.vuejs.org/guide/transitions-overview.html

Render-Funktionen

Render-Funktionen

Konzept aus React: JSX - Kombination aus JavaScript und XML

Render-Funktionen können als Alternative zu Templates verwendet werden

Render-Funktionen

export default {
  name: 'Foo',
  render() {
    return (
      <div>
        foo
        <button>bar</button>
      </div>
    );
  },
};