Vue.js ToDo-List Tutorial

25.02.2021 Ricky Elfner
Mobile vuejs foss javascript frontend framework handson tutorial howto

Für dieses Tutorial gehen wir davon aus, dass Sie bereits erste Erfahrung mit Vue.js haben und wissen, wie eine Applikation mit verschiedenen Komponenten aufgebaut wird. Falls Sie sich nicht ganz sicher sind, können Sie zuvor unseren Blog Beitrag zu den Grundlagen in Vue.js lesen. In diesem werden die Grundlagen für dieses Tutorial erklärt .

Erstellen des Projekts

Über das Terminal öffnen Sie den Ordner, in dem die App erstellt werden soll. Dort führen Sie das Command aus, um das Projekt zu erstellen. Für dieses Tutorial können die Standardeinstellungen von Vue.js übernommen werden.

$ vue create vue-todo-app

Falls Sie ebenfalls dieses Tutorial mit VS Code durch führen möchten, können Sie zum Starten den Befehl code . nutzen. Für unsere ToDo-Liste können Sie zunächst einmal die Standardkomponente HelloWorld.vue, sowie die standardmässigen Bilddateien und den gesamten Code in App.vue löschen. Im Anschluss sollten Sie nur noch das Grundgerüst einer Komponente haben.

<template>
  <div id="app">
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</script>

<style>

</style>

Erstellen der Komponenten

Dasselbe Grundgerüst verwenden Sie am besten gleich als Vorlage für alle Komponenten, die Sie für eine ToDo-Liste benötigen. Natürlich mit dem Unterschied, dass der Name entsprechend der Komponente umbenannt werden muss. Für unsere App benötigen wir drei Komponenten. ToDoItem.vue, welches die einzelnen Items in der ToDo-Liste abbildet. Dann benötigen Sie noch die Liste ToDos.vue, welche die Items enthält. Und zum Schluss benötigen Sie noch eine Komponente für den Button AddToDoButton.vue.

Die Liste

Der Komponente ToDos.vue können Sie gleich eine Überschrift hinzufügen, damit Sie diese Komponente anschliessend in der App importieren können und dabei auch erkennen, dass es wie gewollt funktioniert.

// ToDos.vue
<template>
    <div>
        <h1>Meine To-Do-Liste</h1>
    </div>
</template>

In der App.vue Komponente können Sie nun die ToDos.vue Komponente importieren und auch direkt verwenden. Für den initialen Zustand Ihrer ToDo-Liste können Sie auch gleich innerhalb des <script>-Abschnitts Daten durch ein Array bestimmen. Das Einbinden der Daten kommt einen Schritt später.

// App.vue
<template>
    <div id="app">
        <ToDos />
    </div>
</template>

<script>
    import ToDos from './components/ToDos'

    export default {
    name: 'App',
    components: {
    ToDos
    },
    data() {
        return {
            todoEntries: [
                {
                    id: 1,
                    title: 'Infos sammeln',
                    completed: false
                },
                {
                    id: 2,
                    title: 'Test Projekt erstellen',
                    completed: false
                },
                {
                    id: 3,
                    title: 'Blog Beitrag schreiben',
                    completed: false
                },
                ],
            }
        },
    }
</script>

Da Sie nun die ToDo-Einträge auch verwenden wollen, müssen Sie dies der ToDos.vue Komponente übergeben. Damit die Komponente auch weis, dass sie dies als Properties entgegennehmen kann, müssen Sie dies in dem Export Statement festlegen. In dem gleichen Schritt importieren Sie auch noch die ToDoItem.vue Komponente.

//ToDos.vue
<script>
import ToDoItem from "./ToDoItem";

export default {
  name: 'ToDos',
  components: {
      ToDoItem
  },
  props: [
      "todoEntries"
  ]
}
</script>

Im darauffolgenden Schritt müssen Sie die zuvor bestimmen Properties nun auch zum Übergeben der Einträge nutzen. Dazu verwenden Sie innerhalb App.vue die Direkte v-bind, um das Array zu übergeben.

    //App.vue
    <ToDos v-bind:todoEntries="todoEntries"/>

Das Item

Um nun die Einträge dieser Liste auch anzuzeigen, müssen Sie über das Array Loopen und jedes Mal die Komponente ToDoItem.vue aufrufen. Hierfür müssen wir jedoch zunächst einmal definieren, dass ToDoItemüber die Properties ein ToDo-Eintrag entgegennimmt und den Titel davon anzeigt.

// ToDoItem.vue
<template>
  <div>
    {{ todoItem.title }}
  </div>
</template>

<script>

export default {
  name: 'ToDoItem',
  components: {
  },props: [
    "todoItem"
  ]
}

Innerhalb der ToDos.vue Komponente erstellen Sie nun eine Liste mithilfe der Direktive v-for. Dies entspricht einer For-Schleife. Um jeden Eintrag später genau zu erkennen, legen Sie noch einen Key fest, welcher der Id eines Eintrags entspricht. Auch hierzu wird die v-bind Direktive verwendet. Anschliessend können Sie in Ihrem Browser bereits all Ihre initialen Einträge sehen.

// ToDos.vue
<template>
  <div>
      <h1>Meine To-Do-Liste</h1>
      <ul>
          <li v-bind:key="item.id" v-for="item in todoEntries">
              <ToDoItem v-bind:todoItem="item" />
          </li>   
      </ul>
  </div>
</template>

Hinzufügen von Einträgen

Nun benötigen Sie selbstverständlich auch noch ein Input Feld, sowie einen Button um neue To-Do's der Liste hinzuzufügen. Dafür legen Sie ein Formular an, welches auf das Event Submit reagiert, welches durch den Button getriggert wird. Sobald dieses Event eintrifft, wird die Methode addToDo aufgerufen. Mittels dem two-way-binding, welches man üblicherweise aus anderen JavaScript Frameworks kennt, werden unsere Daten mit den Eingaben des Input Felds abgeglichen. Dies geschieht durch die Direktive v-model.

//AddToDoButton.vue
<template>
  <div>
    <form @submit="addToDo">
      <input type="text" v-model="title" name="title">
      <button type="submit">Hinzufügen</button>
    </form>
  </div>
</template>

Danach benötigen Sie noch die Implementation der Funktion addToDo. Hierbei müssen Sie als Erstes festlegen, dass das Event nicht das Standardverhalten eines Submits durchführt. Stattdessen, wollen wir nämlich die Daten in unser Array toDoEintries innerhalb der App.vue Komponente weitergeben. Dafür müssen Sie zunächst ein neues ToDo-Item erstellen. Für die Id greifen wir auf ein Package namens uuid zurück. Hiermit ist es möglich, automatisch zufällige Ids zu erstellen. Sollten Sie dieses Package noch nicht installiert haben, können Sie dies über Ihr Terminal in Ihrem Root-Verzeichnis machen.

$ nmp install uuid;

Nun können Sie die Funktion verwenden, um eine Id für das neue Item zu erstellen. Für den Titel benutzen Sie den Inhalt des Input-Felds. Den Zustand completedsetzen Sie standardmässig auf false. Danach müssen Sie wieder ein Custom-Event erstellen, auf das zugegriffen werden kann und zusätzlich das neu erstellte Item übergibt. In dem folgenden Beispiel handelt es sich um das Event add-todo-event. Wichtig daran zu denken, den Inhalt des Input Felds wieder zu leeren.

<script>

    import { v4 as uuidv4 } from 'uuid';

    export default {
    name: 'AddToDoButton',
    data() {
        return {
            title: ''
        }
    },
    methods: {
        addToDo(event){
            event.preventDefault();
        
            const newToDoObject = {
                id: uuidv4(),
                title: this.title,
                completed: false
            }
            
            this.$emit("add-todo-event", newToDoObject);
            this.title= '';
        }
    }
}
</script>

Damit Sie die letzte Komponente auch verwenden können, müssen Sie diese wie gewohnt in der Komponente App.vue importieren. Des Weiteren soll die Komponente, auf das zuvor erstelle Event „lauschen" und sobald es getriggert wird, eine Methode addToDoItem ausführen. Dies wird mit @dd-todo-event definiert.

// App.vue
    <template>
      <div id="app">
        <ToDos v-bind:todoEntries="todoEntries"/>
        <AddToDoButton @add-todo-event="addToDoItem"/>
      </div>
    </template>

Dabei nimmt die Methode addToDoItem das neue Item als Parameter entgegen. Mithilfe der Spread-Syntax wird das entgegengenommene Objekt dem Array hinzugefügt.

  methods: {
    addToDoItem(newToDoItem) {
      this.todoEntries = [...this.todoEntries, newToDoItem];
    }
  },

Einträge als erledigt markieren

Typischerweise möchte man auch die Möglichkeit haben, die Einträge in einer ToDo-Liste als erledigt zu markieren. Hierfür fügen wir dem ToDoItem.vue die Klasse completedhinzu, je nachdem ob completed true oder false ist. Dieser Zustand ändert sich durch die Methode markComplete, welche durch das Event Click aufgerufen wird.

// ToDoItem.vue
    <template>
      <div v-bind:class="{ 'completed' : todoItem.completed }">
        <p @click="markComplete">{{ todoItem.title }}</p>
      </div>
    </template>

Die Methode invertiert dabei einfach den Zustand von dem Attribute completed.

  methods: {
    markComplete(){
      this.todoItem.completed = !this.todoItem.completed
    }
  }

Die letzte Anpassung ist nun noch die Styleanpassung für die Klasse completed.

    <style>
      .completed {
        text-decoration: line-through;
      }
    </style>

Löschen von Einträgen

Zu guter Letzt können Sie die Löschfunktion für einzelne Einträge der Liste implementieren. Dies funktioniert ähnlich wie das Erstellen eines neuen Objekts, nur müssen hier die Daten über zwei Komponenten weitergegeben werden. Dafür fügen wir einen Button der Komponente ToDoItem.vue hinzu. Dieser erstellt direkt ein Custom-Event und übergibt die Id weiter nach oben, sobald dieser geklickt wird.

//ToDoItem.vue
    <button @click="$emit('delete-todo-event', todoItem.id)">Löschen</button>

Als Nächstes müssen Sie dieses Event in der Komponente ToDos.vue entgegennehmen und mittels weiterem Event ebenfalls nach oben weiter geben, damit die Id innerhalb der App.vue Komponente weiterverarbeitet werden kann. Auch dieses Mal können Sie dies direkt per Inline Schreibweise erledigen.

//ToDos.vue
    <ToDoItem v-bind:todoItem="item" @delete-todo-event="$emit('delete-todo-event', item.id)"/>

Schliesslich und endlich haben Sie die Id an dem gewünschten Ort. Dieses Mal nutzen Sie am besten wieder einen Methodenaufruf, sobald das Event delete-todo-event getriggert wird.

    <ToDos v-bind:todoEntries="todoEntries" @delete-todo-event="deleteToDoItem"/>

In unserem Beispiel wird die Methode delteToDoItem aufgerufen und nimmt die Id als Parameter entgegen. Innerhalb der Methode wird das Array mit allen Items neu zusammen gesetzt, welche nicht die gleiche Id haben als die Parameter Variable.

  methods: {
    addToDoItem(newToDoItem) {
      this.todoEntries = [...this.todoEntries, newToDoItem];
    },
    deleteToDoItem(toDoId){
      this.todoEntries = this.todoEntries.filter(item => item.id !== toDoId)
    }
  },

Herzlichen Glückwunsch! Sie haben nun Ihre erste eigene ToDo-Liste mittels Vue.js erstellt.

Ricky Elfner – Denker, Überlebenskünstler, Gadget-Sammler. Dabei ist er immer auf der Suche nach neuen Innovationen, sowie Tech News, um immer über aktuelle Themen schreiben zu können.