Heim  >  Artikel  >  Web-Frontend  >  Wie implementiert man eine Zhihu-ähnliche Antwort- und Kommentarfunktion in Vue?

Wie implementiert man eine Zhihu-ähnliche Antwort- und Kommentarfunktion in Vue?

PHPz
PHPzOriginal
2023-06-25 16:19:221498Durchsuche

Vue ist ein sehr beliebtes Frontend-Framework. Aufgrund seiner Flexibilität und Benutzerfreundlichkeit wird es häufig in der Webentwicklung eingesetzt. Zhihu ist eine sehr beliebte Q&A-Community mit einer großen Benutzerbasis und umfangreichen Inhalten. In Zhihu ist die Kommentarfunktion unter Antworten sehr wichtig. In diesem Artikel erfahren Sie, wie Sie mit Vue Zhihu-ähnliche Antwort- und Kommentarfunktionen implementieren.

1. Funktionseinführung

In Zhihu können Benutzer unter den Antworten kommentieren. Kommentare können eine Baumstruktur bilden, in der jeder Knoten einen Kommentar darstellt und zwischen den Knoten eine Eltern-Kind-Beziehung besteht. Benutzer können unter jedem Knoten eigene Kommentare hinzufügen, die ebenfalls eine Baumstruktur bilden. Um Benutzern die Anzeige zu erleichtern, wird Zhihu auch Kommentare erweitern und verkleinern.

Das Folgende ist eine Liste der Funktionen, die in diesem Artikel implementiert werden müssen:

  1. Benutzer können unter Antworten Kommentare hinzufügen;
  2. Benutzer können unter jedem Knoten Kommentare hinzufügen; Kommentare nach Ebenen;
  3. Benutzer können Kommentare erweitern und verkleinern.
  4. 2. Datenstrukturdesign
  5. Bevor wir diese Funktion implementieren, müssen wir zuerst die Datenstruktur entwerfen. In Zhihu sind Kommentare eine Baumstruktur und jeder Knoten hat die folgenden Attribute:

id: die eindeutige Kennung des Knotens;

Inhalt: der Inhalt des Knotens;
  1. createTime: Knotenerstellungszeit;
  2. children: Liste der untergeordneten Knoten.
  3. Hier ist die Definition der Datenstruktur:
  4. interface Comment {
      id: string;
      content: string;
      author: string;
      createTime: number;
      children?: Comment[];
    }
  5. Für jede Antwort benötigen wir eine Liste mit Kommentaren. Da es mehrere Antworten geben kann, müssen wir diese Kommentarlisten in ein Objekt einfügen, damit die entsprechende Kommentarliste über die ID der Antwort abgerufen werden kann. Das Folgende ist die Definition der Datenstruktur:
  6. interface CommentData {
      [answerId: string]: Comment[];
    }
  7. 3. Implementierungsschritte

3.1 Kommentare anzeigen

Zuerst müssen wir die Kommentarliste anzeigen. Um eine Baumstruktur anzuzeigen, können wir rekursive Komponenten verwenden. Rekursive Komponenten bedeuten, dass die Komponente sich selbst in einer eigenen Vorlage aufrufen kann.

In Vue können Sie das Namensattribut der Komponente verwenden, um eine Rekursion zu implementieren. Hier ist eine einfache Komponente:

<template>
  <div>
    <div>{{ comment.content }}</div>
    <div v-if="comment.children">
      <comment v-for="c in comment.children" :key="c.id" :comment="c" />
    </div>
  </div>
</template>

<script>
export default {
  name: "comment",
  props: {
    comment: {
      type: Object,
      required: true,
    },
  },
};
</script>

Diese Komponente rendert alle untergeordneten Knoten rekursiv.

3.2 Kommentar hinzufügen

Beim Hinzufügen eines Kommentars müssen wir angeben, zu welchem ​​Knoten er hinzugefügt werden soll. Daher müssen wir jedem Knoten eine eindeutige Kennung hinzufügen. In diesem Beispiel verwenden wir UUID, um eine eindeutige Kennung zu generieren. Gleichzeitig speichern wir zur Vereinfachung der Bedienung auch die ID der Antwort, zu der sie in jedem Knoten gehört.

Wir können Vuex verwenden, um den Status zu verwalten. Der Vorgang zum Hinzufügen von Kommentaren ist wie folgt:

Der Benutzer gibt den Kommentarinhalt ein und wählt aus, zu welchem ​​Knoten er hinzugefügt werden soll.

löst die Vuex-Aktion aus, sendet eine Anfrage an den Server und fügt einen Kommentardatensatz auf dem Server hinzu.

Nachdem das Hinzufügen erfolgreich war, gibt der Server einen neuen Kommentardatensatz zurück.
  1. löst die Mutation von Vuex aus, um dem Status neue Kommentardatensätze hinzuzufügen.
  2. In der Komponente können wir die V-Model-Direktive verwenden, um den vom Benutzer eingegebenen Kommentarinhalt zu binden, und mit dem Element 221f08282418e2996498697df914ce4e auswählen, zu welchem ​​Knoten er hinzugefügt werden soll. Das Folgende ist ein Beispiel für eine Komponente:
  3. <template>
      <div>
        <div>
          <textarea v-model="content" />
        </div>
        <div>
          <select v-model="parentId">
            <option value="root">回答</option>
            <option :value="comment.id" v-for="comment in comments" :key="comment.id">
              {{ comment.content }}
            </option>
          </select>
        </div>
        <div>
          <button @click="addComment">添加评论</button>
        </div>
      </div>
    </template>
    
    <script>
    import { mapActions } from "vuex";
    
    export default {
      props: {
        answerId: {
          type: String,
          required: true,
        },
        comment: {
          type: Object,
          required: false,
          default: () => null,
        },
      },
      data() {
        return {
          content: "",
          parentId: "root",
          comments: [],
        };
      },
      created() {
        if (this.comment) {
          this.comments = this.comment.children || [];
        } else {
          this.comments = this.$store.state.comments[this.answerId] || [];
        }
      },
      methods: {
        ...mapActions("comments", ["addComment"]),
      },
    };
    </script>
  4. In dieser Komponente binden wir den vom Benutzer eingegebenen Inhalt und die ausgewählte übergeordnete Knoten-ID bidirektional an die Daten der Komponente. Gleichzeitig erhält die Komponente auch ein comment-Attribut. Wenn dieses Attribut vorhanden ist, bedeutet dies, dass die Komponente zu einem vorhandenen Kommentar hinzugefügt werden soll Kommentar unter der Antwort.
  5. In der Methode created der Komponente rufen wir die Liste der untergeordneten Knoten der Kommentare ab, die von der Komponente hinzugefügt werden sollen. Wenn die aktuelle Komponente zu einem vorhandenen Kommentar hinzugefügt werden soll, verwenden wir deren untergeordnete Knotenliste. Andernfalls erhalten wir die Kommentarliste der Antwort aus dem Vuex-Status.

In der addComment-Methode der Komponente können wir die Aktion von Vuex aufrufen, um einen neuen Kommentardatensatz zum Server hinzuzufügen: 221f08282418e2996498697df914ce4e元素来选择要添加到哪个节点下面。下面是一个组件的例子:

async addComment() {
  const { content, parentId } = this;
  const answerId = this.answerId;
  await this.addComment({ answerId, parentId, content });
  this.$emit("added");
}

在这个组件中,我们将用户输入的内容和选择的父节点id双向绑定到组件的data中。同时,该组件还接收一个comment属性,如果该属性存在,则表示该组件要添加到一个已有的评论下面;否则,该组件是要添加到回答下面的新评论。

在该组件的created方法中,我们检索该组件要添加的评论的子节点列表。如果当前组件是要添加到一个已有的评论下面,则使用它的子节点列表;否则,我们从Vuex的状态中获取所在回答的评论列表。

在组件的addComment方法中,我们可以调用Vuex的Action,来向服务器添加新的评论记录:

<template>
  <div>
    <div>
      <div>{{ comment.content }}</div>
      <div>
        <button @click="toggle"> {{ open ? "收起" : "展开" }} </button>
      </div>
    </div>
    <div v-if="open && comment.children">
      <comment v-for="subComment in comment.children" :key="subComment.id" :comment="subComment" />
    </div>
  </div>
</template>

<script>
export default {
  name: "comment",
  props: {
    comment: {
      type: Object,
      required: true,
    },
  },
  computed: {
    open() {
      return this.$store.state.expanded[this.comment.id];
    },
  },
  methods: {
    toggle() {
      this.$store.commit("toggle", this.comment.id);
    },
  },
};
</script>

在Action处理完毕后,我们触发added事件,以通知父组件刷新界面。

3.3 展开和收缩评论

展开和收缩评论是一项比较复杂的功能。需要记录每个节点的展开状态,并能够快速的获取所在节点和它的子节点。我们可以在Vuex的状态中记录每个节点的展开状态。

展开和收缩评论的流程如下:

  1. 用户点击展开或收缩;
  2. 触发Vuex的Mutation,更新对应节点的展开状态;
  3. 组件根据展开状态,递归地渲染子节点。

这个功能我们需要编写一个递归组件。组件会根据节点是否展开来决定是否渲染子节点。在该组件中,我们还需要编写一个展开和收缩按钮。下面是该组件的代码:

toggle(state, id) {
  state.expanded[id] = !state.expanded[id];
},

在该组件中,我们使用Vuex中的expandedrrreee

Nachdem die Aktion verarbeitet wurde, lösen wir das Ereignis added aus um die übergeordnete Komponente zu benachrichtigen, die Schnittstelle zu aktualisieren.

3.3 Kommentare erweitern und verkleinern🎜🎜Das Erweitern und Verkleinern von Kommentaren ist eine relativ komplexe Funktion. Es ist notwendig, den Erweiterungsstatus jedes Knotens aufzuzeichnen und den Knoten und seine untergeordneten Knoten schnell abzurufen. Wir können den Erweiterungsstatus jedes Knotens im Vuex-Status aufzeichnen. 🎜🎜Der Prozess zum Erweitern und Verkleinern von Kommentaren ist wie folgt: 🎜🎜🎜Der Benutzer klickt zum Erweitern oder Verkleinern; 🎜🎜löst Vuex's Mutation aus, um den Erweiterungsstatus des entsprechenden Knotens zu aktualisieren; 🎜🎜Die Komponente rendert die untergeordneten Knoten rekursiv den Ausbaustatus. 🎜🎜🎜Für diese Funktion müssen wir eine rekursive Komponente schreiben. Die Komponente entscheidet, ob untergeordnete Knoten gerendert werden, basierend darauf, ob der Knoten erweitert ist. In dieser Komponente müssen wir auch eine Schaltfläche zum Erweitern und Reduzieren schreiben. Das Folgende ist der Code der Komponente: 🎜rrreee🎜In dieser Komponente verwenden wir den Status expanded in Vuex, um aufzuzeichnen, ob jeder Knoten erweitert ist. In der berechneten Komponente verwenden wir diesen Zustand, um zu bestimmen, ob der aktuelle Knoten erweitert ist. In den Methoden der Komponente verwenden wir die Mutation von Vuex, um den erweiterten Zustand zu aktualisieren. 🎜🎜Die Verarbeitungslogik des Erweiterungszustands ist sehr einfach. Wir müssen nur den Erweiterungszustand des entsprechenden Knotens in Mutation umkehren: 🎜
toggle(state, id) {
  state.expanded[id] = !state.expanded[id];
},

4. 总结

本文介绍了如何使用Vue实现仿知乎的回答评论功能,包括评论的树形结构、添加评论、展开和收缩评论。Vue的组件、状态管理和递归组件等特性,为实现该功能提供了非常便利的支持。如果您想尝试实现仿知乎的回答评论功能,本文提供了非常好的参考。

Das obige ist der detaillierte Inhalt vonWie implementiert man eine Zhihu-ähnliche Antwort- und Kommentarfunktion in Vue?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn