引言

1. 项目准备

在开始之前,确保你已经安装了Vue.js。以下是创建一个Vue项目的简单步骤:

# 安装Vue CLI
npm install -g @vue/cli

# 创建新项目
vue create comment-system

# 进入项目目录
cd comment-system

# 安装依赖
npm install axios vuex

2. 数据结构与状态管理

// store.js
export default new Vuex.Store({
  state: {
    comments: []
  },
  mutations: {
    ADD_COMMENT(state, comment) {
      state.comments.push(comment);
    },
    ADD_REPLY(state, { commentId, reply }) {
      const comment = state.comments.find(c => c.id === commentId);
      comment.replies.push(reply);
    }
  },
  actions: {
    addComment({ commit }, comment) {
      commit('ADD_COMMENT', comment);
    },
    addReply({ commit }, { commentId, reply }) {
      commit('ADD_REPLY', { commentId, reply });
    }
  }
});

3. 评论组件

<template>
  <div>
    <div>
      <span>{{ comment.author }}</span>
      <span>{{ comment.content }}</span>
    </div>
    <div v-for="reply in comment.replies" :key="reply.id">
      <span>{{ reply.author }}</span>
      <span>{{ reply.content }}</span>
    </div>
    <div>
      <input v-model="newReply" placeholder="Add a reply..." />
      <button @click="addReply(comment.id)">Reply</button>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    comment: Object
  },
  data() {
    return {
      newReply: ''
    };
  },
  methods: {
    addReply(commentId) {
      this.$emit('add-reply', { commentId, reply: { author: 'User', content: this.newReply } });
      this.newReply = '';
    }
  }
};
</script>

4. 父组件

在父组件中,使用Comment组件并监听add-reply事件。

<template>
  <div>
    <comment
      v-for="comment in comments"
      :key="comment.id"
      :comment="comment"
      @add-reply="handleAddReply"
    />
  </div>
</template>

<script>
import Comment from './Comment.vue';
import { mapState, mapActions } from 'vuex';

export default {
  components: {
    Comment
  },
  computed: {
    ...mapState(['comments'])
  },
  methods: {
    ...mapActions(['addComment', 'addReply']),
    handleAddReply({ commentId, reply }) {
      this.addReply({ commentId, reply });
    }
  }
};
</script>

5. 总结