首頁  >  文章  >  web前端  >  Vue 中如何實現仿知乎的回答評論功能?

Vue 中如何實現仿知乎的回答評論功能?

PHPz
PHPz原創
2023-06-25 16:19:221505瀏覽

Vue是一款非常受歡迎的前端框架,它的靈活性和易用性使得它在web開發中有著廣泛的應用。知乎是一個非常流行的問答社區,它擁有龐大的用戶群和豐富的內容。在知乎中,回答下的評論功能是非常重要的。在本文中,我們將探討如何使用Vue來實現仿知乎的回答評論功能。

1. 功能簡介

在知乎中,使用者可以在回答下進行評論。評論可以形成一個樹狀結構,其中每個節點表示一個評論,節點之間有父子關係。使用者可以在每個節點下方加入自己的評論,同樣會形成樹狀結構。為了方便用戶查看,知乎還會展開和縮小評論。

以下是本文需要實作的功能清單:

  1. 使用者可以在回答下新增註解;
  2. 註解可以形成樹狀結構;
  3. #用戶可以在每個節點下面添加評論;
  4. 根據層級展示評論;
  5. 用戶可以展開和收縮評論。

2. 資料結構設計

在實作此功能之前,我們需要先設計資料結構。在知乎中,註解是樹狀結構,每個節點都有以下屬性:

  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的Action,向伺服器發送請求,在伺服器中新增評論記錄;
  3. 新增成功後,伺服器傳回新的評論記錄;
  4. 觸發Vuex的Mutation,將新的評論記錄新增至狀態。

在元件中,我們可以使用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雙向綁定到元件的data。同時,該元件也接收一個comment屬性,如果該屬性存在,則表示該元件要新增到一個已有的評論下方;否則,該元件是要新增到回答下面的新評論。

在該元件的created方法中,我們檢索該元件要新增的註解的子節點清單。如果當前元件是要新增到一個已有的評論下面,則使用它的子節點清單;否則,我們從Vuex的狀態中取得所在回答的評論清單。

在元件的addComment方法中,我們可以呼叫Vuex的Action,來為伺服器新增新的評論記錄:

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

在Action處理完畢後,我們觸發added事件,以通知父元件刷新介面。

3.3 展開和收縮評論

展開和收縮評論是一項比較複雜的功能。需要記錄每個節點的展開狀態,並且能夠快速的取得所在節點和它的子節點。我們可以在Vuex的狀態中記錄每個節點的展開狀態。

展開與縮略評論的流程如下:

  1. 使用者點選展開或縮略;
  2. 觸發Vuex的Mutation,更新對應節點的展開狀態;
  3. 元件根據展開狀態,遞歸地渲染子節點。

這個功能我們需要寫一個遞迴元件。元件會根據節點是否展開來決定是否渲染子節點。在這個元件中,我們還需要編寫一個展開和收縮按鈕。以下是該元件的程式碼:

<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狀態來記錄每個節點是否展開。在元件的computed中,我們使用該狀態來判斷目前節點是否展開。在元件的methods中,我們使用Vuex的Mutation來更新展開狀態。

展開狀態的處理邏輯很簡單,我們只需要在Mutation中將對應的節點的展開狀態取反即可:

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

4. 总结

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

以上是Vue 中如何實現仿知乎的回答評論功能?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn