You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js同路由下无需刷新页面更新评论的实现方案

问题描述

我开发了一个博客应用,添加评论功能后,必须硬刷新博客详情路由才能更新评论展示。以下是我的博客详情路由组件、评论添加组件、评论展示组件的代码,请问如何实现无需硬刷新页面即可更新评论?

博客详情路由组件代码

<template>
  <div>  
      <h3 class="pt-4"> {{blog.title}}</h3>
      <p class="pt-3">
        {{blog.description}}
      </p>
  <Review />
  <reviewSection/>
  </div>
</template>

<script>
import axios from "axios";
import Review from "../components/Review.vue";
import reviewSection from "../components/reviewSection.vue";
export default {
  components: {
  },
  data() {
    return {
      blog: []
    };
  },
  watch: {},
  created() {
 axios
      .get(`http://localhost:4000/api/blogs/${this.$route.params.id}`, {})
      .then(response => {
        this.blog = response.data.blog;
      })
      .catch(error => {
        console.log(error);
      });
  },

};
</script>

评论添加组件代码

<template>
              <div class="a-spacing-base">
                <textarea
                  placeholder="Add a comment"
                  v-model="body"
                ></textarea>
              </div>
            <div class="a-row text-right a-spacing-top-large">
              <button
                class="a-button-text btn"
                @click="onAddReview"
              >Submit</button>
            </div>
</template>

<script>
import axios from "axios";
export default {
  data() {
    return {
      body: "",
    };
  },
  methods: {
    async onAddReview() {
      try {
        var data = {
          body: this.body,
        };
        let response = await axios.post(
          `http://localhost:4000/api/reviews/${this.$route.params.id}`,
          data,
        );   
      } catch (err) {
        console.log(err);
      }
    }
  }
};
</script>

评论展示组件代码

<template>
  <div>
    <div
      v-for="review in reviews"
      :key="review._id"
      class="pt-3"
    >
      <div class="row">     
          <div class="pt-2">
            {{ review.body }}
          </div>
    </div>
  </div>
</template>

<script>
import axios from "axios";
export default {
  data(){
 return {
      reviews: null,
    };
  },
 watch: {
    "$route.params.id": {
      handler(newVal) {
        this.loadReviews(newVal);
      }
    }
  },
 methods: {
    loadReviews(id) {
      axios
        .get(`http://localhost:4000/api/reviews/${id}`, {})
        .then(response => {
         // console.log(response);
          this.reviews = response.data.reviews;
        })
        .catch(error => {
          console.log(error);
          error;
        });
    },
  }
};
</script>
解决方案

核心问题是评论提交后,评论展示组件无法感知新评论的生成,需要在提交成功后触发评论列表的更新。以下是三种可行方案:

方案一:事件总线跨组件通知更新

适合组件无直接父子关系的场景,通过全局事件总线传递更新信号。

  1. 全局注册事件总线
    在项目入口文件(如main.js)中添加:
Vue.prototype.$eventBus = new Vue()
  1. 修改评论添加组件
    提交成功后触发自定义事件,传递当前博客ID:
<script>
import axios from "axios";
export default {
  data() {
    return {
      body: "",
    };
  },
  methods: {
    async onAddReview() {
      try {
        var data = {
          body: this.body,
        };
        await axios.post(
          `http://localhost:4000/api/reviews/${this.$route.params.id}`,
          data,
        );   
        // 触发评论更新事件
        this.$eventBus.$emit('reviewAdded', this.$route.params.id)
        // 清空输入框
        this.body = ''
      } catch (err) {
        console.log(err);
      }
    }
  }
};
</script>
  1. 修改评论展示组件
    监听事件总线的更新信号,重新加载评论,并补充初始加载逻辑:
<script>
import axios from "axios";
export default {
  data(){
 return {
      reviews: null,
    };
  },
  created() {
    // 页面加载时初始化评论列表
    this.loadReviews(this.$route.params.id)
    // 监听评论更新事件
    this.$eventBus.$on('reviewAdded', (blogId) => {
      this.loadReviews(blogId)
    })
  },
  beforeDestroy() {
    // 销毁组件时移除监听,避免内存泄漏
    this.$eventBus.$off('reviewAdded')
  },
 watch: {
    "$route.params.id": {
      handler(newVal) {
        this.loadReviews(newVal);
      }
    }
  },
 methods: {
    loadReviews(id) {
      axios
        .get(`http://localhost:4000/api/reviews/${id}`, {})
        .then(response => {
          this.reviews = response.data.reviews;
        })
        .catch(error => {
          console.log(error);
        });
    },
  }
};
</script>

方案二:直接添加新评论到列表(无需重新请求)

如果后端返回新创建的评论数据,可直接将其插入前端列表,减少HTTP请求次数。

  1. 修改评论添加组件
    提交成功后传递新评论数据:
<script>
import axios from "axios";
export default {
  data() {
    return {
      body: "",
    };
  },
  methods: {
    async onAddReview() {
      try {
        var data = {
          body: this.body,
        };
        const response = await axios.post(
          `http://localhost:4000/api/reviews/${this.$route.params.id}`,
          data,
        );   
        // 假设后端返回的新评论在response.data.review中
        this.$eventBus.$emit('newReview', response.data.review)
        this.body = ''
      } catch (err) {
        console.log(err);
      }
    }
  }
};
</script>
  1. 修改评论展示组件
    监听新评论事件,直接添加到列表:
<script>
import axios from "axios";
export default {
  data(){
 return {
      reviews: [],
    };
  },
  created() {
    this.loadReviews(this.$route.params.id)
    this.$eventBus.$on('newReview', (newReview) => {
      this.reviews.push(newReview)
    })
  },
  beforeDestroy() {
    this.$eventBus.$off('newReview')
  },
 watch: {
    "$route.params.id": {
      handler(newVal) {
        this.loadReviews(newVal);
      }
    }
  },
 methods: {
    loadReviews(id) {
      axios
        .get(`http://localhost:4000/api/reviews/${id}`, {})
        .then(response => {
          this.reviews = response.data.reviews;
        })
        .catch(error => {
          console.log(error);
        });
    },
  }
};
</script>

方案三:父组件传递更新方法(父子通信)

利用博客详情组件作为父容器,直接调用子组件的更新方法。

  1. 修改博客详情组件
    注册子组件,添加ref引用并定义刷新方法:
<template>
  <div>  
      <h3 class="pt-4"> {{blog.title}}</h3>
      <p class="pt-3">
        {{blog.description}}
      </p>
  <!-- 绑定自定义事件 -->
  <Review @review-submitted="refreshReviews"/>
  <!-- 添加ref引用子组件 -->
  <reviewSection ref="reviewSection"/>
  </div>
</template>

<script>
import axios from "axios";
import Review from "../components/Review.vue";
import reviewSection from "../components/reviewSection.vue";
export default {
  // 注册子组件
  components: {
    Review,
    reviewSection
  },
  data() {
    return {
      blog: []
    };
  },
  created() {
 axios
      .get(`http://localhost:4000/api/blogs/${this.$route.params.id}`, {})
      .then(response => {
        this.blog = response.data.blog;
      })
      .catch(error => {
        console.log(error);
      });
  },
  methods: {
    refreshReviews() {
      // 调用评论展示组件的加载方法
      this.$refs.reviewSection.loadReviews(this.$route.params.id)
    }
  }
};
</script>
  1. 修改评论添加组件
    提交成功后触发父组件的自定义事件:
<script>
import axios from "axios";
export default {
  data() {
    return {
      body: "",
    };
  },
  methods: {
    async onAddReview() {
      try {
        var data = {
          body: this.body,
        };
        await axios.post(
          `http://localhost:4000/api/reviews/${this.$route.params.id}`,
          data,
        );   
        // 通知父组件刷新评论
        this.$emit('review-submitted')
        this.body = ''
      } catch (err) {
        console.log(err);
      }
    }
  }
};
</script>
  1. 修改评论展示组件
    补充初始加载逻辑:
<script>
import axios from "axios";
export default {
  data(){
 return {
      reviews: null,
    };
  },
  created() {
    // 页面初始化时加载评论
    this.loadReviews(this.$route.params.id)
  },
 watch: {
    "$route.params.id": {
      handler(newVal) {
        this.loadReviews(newVal);
      }
    }
  },
 methods: {
    loadReviews(id) {
      axios
        .get(`http://localhost:4000/api/reviews/${id}`, {})
        .then(response => {
          this.reviews = response.data.reviews;
        })
        .catch(error => {
          console.log(error);
        });
    },
  }
};
</script>
补充说明
  • 原博客详情组件未注册子组件,需在components选项中添加Review和reviewSection,否则组件无法正常渲染。
  • 原评论展示组件未在created钩子中加载初始评论,补充后才能确保进入页面时显示已有评论。

内容的提问来源于stack exchange,提问作者jibzy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:55:20