Vue.js 重新加载组件单页应用 (SPA)

huangapple go评论70阅读模式
英文:

vuejs reload component SPA

问题

我有一个用于在帖子上添加评论的功能。现在,当您在博客上添加新评论时,页面需要重新加载,以便您可以看到新添加的博客。

我现在使用location.reload(),但这会刷新整个页面,这不是我想要的。我该如何才能只刷新帖子?

我找到了this.$forceUpdate(),但这根本不会重新加载组件。

以下是我现在使用的文件以及我如何做到的,我删除了不必要的代码,如果你想知道为什么有些东西不见了。

我的容器视图:

<template>
    <main>
        <div class="container">
            <MainContainerItem v-for="blog in blogs" :blog="blog"/>
        </div>
    </main>
</template>

<script setup>
import MainContainerItem from './MainContainerItem.vue';
import axios from 'axios';
</script>

<script>
export default {
    name: "MainContainer",
    data() {
        return {
            'blogs': null,
        }
    },
    methods: {
        getAllBlogs() {
            axios.get('/api/blog')
                .then((response) => {
                    this.blogs = response.data.blogs;
                    console.log(this.blogs);
                })
                .catch((error) => {
                    console.warn(error);
                })
        },
    },
    mounted() {
        this.getAllBlogs();
    }
}
</script>

我的其他视图:

<template>
    <div class="blog__comments">  
        <div class="blog__comments__existingComment">   
            <div v-if="blog.comment !== null">
                <div v-for="comments in blog.comments">
                    <span class="blog__comments blog__comments__existingComment--text">{{comments.comment}}</span>
                </div>
            </div>
        </div>

        <div class="blog__comments__add">
            <img class="blog__comments blog__comments--profilePicture" :src="defaultProfilePicture">
            <input class="blog__comments blog__comments--text" type="text" v-model="comment" placeholder="Write comment...">
            <button @click="addComment()">Add comment</button>
        </div>
    </div>
</template>

<script>
import axios from 'axios';

export default {
    name: "MainContainerItem",
    methods: {
        /* 向博客添加评论 */
        addComment() {
            axios.post('/api/blog/posts/' + this.posts_id + '/comment', {
                'comment': this.comment,
                'user_id': this.user_id,
                'posts_id': this.posts_id
            })
            /* 重新加载页面 */
            .then((response) =>  {  
                console.log(response);
                /* 我尝试使用 this.$forceUpdate() */
                /* this.$forceUpdate(); */

                /* 使用当前的 location.reload() */
                location.reload();
                this.blog.id = response.data.id;
            })
            .catch(function (error) {  
                console.log(error);
            });
        },
    }
}
</script>

我的获取帖子和评论的函数:

public function getAllBlogs() : JsonResponse
{
    return response()->json([
        'blogs' => 
        Posts::with(['comments' => function ($query) {
            $query->with('user');
        }])
        ->get()
    ]);
}

希望这对您有所帮助,如果您有任何其他问题,请随时提问。

英文:

I have a function to add a comment to a post. Now when you add a new comment to a blog the page needs to reload so that you can see the new added blog.

I now use location.reload() but this refreshes the whole page which I don't want to happen. How can I make it so that I only refresh the post?

I found this.$forceUpdate() but this won't reload the component at all.

Here are the files I use and how I do it right now, I removed the unnecessary code for If youre wondering why somethings are missing.

my container view:

&lt;template&gt;
    &lt;main&gt;
        &lt;div class=&quot;container&quot;&gt;
            &lt;MainContainerItem v-for=&quot;blog in blogs&quot; :blog=&quot;blog&quot;/&gt;
        &lt;/div&gt;
        
    &lt;/main&gt;
&lt;/template&gt;

&lt;script setup&gt;
import MainContainerItem from &#39;./MainContainerItem.vue&#39;;
import axios from &#39;axios&#39;
&lt;/script&gt;


&lt;script&gt;
export default {
    name: &quot;MainContainer&quot;,
    data(){
        return {
            &#39;blogs&#39;: null,
        }
    },
    methods: {
        getAllBlogs(){
            axios.get(&#39;/api/blog&#39;)
                .then((response) =&gt; {
                    this.blogs = response.data.blogs
                    console.log(this.blogs)
                })
                .catch((error) =&gt; {
                    console.warn(error)
                })
        },
    },
    mounted(){
        this.getAllBlogs()
    }
}
&lt;/script&gt;

my other view:

&lt;template&gt;
        &lt;div class=&quot;blog__comments&quot;&gt;  
                &lt;div class=&quot;blog__comments__existingComment&quot;&gt;   
                    &lt;div v-if=&quot;blog.comment !== null&quot;&gt;
                        &lt;div v-for=&quot;comments in blog.comments&quot;&gt;
                            &lt;span class=&quot;blog__comments blog__comments__existingComment--text&quot;&gt;{{comments.comment}}&lt;/span&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                &lt;/div&gt;

            &lt;div class=&quot;blog__comments__add&quot;&gt;
                &lt;img class=&quot;blog__comments blog__comments--profilePicture&quot; :src=&quot;defaultProfilePicture&quot;&gt;
                &lt;input class=&quot;blog__comments blog__comments--text&quot; type=&quot;text&quot; v-model=&quot;comment&quot; placeholder=&quot;Write comment...&quot;&gt;
                &lt;button @click=&quot;addComment()&quot;&gt;Add comment&lt;/button&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/template&gt;


&lt;script&gt;
    import axios from &#39;axios&#39;
    export default {
        name: &quot;MainContainerItem&quot;,
        methods: {
            /* add a comment to a blog */
            addComment() {
			    axios.post(&#39;/api/blog/posts/&#39; + this.posts_id + &#39;/comment&#39;, {
                    &#39;comment&#39;: this.comment,
                    &#39;user_id&#39;: this.user_id,
                    &#39;posts_id&#39;: this.posts_id
				})
                 /* reload the page */
                 .then((response) =&gt;  {  
                    console.log(response)
                    /* my attempt with this.$forceUpdate() */
                    /* this.$forceUpdate(); */

                    /* with location.reload() how I have it now*/
                    location.reload();
                    this.blog.id = response.data.id 
                })
                .catch(function (error) {  
                    console.log(error);
                });
			},

        }
    }
&lt;/script&gt;

my function to get the posts + comments:

public function getAllBlogs() : JsonResponse
    {
        return response()-&gt;json([
            &#39;blogs&#39; =&gt; 
            Posts::with([&#39;comments&#39; =&gt; function ($query) {
                $query-&gt;with(&#39;user&#39;);
            }])
            -&gt;get()
        ]);
    }

答案1

得分: 1

不要有别的内容,只返回翻译好的部分:

"把握窍门是不要自己重新加载任何内容,而是通过响应性来更新数据,让 Vue 自己处理。"

"我认为在你的情况下,你可以简单地将新评论添加到博客中:"

addComment() {
  axios.post('/api/blog/posts/' + this.posts_id + '/comment', {...})
    .then((response) => {
      this.blog.comments.push({comment: this.comment})
    })
    ...
},      

"通常最好的做法是在保存后让服务返回评论数据,这样你会得到与加载时相同的数据(即服务器端添加了 ID 和其他数据)。然后你可以这样做:"

async addComment() {
  const url = '/api/blog/posts/' + this.posts_id + '/comment'
  const response = await axios.post(url, {...})
  this.blog.comments.push({comment: response.data})
},      

"另外,你也可以将创建的值发送到管理数据的父组件,或者将其全部放入存储器中。"

"这样做有意义吗?对你有用吗?"

英文:

The trick is to not reload anything yourself, but update the data and have Vue figure it out through reactivity.

I think in your case, you can just add the new comment to the blog:

addComment() {
  axios.post(&#39;/api/blog/posts/&#39; + this.posts_id + &#39;/comment&#39;, {...})
    .then((response) =&gt; {
      this.blog.comments.push({comment: this.comment})
    })
    ...
},      

It is usually good practice to have your service return the comment data after saving, so you get the same data you would get when loading it (i.e. with IDs and other data added on server side). Then you can do something like:

async addComment() {
  const url = &#39;/api/blog/posts/&#39; + this.posts_id + &#39;/comment&#39;
  const response = await axios.post(url, {...})
  this.blog.comments.push({comment: response.data})
},      

Alternatively, you could emit the created value to the parent component that manages the data or put it all into a store.

Does that make sense? Does it work for you?

答案2

得分: 1

不需要重新加载此页面吗?也许你应该只是将新添加的评论推送到你正在遍历的评论数组中?

你不能修改 props,所以你应该先将数据从 prop 移动到 data 变量中的 mounted 钩子。MainContainerItem 应该如下所示:

<template>
    <div class="blog__comments">  
        <div class="blog__comments__existingComment">   
          <div v-if="blog.comment !== null">
            <div v-for="comment in comments">
              <span class="blog__comments blog__comments__existingComment--text">{{comment.comment}}</span>
            </div>
          </div>
        </div>

      <div class="blog__comments__add">
        <img class="blog__comments blog__comments--profilePicture" :src="defaultProfilePicture">
        <input class="blog__comments blog__comments--text" type="text" v-model="comment" placeholder="Write comment...">
        <button @click="addComment()">Add comment</button>
      </div>
    </div>
</template>

<script>
  import axios from 'axios'
  export default {
    name: "MainContainerItem",
    data () {
      return {
        comments: []
      }
    },
    methods: {
      /* add a comment to a blog */
      addComment() {
        const newCommentData = {
          'comment': this.comment,
          'user_id': this.user_id,
          'posts_id': this.posts_id
        };
        axios.post('/api/blog/posts/' + this.posts_id + '/comment', newCommentData)
         .then((response) =>  {  
          this.comments.push(newCommentData)
          this.blog.id = response.data.id 
        })
        .catch(function (error) {  
          console.log(error);
        });
      },
    },
    mounted () {
      this.comments = this.blog.comments
    }
  }
</script>

注意:代码中的一些文本可能无法准确翻译,因为其中包含了特殊字符和代码标记。

英文:

Do you really need to reload this page? Maybe you should just push newly added comment to this comments array you are iterating through?

You can't modify props, so you should first move data from prop to data variable in mounted hook. Here is how MainContainerItem should look like:

&lt;template&gt;
&lt;div class=&quot;blog__comments&quot;&gt;  
&lt;div class=&quot;blog__comments__existingComment&quot;&gt;   
&lt;div v-if=&quot;blog.comment !== null&quot;&gt;
&lt;div v-for=&quot;comment in comments&quot;&gt;
&lt;span class=&quot;blog__comments blog__comments__existingComment--text&quot;&gt;{{comment.comment}}&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;blog__comments__add&quot;&gt;
&lt;img class=&quot;blog__comments blog__comments--profilePicture&quot; :src=&quot;defaultProfilePicture&quot;&gt;
&lt;input class=&quot;blog__comments blog__comments--text&quot; type=&quot;text&quot; v-model=&quot;comment&quot; placeholder=&quot;Write comment...&quot;&gt;
&lt;button @click=&quot;addComment()&quot;&gt;Add comment&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/template&gt;
&lt;script&gt;
import axios from &#39;axios&#39;
export default {
name: &quot;MainContainerItem&quot;,
data () {
return {
comments: []
}
},
methods: {
/* add a comment to a blog */
addComment() {
const newCommentData = {
&#39;comment&#39;: this.comment,
&#39;user_id&#39;: this.user_id,
&#39;posts_id&#39;: this.posts_id
};
axios.post(&#39;/api/blog/posts/&#39; + this.posts_id + &#39;/comment&#39;, newCommentData)
.then((response) =&gt;  {  
this.comments.push(newCommentData)
this.blog.id = response.data.id 
})
.catch(function (error) {  
console.log(error);
});
},
},
mounted () {
this.comments = this.blog.comments
}
}
&lt;/script&gt;

答案3

得分: 0

只需要将 location.reload() 更改为 this.$emit("refresh")

然后,将此代码更改为:

<MainContainerItem v-for="blog in blogs" :blog="blog" @refresh="getAllBlogs"/>
英文:

You just need to change location.reload() to this.$emit(&quot;refresh&quot;).

Then, change this code to:

&lt;MainContainerItem v-for=&quot;blog in blogs&quot; :blog=&quot;blog&quot; @refresh=&quot;getAllBlogs&quot;/&gt;

huangapple
  • 本文由 发表于 2023年3月10日 01:27:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/75688068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定