ホームページ  >  記事  >  ウェブフロントエンド  >  Zhihu のような回答とコメント機能を Vue に実装するにはどうすればよいですか?

Zhihu のような回答とコメント機能を Vue に実装するにはどうすればよいですか?

PHPz
PHPzオリジナル
2023-06-25 16:19:221504ブラウズ

Vue は非常に人気のあるフロントエンド フレームワークであり、その柔軟性と使いやすさにより、Web 開発で広く使用されています。 Zhihu は、大規模なユーザー ベースと豊富なコンテンツを備えた非常に人気のある Q&A コミュニティです。 Zhihuでは、回答の下にあるコメント機能が非常に重要です。この記事では、Vue を使用して Zhihu のような回答およびコメント機能を実装する方法を検討します。

1. 機能の紹介

Zhihu では、ユーザーは回答の下にコメントを付けることができます。コメントはツリー構造を形成できます。各ノードはコメントを表し、ノード間には親子関係があります。ユーザーは各ノードの下に独自のコメントを追加でき、ツリー構造も形成されます。ユーザーが閲覧しやすいように、Zhihu はコメントを拡大および縮小することもできます。

次は、この記事で実装する必要がある機能のリストです:

  1. ユーザーは回答の下にコメントを追加できます;
  2. コメントはツリー構造を形成できます;
  3. ユーザーは各ノードの下にコメントを追加できます;
  4. 階層に従ってコメントを表示します;
  5. ユーザーはコメントを展開および縮小できます。

2. データ構造の設計

この機能を実装する前に、まずデータ構造を設計する必要があります。 Zhihu では、コメントはツリー構造になっており、各ノードには次の属性があります:

  1. id: ノードの一意の識別子;
  2. content: ノードのコンテンツ。
  3. author: ノードの作成者;
  4. createTime: ノードの作成時間;
  5. children: 子ノードのリスト。

データ構造の定義は次のとおりです:

interface Comment {
  id: string;
  content: string;
  author: string;
  createTime: number;
  children?: Comment[];
}

各回答には、コメントのリストが必要です。複数の回答がある可能性があるため、回答の ID によって対応するコメント リストを取得できるように、これらのコメント リストをオブジェクトに入れる必要があります。データ構造の定義は次のとおりです:

interface CommentData {
  [answerId: string]: Comment[];
}

3. 実装手順

3.1 コメントの表示

最初にコメント リストを表示する必要があります。ツリー構造を表示するには、再帰コンポーネントを使用できます。再帰コンポーネントとは、コンポーネントが独自のテンプレート内でそれ自体を呼び出すことができることを意味します。

Vue では、コンポーネントの name 属性を使用して再帰を実装できます。これは単純なコンポーネントです:

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

このコンポーネントはすべての子ノードを再帰的にレンダリングします。

3.2 コメントの追加

コメントを追加するときは、コメントを追加するノードを指定する必要があります。したがって、各ノードに一意の識別子を追加する必要があります。この例では、UUID を使用して一意の識別子を生成します。同時に、操作の便宜のために、それが属する回答の ID も各ノードに保存します。

Vuex を使用して状態を管理できます。コメントを追加するプロセスは次のとおりです:

  1. ユーザーはコメントの内容を入力し、コメントを追加するノードを選択します;
  2. Vuex のアクションをトリガーし、サーバーにリクエストを送信し、サーバー レコードにコメントを追加します。
  3. 追加が成功すると、サーバーは新しいコメント レコードを返します。
  4. Vuex のミューテーションをトリガーして、新しいコメント レコードを状態に追加します。

コンポーネントでは、v-model ディレクティブを使用してユーザーが入力したコメントの内容をバインドし、221f08282418e2996498697df914ce4e 要素を使用してどのノードを選択するかを選択できます。に追加してください。以下はコンポーネントの例です。

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

このコンポーネントでは、ユーザーが入力したコンテンツと選択した親ノード ID をコンポーネントのデータに双方向にバインドします。同時に、コンポーネントは comment 属性も受け取ります。この属性が存在する場合、コンポーネントが既存のコメントに追加されることを意味し、そうでない場合、コンポーネントは新しいコメントに追加されることを意味します答えの下にあります。

コンポーネントの created メソッドでは、コンポーネントによって追加されるコメントの子ノードのリストを取得します。現在のコンポーネントを既存のコメントに追加する場合は、その子ノード リストを使用します。それ以外の場合は、Vuex 状態から回答のコメント リストを取得します。

コンポーネントの addComment メソッドでは、Vuex のアクションを呼び出して、新しいコメント レコードをサーバーに追加できます。

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

アクションが処理された後、## をトリガーします。 #added イベントは、親コンポーネントにインターフェースを更新するよう通知します。

3.3 コメントの展開と縮小

コメントの展開と縮小は、比較的複雑な機能です。各ノードの拡張状況を記録し、ノードとその子ノードを迅速に取得する必要があります。 Vuex 状態の各ノードの拡張ステータスを記録できます。

コメントの展開と縮小のプロセスは次のとおりです:

    ユーザーをクリックして展開または縮小します;
  1. Vuex のミューテーションをトリガーし、コメントの展開ステータスを更新します。対応するノード;
  2. コンポーネントは、展開された状態に基づいて子ノードを再帰的にレンダリングします。
この関数では、再帰コンポーネントを作成する必要があります。コンポーネントは、ノードが展開されているかどうかに基づいて、子ノードをレンダリングするかどうかを決定します。このコンポーネントでは、展開ボタンと折りたたみボタンも記述する必要があります。以下はコンポーネントのコードです:

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

このコンポーネントでは、Vuex の

expanded 状態を使用して、各ノードが展開されているかどうかを記録します。計算コンポーネントでは、この状態を使用して現在のノードが展開されているかどうかを判断します。コンポーネントのメソッドでは、Vuex の Mutation を使用して展開された状態を更新します。

展開状態の処理ロジックは非常に単純で、Mutation:

で対応するノードの展開状態を反転するだけです。

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

4. 总结

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

以上がZhihu のような回答とコメント機能を Vue に実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。